Skip to content
Snippets Groups Projects
Commit fddd46d0 authored by Antonio Savorelli's avatar Antonio Savorelli
Browse files

Issue #3374265: Overriding the user.reset route is unnecessary

This effectively breaks #2641148, but implementing hook_user_login() should make up for it.
parent 57f1541f
No related branches found
No related tags found
No related merge requests found
<?php
/**
* @file
* Describe hooks provided by the Passwordless module.
*/
/**
* Allows other modules to customize the landing page after a successful login.
*
* @param string $route_name
* @param array $route_parameters
*/
function hook_passwordless_login_redirect_alter(string &$route_name, array &$route_parameters = []) {
$route_name = '<front>';
}
<?php <?php
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url; use Drupal\Core\Url;
use Drupal\Core\Block\BlockPluginInterface; use Drupal\Core\Block\BlockPluginInterface;
...@@ -71,6 +73,23 @@ function passwordless_form_alter(&$form, FormStateInterface $form_state, $form_i ...@@ -71,6 +73,23 @@ function passwordless_form_alter(&$form, FormStateInterface $form_state, $form_i
} }
unset($form['account']['pass'], $form['account']['current_pass']); unset($form['account']['pass'], $form['account']['current_pass']);
break; break;
case 'user_pass_reset':
$form['#title'] = t('Log in');
$build_info = $form_state->getBuildInfo();
// See arguments at \Drupal\user\Form\UserPasswordResetForm::buildForm().
/** @var Drupal\Core\Session\AccountInterface $user */
$user = NestedArray::getValue($build_info, ['args', 0]);
if ($expiration_date = NestedArray::getValue($build_info, ['args', 1])) {
$message = t('<p>This is a one-time login for %user_name and will expire on %expiration_date.</p><p>Click on this button to log in to the site.</p>', ['%user_name' => $user->getAccountName(), '%expiration_date' => $expiration_date]);
}
else {
$message = t('<p>This is a one-time login for %user_name.</p><p>Click on this button to log in to the site.</p>', ['%user_name' => $user->getAccountName()]);
}
$form['message'] = ['#markup' => $message];
break;
} }
} }
......
...@@ -2,93 +2,26 @@ ...@@ -2,93 +2,26 @@
namespace Drupal\passwordless\Controller; namespace Drupal\passwordless\Controller;
use Drupal\Core\Url; use Drupal\Core\Messenger\MessengerInterface;
use Drupal\user\Controller\UserController; use Drupal\user\Controller\UserController;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
/** /**
* Controller routines for Passwordless routes. * Overrides core's UserController methods.
*/ */
class PasswordlessUserController extends UserController { class PasswordlessUserController extends UserController {
/** /**
* {@inheritdoc} * {@inheritDoc}
*/ */
public function resetPass(Request $request, $uid, $timestamp, $hash) { public function resetPassLogin($uid, $timestamp, $hash, Request $request) {
$account = $this->currentUser(); $redirect = parent::resetPassLogin($uid, $timestamp, $hash, $request);
$config = $this->config('user.settings'); // This is pretty safe, since at this point there shouldn't be any other
// When processing the one-time login link, we have to make sure that a user // status messages.
// isn't already logged in. $this->messenger()->deleteByType(MessengerInterface::TYPE_STATUS);
if ($account->isAuthenticated()) { // We don't want to tell the user to set their password.
// The current user is already logged in. $this->messenger()->addStatus($this->t('You have just used your one-time login link. It is no longer necessary to use this link to log in.'));
if ($account->id() == $uid) { return $redirect;
$this->messenger()
->addMessage($this->t('You are logged in as %user.', ['%user' => $account->getDisplayName()]));
}
// A different user is already logged in on the computer.
else {
/** @var \Drupal\user\UserInterface $reset_link_user */
if ($reset_link_user = $this->userStorage->load($uid)) {
$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' => $account->getDisplayName(),
'%resetting_user' => $reset_link_user->getDisplayName(),
':logout' => Url::fromRoute('user.logout')->toString(),
]), 'warning');
}
else {
// Invalid one-time link specifies an unknown user.
$this->messenger()
->addMessage($this->t('The one-time login link you clicked is invalid.'), 'error');
}
}
return $this->redirect('<front>');
}
else {
// The current user is not logged in, so check the parameters.
// Time out, in seconds, until login URL expires.
$timeout = $config->get('password_reset_timeout');
$current = \Drupal::time()->getRequestTime();
/* @var \Drupal\user\UserInterface $user */
$user = $this->userStorage->load($uid);
// Verify that the user exists and is active.
if ($user && $user->isActive()) {
// No time out for first time login.
if ($user->getLastLoginTime() && $current - $timestamp > $timeout) {
$this->messenger()
->addMessage($this->t('You have tried to use a one-time login link that has expired. Please request a new one using the form below.'), 'warning');
return $this->redirect('user.page');
}
elseif ($user->isAuthenticated() && ($timestamp >= $user->getLastLoginTime()) && ($timestamp <= $current) && ($hash === user_pass_rehash($user, $timestamp))) {
$expiration_date = $user->getLastLoginTime() ? $this->dateFormatter->format($timestamp + $timeout) : NULL;
/** @see Drupal\user\Form\UserController::resetPassLogin */
user_login_finalize($user);
$this->logger->notice('User %name used one-time login link at time %timestamp.', [
'%name' => $user->getDisplayName(),
'%timestamp' => $timestamp,
]);
$this->messenger()
->addMessage($this->t('You have just used your one-time login link.'));
$user->pass = sha1(\Drupal::service('password_generator')->generate());
$user->save();
$route_name = 'user.page';
$route_parameters = [];
\Drupal::moduleHandler()
->alter('passwordless_login_redirect', $route_name, $route_parameters);
return $this->redirect($route_name, $route_parameters);
}
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.'), 'warning');
return $this->redirect('user.page');
}
}
}
// Blocked or invalid user ID, so deny access. The parameters will be in the
// watchdog's URL for the administrator to check.
throw new AccessDeniedHttpException();
} }
}
\ No newline at end of file }
...@@ -22,11 +22,11 @@ class RouteSubscriber extends RouteSubscriberBase { ...@@ -22,11 +22,11 @@ class RouteSubscriber extends RouteSubscriberBase {
$route->setDefaults(['_controller' => '\Drupal\passwordless\Controller\PasswordlessController::redirectUserPassPage']); $route->setDefaults(['_controller' => '\Drupal\passwordless\Controller\PasswordlessController::redirectUserPassPage']);
} }
if ($route = $collection->get('user.reset')) { if ($route = $collection->get('user.reset.login')) {
$route->setDefaults([ $route->setDefaults([
'_controller' => '\Drupal\passwordless\Controller\PasswordlessUserController::resetPass', '_controller' => '\Drupal\passwordless\Controller\PasswordlessUserController::resetPassLogin',
'_title' => 'Log-in',
]); ]);
} }
} }
}
\ No newline at end of file }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment