diff --git a/core/modules/rest/src/Plugin/rest/resource/UserLoginResource.php b/core/modules/rest/src/Plugin/rest/resource/UserLoginResource.php index 8cb06bf..1d75d62 100644 --- a/core/modules/rest/src/Plugin/rest/resource/UserLoginResource.php +++ b/core/modules/rest/src/Plugin/rest/resource/UserLoginResource.php @@ -45,13 +45,6 @@ class UserLoginResource extends ResourceBase { protected $userStorage; /** - * A logger instance. - * - * @var \Psr\Log\LoggerInterface - */ - protected $logger; - - /** * The Csrf Token Generator. * * @var \Drupal\Core\Access\CsrfTokenGenerator @@ -85,7 +78,6 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition $this->configFactory = $config_factory; $this->flood = $flood; $this->userStorage = $user_storage; - $this->logger = $logger; $this->csrfToken = $csrf_token; } @@ -98,7 +90,7 @@ public static function create(ContainerInterface $container, array $configuratio $plugin_id, $plugin_definition, $container->getParameter('serializer.formats'), - $container->get('logger.factory')->get('rest'), + $container->get('logger.channel.rest'), $container->get('config.factory'), $container->get('flood'), $container->get('entity.manager')->getStorage('user'), diff --git a/core/modules/rest/src/Plugin/rest/resource/UserLoginStatus.php b/core/modules/rest/src/Plugin/rest/resource/UserLoginStatus.php index 7a87c2d..daf98b0 100644 --- a/core/modules/rest/src/Plugin/rest/resource/UserLoginStatus.php +++ b/core/modules/rest/src/Plugin/rest/resource/UserLoginStatus.php @@ -2,6 +2,8 @@ namespace Drupal\rest\Plugin\rest\resource; +use Drupal\Core\Cache\Cache; +use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Session\AccountInterface; use Drupal\rest\Plugin\ResourceBase; use Drupal\rest\ResourceResponse; @@ -72,9 +74,12 @@ public static function create(ContainerInterface $container, array $configuratio */ public function get() { if ($this->currentUser->isAuthenticated()) { - return new ResourceResponse('You are logged in.', 200, []); + $response = new ResourceResponse('You are logged in.', 200, []); } - return new ResourceResponse('You are not logged in.', 200, []); + else { + $response = new ResourceResponse('You are not logged in.', 200, []); + } + return $response->addCacheableDependency((new CacheableMetadata())->setCacheMaxAge(0)); } } diff --git a/core/modules/rest/src/Tests/UserLoginTest.php b/core/modules/rest/src/Tests/UserLoginTest.php index a28c982..5c66aa0 100644 --- a/core/modules/rest/src/Tests/UserLoginTest.php +++ b/core/modules/rest/src/Tests/UserLoginTest.php @@ -58,7 +58,7 @@ public function testLogin() { ->save(); - $url = URL::fromRoute('rest.user_login_status.GET.json'); + $url = Url::fromRoute('rest.user_login_status.GET.json'); $url->setRouteParameter('_format', 'json'); $this->httpRequest($url, 'GET', NULL, 'application/json'); $this->assertResponseBody('200', '"You are not logged in."'); @@ -83,6 +83,7 @@ public function testLogin() { $response = $this->httpRequest('user_login', 'POST', json_encode($payload), 'application/json'); $response = json_decode($response); $this->assertEqual($name, $response->current_user->name, "The user name is correct."); + debug($this->cookies); $url = Url::fromRoute('rest.user_login_status.GET.json'); $url->setRouteParameter('_format', 'json'); diff --git a/core/modules/rest/tests/src/Unit/UserLoginResourceTest.php b/core/modules/rest/tests/src/Unit/UserLoginResourceTest.php index d7e2445..1d94a90 100644 --- a/core/modules/rest/tests/src/Unit/UserLoginResourceTest.php +++ b/core/modules/rest/tests/src/Unit/UserLoginResourceTest.php @@ -2,7 +2,9 @@ namespace Drupal\Tests\rest\Unit; +use Drupal\Core\Access\CsrfTokenGenerator; use Drupal\Core\DependencyInjection\ContainerBuilder; +use Drupal\Core\Flood\FloodInterface; use Drupal\rest\Plugin\rest\resource\UserLoginResource; use Drupal\Tests\UnitTestCase; @@ -23,7 +25,7 @@ class UserLoginResourceTest extends UnitTestCase { /** * The flood control mechanism. * - * @var \Drupal\Core\Flood\FloodInterface + * @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Flood\FloodInterface */ protected $flood; @@ -35,13 +37,6 @@ class UserLoginResourceTest extends UnitTestCase { protected $logger; /** - * A reflection of self::$translation. - * - * @var \ReflectionClass - */ - protected $reflection; - - /** * Config. * * @var \Drupal\Core\Config\Config @@ -49,13 +44,6 @@ class UserLoginResourceTest extends UnitTestCase { protected $config; /** - * The resource to be tested as a mock object. - * - * @var \PHPUnit_Framework_MockObject_MockBuilder - */ - protected $testClassMock; - - /** * The user storage. * * @var \Drupal\user\UserStorageInterface @@ -63,6 +51,11 @@ class UserLoginResourceTest extends UnitTestCase { protected $userStorage; /** + * @var + */ + protected $csrfToken; + + /** * {@inheritdoc} */ protected function setUp() { @@ -77,60 +70,21 @@ protected function setUp() { $container->set('user.auth', $user_auth_service); \Drupal::setContainer($container); - $this->flood = $this->getMock('\Drupal\Core\Flood\FloodInterface'); + $this->flood = $this->getMock(FloodInterface::class); $this->userStorage = $this->getMockBuilder('\Drupal\user\UserStorage') ->disableOriginalConstructor() ->getMock(); - $this->config = $this->getMockBuilder('\Drupal\Core\Config\ConfigFactory') - ->disableOriginalConstructor() - ->setMethods(['get']) - ->getMock(); - - $immutableConfig = $this->getMockBuilder('\Drupal\Core\Config\ConfigFactory') - ->disableOriginalConstructor() - ->setMethods(['get']) - ->getMock(); - - $this->config->expects($this->any()) - ->method('get') - ->will($this->returnValue($immutableConfig)); + $this->config = $this->getConfigFactoryStub([ + 'user.flood' => [], + ]); $this->logger = $this->getMock('Psr\Log\LoggerInterface'); - $this->testClass = new UserLoginResource([], 'plugin_id', '', [], $this->logger, $this->config, $this->flood, $this->userStorage); - - $this->testClassMock = $this->getMockBuilder('\Drupal\rest\Plugin\rest\resource\UserLoginResource') - ->setMethods(['restFloodControl', 'login', 'logout', 'post', 'userIsBlocked']) - ->setConstructorArgs([[], 'plugin_id', '', [], $this->logger, $this->config, $this->flood, $this->userStorage]) - ->getMock(); + $this->csrfToken = $this->prophesize(CsrfTokenGenerator::class); - $this->reflection = new \ReflectionClass($this->testClass); - } - - /** - * Gets a protected method from current class using reflection. - * - * @param string $method - * The requested method. - * - * @return mixed - * The protected method. - */ - public function getProtectedMethod($method) { - $method = $this->reflection->getMethod($method); - $method->setAccessible(TRUE); - - return $method; - } - - /** - * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException - * @expectedExceptionMessage No op found. Use: status, login, logout. - */ - public function testEmptyPayload() { - $this->testClass->post([]); + $this->testClass = new TestUserLoginResource([], 'plugin_id', '', [], $this->logger, $this->config, $this->flood, $this->userStorage, $this->csrfToken->reveal()); } /** @@ -138,24 +92,7 @@ public function testEmptyPayload() { * @expectedExceptionMessage Missing credentials. */ public function testMissingCredentials() { - $this->testClass->post(['op'=>'login']); - } - - /** - * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException - * @expectedExceptionMessage Unsupported op UnsuportedOp. - */ - public function testUnsupportedOp() { - $this->testClass->post(['op'=>'UnsuportedOp']); - } - - /** - * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException - * @expectedExceptionMessage Missing credentials. - */ - public function testLoginMissingCredentialName() { - $method = $this->getProtectedMethod('login'); - $method->invokeArgs($this->testClass, ['credentials' => []]); + $this->testClass->post([]); } /** @@ -163,8 +100,7 @@ public function testLoginMissingCredentialName() { * @expectedExceptionMessage Missing credentials.pass. */ public function testLoginMissingCredentialPass() { - $method = $this->getProtectedMethod('login'); - $method->invokeArgs($this->testClass, ['credentials' => ['name' => 'Druplicon']]); + $this->testClass->post(['name' => 'Druplicon']); } /** @@ -172,12 +108,11 @@ public function testLoginMissingCredentialPass() { * @expectedExceptionMessage Blocked. */ public function testLoginBlockedUserByFloodControl() { - $this->testClassMock->expects($this->once()) - ->method('restFloodControl') - ->will($this->returnValue(FALSE)); + $this->flood->expects($this->once()) + ->method('isAllowed') + ->willReturn(FALSE); - $method = $this->getProtectedMethod('login'); - $method->invokeArgs($this->testClassMock, ['credentials' => ['name' => 'Druplicon', 'pass' => 'SuperSecret']]); + $this->testClass->post(['name' => 'Druplicon', 'pass' => 'SuperSecret']); } /** @@ -185,16 +120,13 @@ public function testLoginBlockedUserByFloodControl() { * @expectedExceptionMessage The user has not been activated or is blocked. */ public function testLoginBlockedUser() { - $this->testClassMock->expects($this->once()) - ->method('restFloodControl') - ->will($this->returnValue(TRUE)); + $this->flood->expects($this->once()) + ->method('isAllowed') + ->willReturn(TRUE); - $this->testClassMock->expects($this->once()) - ->method('userIsBlocked') - ->will($this->returnValue(TRUE)); + $this->testClass->setUserIsBlocked(TRUE); - $method = $this->getProtectedMethod('login'); - $method->invokeArgs($this->testClassMock, ['credentials' => ['name' => 'Druplicon', 'pass' => 'SuperSecret']]); + $this->testClass->post(['name' => 'Druplicon', 'pass' => 'SuperSecret']); } /** @@ -202,16 +134,13 @@ public function testLoginBlockedUser() { * @expectedExceptionMessage Sorry, unrecognized username or password. */ public function testLoginUnrecognizedUsernameOrPassword() { - $this->testClassMock->expects($this->once()) - ->method('restFloodControl') - ->will($this->returnValue(TRUE)); + $this->flood->expects($this->once()) + ->method('isAllowed') + ->willReturn(TRUE); - $this->testClassMock->expects($this->once()) - ->method('userIsBlocked') - ->will($this->returnValue(FALSE)); + $this->testClass->setUserIsBlocked(FALSE); - $method = $this->getProtectedMethod('login'); - $method->invokeArgs($this->testClassMock, ['credentials' => ['name' => 'Druplicon', 'pass' => 'SuperSecret']]); + $this->testClass->post(['name' => 'Druplicon', 'pass' => 'SuperSecret']); } /** @@ -237,3 +166,27 @@ public function testResetPasswordNotRecognizedNameOrEmail() { } } +class TestUserLoginResource extends UserLoginResource { + + /** + * @var bool|null + */ + protected $blocked; + + public function setUserIsBlocked($blocked) { + $this->blocked = $blocked; + return $this; + } + + /** + * {@inheritdoc} + */ + protected function userIsBlocked($name) { + if (isset($this->blocked)) { + return $this->blocked; + } + + return parent::userIsBlocked($name); + } + +} diff --git a/core/modules/rest/tests/src/Unit/UserPasswordReset.php b/core/modules/rest/tests/src/Unit/UserPasswordReset.php new file mode 100644 index 0000000..e0fe4f1 --- /dev/null +++ b/core/modules/rest/tests/src/Unit/UserPasswordReset.php @@ -0,0 +1,82 @@ +getMock('Drupal\user\UserAuthInterface'); + $user_auth_service->expects($this->any()) + ->method('authenticate') + ->will($this->returnValue(FALSE)); + + $container = new ContainerBuilder(); + $container->set('user.auth', $user_auth_service); + \Drupal::setContainer($container); + + $this->flood = $this->getMock(FloodInterface::class); + + $this->userStorage = $this->getMockBuilder('\Drupal\user\UserStorage') + ->disableOriginalConstructor() + ->getMock(); + + $this->config = $this->getConfigFactoryStub([ + 'user.flood' => [], + ]); + + $this->logger = $this->getMock('Psr\Log\LoggerInterface'); + + $this->csrfToken = $this->prophesize(CsrfTokenGenerator::class); + + $this->testClass = new TestUserLoginResource([], 'plugin_id', '', [], $this->logger, $this->config, $this->flood, $this->userStorage, $this->csrfToken->reveal()); + } + +}