diff --git a/core/modules/rest/src/Plugin/ResourceBase.php b/core/modules/rest/src/Plugin/ResourceBase.php index d0d22a3..9aeec30 100644 --- a/core/modules/rest/src/Plugin/ResourceBase.php +++ b/core/modules/rest/src/Plugin/ResourceBase.php @@ -216,4 +216,18 @@ protected function getBaseRoute($canonical_path, $method) { return $route; } + /** + * Throws an exception if the current user triggers flood control. + * + * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException + */ + protected function restFloodControl($config, $name) { + $limit = $config->get('user_limit'); + $interval = $config->get('user_window'); + if (!\Drupal::flood()->isAllowed($name, $limit, $interval)) { + return TRUE; + } + return FALSE; + } + } diff --git a/core/modules/rest/src/Plugin/rest/resource/UserLoginResource.php b/core/modules/rest/src/Plugin/rest/resource/UserLoginResource.php new file mode 100644 index 0000000..7a70ffd --- /dev/null +++ b/core/modules/rest/src/Plugin/rest/resource/UserLoginResource.php @@ -0,0 +1,93 @@ +login($operation['credentials']); + } + return new ResourceResponse('credentials.', 400, array()); + + case 'logout': + return $this->logout(); + + } + } + + /** + * User login. + * + * @param array $credentials + * The username and pass for the user. + * + * @return \Drupal\rest\ResourceResponse + * The HTTP response object + */ + protected function login(array $credentials = array()) { + // Verify that the username is filled. + if (!array_key_exists('name', $credentials)) { + return new ResourceResponse('Missing credentials.name.', 400, array()); + } + // Verify that the username is filled. + if (!array_key_exists('pass', $credentials)) { + return new ResourceResponse('Missing credentials.pass.', 400, array()); + } + + // Flood control. + if ($this->restFloodControl(\Drupal::config('user.flood'), 'rest.login_cookie')) { + return new ResourceResponse('Blocked.', 400, array()); + } + + // Log in the user. + if ($uid = \Drupal::service('user.auth')->authenticate($credentials['name'], $credentials['pass'])) { + $user = User::load($uid); + user_login_finalize($user); + return new ResourceResponse('You are logged in as ' . $credentials['name'], 200, array()); + } + \Drupal::flood()->register('rest.login_cookie', \Drupal::config('user.flood')->get('user_window')); + return new ResourceResponse('Sorry, unrecognized username or password.', 400, array()); + } + + /** + * User Logout. + * + * @return ResourceResponse + */ + protected function logout() { + user_logout(); + return new ResourceResponse('Logged out!', 200, array()); + } + +} diff --git a/core/modules/rest/src/RequestHandler.php b/core/modules/rest/src/RequestHandler.php index 0ddfdd7..0cb2ef9 100644 --- a/core/modules/rest/src/RequestHandler.php +++ b/core/modules/rest/src/RequestHandler.php @@ -63,7 +63,13 @@ public function handle(RouteMatchInterface $route_match, Request $request, Route $definition = $resource->getPluginDefinition(); $class = $definition['serialization_class']; try { - $unserialized = $serializer->deserialize($received, $class, $format, array('request_method' => $method)); + if ($class) { + $unserialized = $serializer->deserialize($received, $class, $format, array('request_method' => $method)); + } + // Avoid denormalization because we need to instantiate a class. + else { + $unserialized = $serializer->decode($received, $format, array('request_method' => $method)); + } } catch (UnexpectedValueException $e) { $error['error'] = $e->getMessage();