diff --git a/core/modules/rest/src/Annotation/RestResource.php b/core/modules/rest/src/Annotation/RestResource.php index 0adbdad..28293b6 100644 --- a/core/modules/rest/src/Annotation/RestResource.php +++ b/core/modules/rest/src/Annotation/RestResource.php @@ -43,11 +43,4 @@ class RestResource extends Plugin { */ public $label; - /** - * Options available. - * - * @var array - */ - public $serialization_context; - } diff --git a/core/modules/rest/src/Plugin/rest/resource/UserRegistrationResource.php b/core/modules/rest/src/Plugin/rest/resource/UserRegistrationResource.php index 30e1265..9836a5e 100644 --- a/core/modules/rest/src/Plugin/rest/resource/UserRegistrationResource.php +++ b/core/modules/rest/src/Plugin/rest/resource/UserRegistrationResource.php @@ -10,6 +10,7 @@ use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\ContentEntityBase; +use Drupal\Core\Render\RenderContext; use Drupal\rest\ResourceResponse; use Drupal\user\Entity\User; use Psr\Log\LoggerInterface; @@ -26,13 +27,8 @@ * @RestResource( * id = "rest_user_registration", * label = @Translation("User Registration"), - * serialization_class = "Drupal\Core\Entity\Entity", - * serialization_context = { - * "entity_type" = "user" - * } + * serialization_class = "Drupal\user\Entity\User" * ) - * - * @see \Drupal\rest\Plugin\Derivative\EntityDerivative */ class UserRegistrationResource extends ResourceBase { @@ -79,7 +75,8 @@ public static function create(ContainerInterface $container, array $configuratio } /** - * Responds to entity POST requests and saves the new entity. + * Responds to user registration POST request and saves new user account + * entities. * * @param \Drupal\user\Entity\User $account * The user account entity. @@ -94,15 +91,10 @@ public function post(User $account = NULL) { throw new BadRequestHttpException('No user account data for registration received.'); } - // Verify that the deserialized entity is of the type that we expect to - // prevent security issues. - if ($account->getEntityTypeId() != 'user') { - throw new BadRequestHttpException('Invalid entity type.'); - } // POSTed user accounts must not have an ID set, because we always // want to create new entities here. if (!$account->isNew()) { - throw new BadRequestHttpException('Only new user accounts can be created.'); + throw new BadRequestHttpException('Only new user accounts can be registered.'); } $approvalSettings = $this->configFactory->get('user.settings')->get('register'); @@ -118,7 +110,7 @@ public function post(User $account = NULL) { // Make sure that the user entity is valid (email and name are valid). $this->validate($account); - // Cannot add extra roles. + // Client cannot submit additional user roles. $roles = $account->getRoles(); foreach ($roles as $role) { if ($role != 'authenticated' && $role != 'anonymous') { @@ -128,46 +120,50 @@ public function post(User $account = NULL) { } $account->save(); + // Send emails from a render context to add bubbleable_metadata to the response. + $context = new RenderContext(); + $renderer = \Drupal::service('renderer'); + $renderer->executeInRenderContext($context, function() use ($account) { + $register = $this->configFactory->get('user.settings')->get('register'); + // No email verification is required. Activating the user. + if ($register == 'visitors') { + if (!$this->configFactory->get('user.settings')->get('verify_mail')) { + // Notification will be sent if activated. + $account->status = 1; + $account->save(); + } + // No administrator approval required. + else { + _user_mail_notify('register_no_approval_required', $account); + } + } + // Administrator approval required. + elseif ($register == 'visitors_admin_approval') { + _user_mail_notify('register_pending_approval', $account); + } + }); - // "Verify email" option disabled and the account as active means that the user can be logged in now. - if (!$this->configFactory->get('user.settings')->get('verify_mail') && $account->isActive()) { - _user_mail_notify('register_no_approval_required', $account); - user_login_finalize($account); - } - // The new account as blocked means that it needs approval. - elseif (!$account->isActive()) { - _user_mail_notify('register_pending_approval', $account); + $response = new ResourceResponse(NULL, 201); + if (!$context->isEmpty()) { + $response->addCacheableDependency($context->pop()); } - return new ResourceResponse(NULL, 201); + return $response; } /** - * Implements ResourceInterface::routes(). + * {@inheritdoc} */ public function routes() { $collection = new RouteCollection(); $route_name = strtr($this->pluginId, ':', '.'); - - $methods = $this->availableMethods(); - foreach ($methods as $method) { - $route = $this->getBaseRoute('/entity/user/register', $method); - - switch ($method) { - case 'POST': - $route->setPath('/entity/user/register'); - // Restrict the incoming HTTP Content-type header to the known - // serialization formats. - $route->addRequirements(array('_content_type_format' => implode('|', $this->serializerFormats))); - $collection->add("$route_name.$method", $route); - break; - - default: - $collection->add("$route_name.$method", $route); - break; - } - } + $route = $this->getBaseRoute('/entity/user/register', 'POST'); + $route->setPath('/entity/user/register'); + // Restrict the incoming HTTP Content-type header to the known + // serialization formats. + $route->addRequirements(array('_content_type_format' => implode('|', $this->serializerFormats))); + $collection->add("$route_name.POST", $route); return $collection; } @@ -183,6 +179,11 @@ public function routes() { */ protected function validate(ContentEntityBase $entity) { $violations = $entity->validate(); + + // Remove violations of inaccessible fields as they cannot stem from our + // changes. + $violations->filterByFieldAccess(); + if (count($violations) > 0) { $message = "Unprocessable Entity: validation failed.\n"; foreach ($violations as $violation) { diff --git a/core/modules/rest/src/RequestHandler.php b/core/modules/rest/src/RequestHandler.php index c4c6b77..51b6aac 100644 --- a/core/modules/rest/src/RequestHandler.php +++ b/core/modules/rest/src/RequestHandler.php @@ -62,11 +62,7 @@ public function handle(RouteMatchInterface $route_match, Request $request) { $definition = $resource->getPluginDefinition(); $class = $definition['serialization_class']; $context = array(); - // Get context information for deserialization from the plugin - // definition. - if (!empty($definition['serialization_context'])) { - $context = $definition['serialization_context']; - } + // Always add the resource ID to the deserialization context. $context['resource_id'] = $plugin; $context['request_method'] = $method; diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 4f8289b..555218e 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -1209,7 +1209,7 @@ function user_role_revoke_permissions($rid, array $permissions = array()) { * language. * * @return array - * An array containint various information about the message. + * An array containing various information about the message. * See \Drupal\Core\Mail\MailManagerInterface::mail() for details. * * @see user_mail_tokens()