You are here

public function RegistrationController::confirmAccount in User registration password 8

Confirms a user account.

Parameters

int $uid: UID of user requesting confirmation.

int $timestamp: The current timestamp.

string $hash: Login link hash.

Return value

array|\Symfony\Component\HttpFoundation\RedirectResponse The form structure or a redirect response.

Throws

\Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException If the login link is for a blocked user or invalid user ID.

1 string reference to 'RegistrationController::confirmAccount'
user_registrationpassword.routing.yml in ./user_registrationpassword.routing.yml
user_registrationpassword.routing.yml

File

src/Controller/RegistrationController.php, line 94

Class

RegistrationController
User registration password controller class.

Namespace

Drupal\user_registrationpassword\Controller

Code

public function confirmAccount($uid, $timestamp, $hash) {
  $route_name = '<front>';
  $route_options = [];
  $current_user = $this
    ->currentUser();

  // Verify that the user exists.
  if ($current_user === NULL) {
    throw new AccessDeniedHttpException();
  }

  // When processing the one-time login link, we have to make sure that a user
  // isn't already logged in.
  if ($current_user
    ->isAuthenticated()) {

    // The existing user is already logged in.
    if ($current_user
      ->id() == $uid) {
      $this->messenger
        ->addMessage($this
        ->t('You are currently authenticated as user %user.', [
        '%user' => $current_user
          ->getAccountName(),
      ]));

      // Redirect to user page.
      $route_name = 'user.page';
      $route_options = [
        'user' => $current_user
          ->id(),
      ];
    }
    else {
      $reset_link_account = $this->userStorage
        ->load($uid);
      if (!empty($reset_link_account)) {
        $this->messenger
          ->addMessage($this
          ->t('Another user (%other_user) is already logged into the site on this computer, but you tried to use a one-time link for user %resetting_user. Please <a href=":logout">log out</a> and try using the link again.', [
          '%other_user' => $current_user
            ->getDisplayName(),
          '%resetting_user' => $reset_link_account
            ->getDisplayName(),
          ':logout' => Url::fromRoute('user.logout')
            ->toString(),
        ]), 'warning');
      }
      else {

        // Invalid one-time link specifies an unknown user.
        $this->messenger
          ->addMessage($this
          ->t('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.'));
        $route_name = 'user.pass';
      }
    }
  }
  else {

    // Time out, in seconds, until login URL expires. 24 hours = 86400
    // seconds.
    $timeout = $this
      ->config('user_registrationpassword.settings')
      ->get('registration_ftll_timeout');
    $current = $this->time
      ->getRequestTime();
    $timestamp_created = $timestamp - $timeout;

    // Some redundant checks for extra security ?
    $users = $this->userStorage
      ->getQuery()
      ->condition('uid', $uid)
      ->condition('status', 0)
      ->condition('access', 0)
      ->execute();

    // Timestamp can not be larger then current.

    /** @var \Drupal\user\UserInterface $account */
    if ($timestamp_created <= $current && !empty($users) && ($account = $this->userStorage
      ->load(reset($users)))) {

      // Check if we have to enforce expiration for activation links.
      if ($this
        ->config('user_registrationpassword.settings')
        ->get('registration_ftll_expire') && !$account
        ->getLastLoginTime() && $current - $timestamp > $timeout) {
        $this->messenger
          ->addMessage($this
          ->t('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.'));
        $route_name = 'user.pass';
      }
      elseif ($account
        ->id() && $timestamp >= $account
        ->getCreatedTime() && !$account
        ->getLastLoginTime() && $hash == user_pass_rehash($account, $timestamp)) {

        // Format the date, so the logs are a bit more readable.
        $date = $this->dateFormatter
          ->format($timestamp);
        $this
          ->getLogger('user')
          ->notice('User %name used one-time login link at time %timestamp.', [
          '%name' => $account
            ->getAccountName(),
          '%timestamp' => $date,
        ]);

        // Activate the user and update the access and login time to $current.
        $account
          ->activate()
          ->setLastAccessTime($current)
          ->setLastLoginTime($current)
          ->save();

        // user_login_finalize() also updates the login timestamp of the
        // user, which invalidates further use of the one-time login link.
        user_login_finalize($account);

        // Display default welcome message.
        $this->messenger
          ->addMessage($this
          ->t('You have just used your one-time login link. Your account is now active and you are authenticated.'));

        // Redirect to user.
        $route_name = 'user.page';
        $route_options = [
          'user' => $account
            ->id(),
        ];
      }
      else {
        $this->messenger
          ->addMessage($this
          ->t('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.'));
        $route_name = 'user.pass';
      }
    }
    else {

      // Deny access, no more clues.
      // Everything will be in the watchdog's
      // URL for the administrator to check.
      $this->messenger
        ->addMessage($this
        ->t('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.'));
      $route_name = 'user.pass';
    }
  }
  return $this
    ->redirect($route_name, $route_options);
}