diff --git a/core/modules/rest/src/Plugin/rest/resource/UserLoginResource.php b/core/modules/rest/src/Plugin/rest/resource/UserLoginResource.php index 1c05c8b..9fe24c4 100644 --- a/core/modules/rest/src/Plugin/rest/resource/UserLoginResource.php +++ b/core/modules/rest/src/Plugin/rest/resource/UserLoginResource.php @@ -157,7 +157,7 @@ public function post($credentials) { 'csrf_token' => $this->csrfToken->get('rest'), ]; - $response = new ResourceResponse($response_data, 200, []); + $response = new ResourceResponse($response_data); return $response->addCacheableDependency($user); } diff --git a/core/modules/rest/src/Plugin/rest/resource/UserLoginStatusResource.php b/core/modules/rest/src/Plugin/rest/resource/UserLoginStatusResource.php index fe6fde9..97cdc49 100644 --- a/core/modules/rest/src/Plugin/rest/resource/UserLoginStatusResource.php +++ b/core/modules/rest/src/Plugin/rest/resource/UserLoginStatusResource.php @@ -87,11 +87,11 @@ public static function create(ContainerInterface $container, array $configuratio */ public function get() { if ($this->currentUser->isAuthenticated()) { - $response = new ResourceResponse(self::LOGGED_IN, 200, []); + $response = new ResourceResponse(self::LOGGED_IN); $response->addCacheableDependency($this->currentUser); } else { - $response = new ResourceResponse(self::LOGGED_OUT, 200, []); + $response = new ResourceResponse(self::LOGGED_OUT); } return $response->addCacheableDependency((new CacheableMetadata())->setCacheMaxAge(0)); } diff --git a/core/modules/rest/src/Plugin/rest/resource/UserLogoutResource.php b/core/modules/rest/src/Plugin/rest/resource/UserLogoutResource.php index a2a527b..58228b3 100644 --- a/core/modules/rest/src/Plugin/rest/resource/UserLogoutResource.php +++ b/core/modules/rest/src/Plugin/rest/resource/UserLogoutResource.php @@ -19,6 +19,20 @@ class UserLogoutResource extends ResourceBase { /** + * {@inheritdoc} + */ + public function routes() { + $routes = parent::routes(); + $route_name = strtr($this->pluginId, ':', '.'); + $routes->get("$route_name.POST")->addRequirements([ + '_user_is_logged_in' => 'TRUE', + ]); + + return $routes; + } + + + /** * Responds to user logout POST requests. * * @return \Drupal\rest\ResourceResponse diff --git a/core/modules/rest/src/Tests/RESTTestBase.php b/core/modules/rest/src/Tests/RESTTestBase.php index c9338ae..0b4a99d 100644 --- a/core/modules/rest/src/Tests/RESTTestBase.php +++ b/core/modules/rest/src/Tests/RESTTestBase.php @@ -73,9 +73,11 @@ protected function setUp() { * The body for POST and PUT. * @param string $mime_type * The MIME type of the transmitted content. + * @param array $request_headers + * Some additional request headers. * - * @return string - * The content returned from the request. + * @return string The content returned from the request. + * The content returned from the request. */ protected function httpRequest($url, $method, $body = NULL, $mime_type = NULL, $request_headers = []) { if (!isset($mime_type)) { diff --git a/core/modules/rest/src/Tests/UserLoginTest.php b/core/modules/rest/src/Tests/UserLoginTest.php index 9f32183..763712c 100644 --- a/core/modules/rest/src/Tests/UserLoginTest.php +++ b/core/modules/rest/src/Tests/UserLoginTest.php @@ -2,8 +2,9 @@ namespace Drupal\rest\Tests; +use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Url; -use Drupal\rest\Plugin\rest\resource\UserLoginStatus; +use Drupal\rest\Plugin\rest\resource\UserLoginStatusResource; use Drupal\user\Entity\Role; use Drupal\user\RoleInterface; @@ -18,29 +19,14 @@ class UserLoginTest extends RESTTestBase { * Test user session life cycle. */ public function testLogin() { - // Enable the service. - $config = $this->config('rest.settings'); - $settings = []; + // Enable the rest resources. $format = 'json'; $auth = $this->defaultAuth; - $resource = ['type' => 'user_login', 'method' => 'POST']; - $settings[$resource['type']][$resource['method']]['supported_formats'][] = $format; - $settings[$resource['type']][$resource['method']]['supported_auth'] = $auth; - - $resource = ['type' => 'user_login_status', 'method' => 'GET']; - $settings[$resource['type']][$resource['method']]['supported_formats'][] = $format; - $settings[$resource['type']][$resource['method']]['supported_auth'] = $auth; - - $resource = ['type' => 'user_logout', 'method' => 'POST']; - $settings[$resource['type']][$resource['method']]['supported_formats'][] = $format; - $settings[$resource['type']][$resource['method']]['supported_auth'] = $auth; - - - $config->set('resources', $settings); - $config->save(); - - $this->rebuildCache(); + $this->enableService('user_login', 'POST', $format, $auth); + $this->enableService('user_login_status', 'GET', $format, $auth); + $this->enableService('user_logout', 'POST'); + $this->enableService('user_password_reset', 'POST'); $permissions[] = 'restful post user_login'; $account = $this->drupalCreateUser($permissions); @@ -63,48 +49,83 @@ public function testLogin() { $url->setRouteParameter('_format', 'json'); $this->httpRequest($url, 'GET', NULL, 'application/json'); $this->assertResponse(200); - $this->assertResponseBody('"' . UserLoginStatus::LOGGED_OUT . '"'); + $this->assertResponseBody('"' . UserLoginStatusResource::LOGGED_OUT . '"'); - $payload = []; - $this->httpRequest('/user/login/', 'POST', json_encode($payload), 'application/json'); + $request_body = []; + $this->httpRequest('/user/login/', 'POST', json_encode($request_body), 'application/json'); $this->assertResponse(400); $this->assertResponseBody('{"error":"Missing credentials."}'); - $payload = ['pass' => $pass]; - $this->httpRequest('/user/login', 'POST', json_encode($payload), 'application/json'); + $request_body = ['pass' => $pass]; + $this->httpRequest('/user/login', 'POST', json_encode($request_body), 'application/json'); $this->assertResponse(400); $this->assertResponseBody('{"error":"Missing credentials.name."}'); - $payload = ['name' => $name, 'pass' => 'garbage']; - $this->httpRequest('/user/login', 'POST', json_encode($payload), 'application/json'); + $request_body = ['name' => $name]; + $this->httpRequest('/user/login', 'POST', json_encode($request_body), 'application/json'); + $this->assertResponse(400); + $this->assertResponseBody('{"error":"Missing credentials.pass."}'); + + // Blocked. + $account->block(); + $account->save(); + $request_body = ['name' => $name]; + $this->httpRequest('/user/login', 'POST', json_encode($request_body), 'application/json'); + $this->assertResponse(400); + $this->assertResponseBody('{"error":"The user has not been activated or is blocked."}'); + $account->activate(); + $account->save(); + + // Flooded. + $request_body = ['name' => $name]; + $this->httpRequest('/user/login', 'POST', json_encode($request_body), 'application/json'); + $this->assertResponse(400); + $this->assertResponseBody('{"error":"Missing credentials.pass."}'); + + $request_body = ['name' => $name, 'pass' => 'garbage']; + $this->httpRequest('/user/login', 'POST', json_encode($request_body), 'application/json'); $this->assertResponse(400); $this->assertResponseBody('{"error":"Sorry, unrecognized username or password."}'); - $payload = ['name' => 'garbage', 'pass' => $pass]; - $this->httpRequest('/user/login', 'POST', json_encode($payload), 'application/json'); + $request_body = ['name' => 'garbage', 'pass' => $pass]; + $this->httpRequest('/user/login', 'POST', json_encode($request_body), 'application/json'); $this->assertResponse(400); $this->assertResponseBody('{"error":"Sorry, unrecognized username or password."}'); - $payload = ['name' => $name, 'pass' => $pass]; - $response = $this->httpRequest('/user/login', 'POST', json_encode($payload), 'application/json'); + $request_body = ['name' => $name, 'pass' => $pass]; + $response = $this->httpRequest('/user/login', 'POST', json_encode($request_body), 'application/json'); $response = json_decode($response); $this->assertEqual($name, $response->current_user->name, "The user name is correct."); - $url = Url::fromRoute('rest.user_login_status.GET.json'); + $url = Url::fromRoute('/user/login/status'); $url->setRouteParameter('_format', 'json'); $this->httpRequest($url, 'GET', NULL, 'application/json'); $this->assertResponse(200); - $this->assertResponseBody('"' . UserLoginStatus::LOGGED_IN . '"'); + $this->assertResponseBody('"' . UserLoginStatusResource::LOGGED_IN . '"'); - $payload = ['name' => $name, 'pass' => $pass]; - $this->httpRequest('/user/logout', 'POST', json_encode($payload), 'application/json'); + $request_body = ['name' => $name, 'pass' => $pass]; + $this->httpRequest('/user/logout', 'POST', json_encode($request_body), 'application/json'); $this->assertResponse(204); - $url = Url::fromRoute('rest.user_login_status.GET.json'); + $url = Url::fromRoute('/user/login/status'); $url->setRouteParameter('_format', 'json'); $this->httpRequest($url, 'GET', NULL, 'application/json'); $this->assertResponse(200); - $this->assertResponseBody('"' . UserLoginStatus::LOGGED_OUT . '"'); + $this->assertResponseBody('"' . UserLoginStatusResource::LOGGED_OUT . '"'); + + + $random_name = $this->randomMachineName(); + $url = Url::fromRoute("/user/password/{$random_name}"); + $url->setRouteParameter('_format', 'json'); + $this->httpRequest($url, 'POST', NULL, 'application/json'); + $this->assertResponse(400); + $this->assertResponseBody('{"error":"' . new FormattableMarkup('%name is not recognized as a username or an email address.', ['%name' => $random_name]) . '"}'); + + $url = Url::fromRoute("/user/password/{$name}"); + $url->setRouteParameter('_format', 'json'); + $this->httpRequest($url, 'POST', NULL, 'application/json'); + $this->assertResponse(200); + $this->assertResponseBody('Further instructions have been sent to your email address.'); } }