diff --git a/core/modules/rest/src/Plugin/rest/resource/UserRegistrationResource.php b/core/modules/rest/src/Plugin/rest/resource/UserRegistrationResource.php index 4a4e5ab..14dedb1 100644 --- a/core/modules/rest/src/Plugin/rest/resource/UserRegistrationResource.php +++ b/core/modules/rest/src/Plugin/rest/resource/UserRegistrationResource.php @@ -8,12 +8,19 @@ namespace Drupal\rest\Plugin\rest\resource; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityStorageException; +use Drupal\Core\Session\AccountInterface; use Drupal\rest\Plugin\ResourceBase; use Drupal\rest\ResourceResponse; +use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; use Symfony\Component\Routing\RouteCollection; +use Drupal\Component\Utility\String; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; +use Symfony\Component\HttpKernel\Exception\HttpException; /** - * Represents entities as resources. + * Represents user registration as resource. * * @RestResource( * id = "rest_user_registration", @@ -40,9 +47,59 @@ class UserRegistrationResource extends ResourceBase { * @throws \Symfony\Component\HttpKernel\Exception\HttpException */ public function post(EntityInterface $entity = NULL) { - // @TODO only username, pass and email shoul be added here. + + if ($entity == NULL) { + throw new BadRequestHttpException('No entity content received.'); + } + + $definition = $this->getPluginDefinition(); + // Verify that the deserialized entity is of the type that we expect to + // prevent security issues. + if ($entity->getEntityTypeId() != $definition['serialization_context']['entity_type']) { + throw new BadRequestHttpException('Invalid entity type'); + } + // POSTed entities must not have an ID set, because we always want to create + // new entities here. + if (!$entity->isNew()) { + throw new BadRequestHttpException('Only new entities can be created'); + } + + $approvalSettings = \Drupal::config('user.settings')->get('register'); + // Verify that the current user can register a user account. + if ($approvalSettings == 'admin_only') { + throw new AccessDeniedHttpException('Only administrators can register users.'); + } + // If current user can register accounts then let's block the new registered user if admin approval is needed. + elseif ($approvalSettings == 'visitors_admin_approval') { + $entity->block(); + } + + // Username and email cannot exist. + $this->validate($entity); + + // Cannot add extra roles. + $roles = $entity->getRoles(); + foreach ($roles as $role) { + if ($role != 'authenticated' && $role != 'anonymous') { + throw new BadRequestHttpException(String::format('Anonymous user cannot assign roles when registering a new user account and by default' . + ' authenticated is added, so you cannot assign @role role.', array('@role' => $role))); + } + } + $entity->save(); + + // "Verify email" option disabled and the account as active means that the user can be logged in now. + if (!\Drupal::config('user.settings')->get('verify_mail') && $entity->isActive()) { + _user_mail_notify('register_no_approval_required', $entity); + user_login_finalize($entity); + } + // The new account as blocked means that it needs approval. + elseif (!$entity->isActive()) { + _user_mail_notify('register_pending_approval', $entity); + } + return new ResourceResponse(NULL, 201); + } /** @@ -75,4 +132,37 @@ public function routes() { return $collection; } + + /** + * Validate the user entity values added for a new user registration. + * + * @param AccountInterface $account + * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException + */ + public function validate(AccountInterface $account) { + // New username cannot exist. + $name_taken = (bool) \Drupal::service('entity.query')->get('user') + ->condition('uid', (int) $account->id(), '<>') + ->condition('name', $account->getUsername()) + ->range(0, 1) + ->count() + ->execute(); + + if ($name_taken) { + throw new BadRequestHttpException(String::format('The username @name is already taken.', array('@name' => $account->getUsername()))); + } + + // New email cannot exist. + $mail_taken = (bool) \Drupal::service('entity.query')->get('user') + ->condition('uid', (int) $account->id(), '<>') + ->condition('mail', $account->getEmail()) + ->range(0, 1) + ->count() + ->execute(); + + if ($mail_taken) { + throw new BadRequestHttpException(String::format('The email address @email is already registered', array('@email' => $account->getEmail()))); + } + } + } \ No newline at end of file