Skip to content
Snippets Groups Projects
Commit 568048fb authored by Joao Ventura's avatar Joao Ventura
Browse files

Issue #2930355: Rename admin_uli_skip to reset_pass_skip_enabled, and make it...

Issue #2930355: Rename admin_uli_skip to reset_pass_skip_enabled, and make it a boolean. Add specific 'reset pass skip tfa' permission
parent 4c2989a7
No related branches found
Tags 7.x-1.0
No related merge requests found
......@@ -14,7 +14,7 @@ trust_cookie_name: 'tfa-trusted-browser'
tfa_flood_uid_only: 1
tfa_flood_window: 300
tfa_flood_threshold: 6
admin_uli_skip: 1
reset_pass_skip_enabled: true
mail:
tfa_enabled_configuration:
subject: "Your [site:name] account now has two-factor authentication"
......
......@@ -38,8 +38,8 @@ tfa.settings:
validation_skip:
type: integer
label: 'No. of times a user without tfa validation set-up can login.'
admin_uli_skip:
type: integer
reset_pass_skip_enabled:
type: boolean
label: 'Allow administrator role to skip TFA when resetting password.'
encryption:
type: string
......
......@@ -4,17 +4,9 @@ namespace Drupal\tfa\Controller;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Url;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Flood\FloodInterface;
use Drupal\tfa\TfaContext;
use Drupal\tfa\TfaLoginPluginManager;
use Drupal\tfa\TfaLoginTrait;
use Drupal\tfa\TfaValidationPluginManager;
use Drupal\user\UserDataInterface;
use Drupal\user\UserStorageInterface;
use Drupal\user\Controller\UserController;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
......@@ -25,6 +17,7 @@ use Drupal\user\UserInterface;
*/
class TfaUserController extends UserController {
use TfaLoginTrait;
/**
* The login plugin manager to fetch plugin information.
*
......@@ -39,6 +32,13 @@ class TfaUserController extends UserController {
*/
protected $tfaValidationPlugin;
/**
* The configuration factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* Tfa login context object.
*
......@@ -48,45 +48,31 @@ class TfaUserController extends UserController {
*/
protected $tfaContext;
/**
* {@inheritdoc}
*/
public function __construct(ConfigFactoryInterface $configFactory, DateFormatterInterface $date_formatter, UserStorageInterface $user_storage, UserDataInterface $user_data, LoggerInterface $logger, FloodInterface $flood, TfaValidationPluginManager $tfa_validation_manager, TfaLoginPluginManager $tfa_plugin_manager) {
parent::__construct($date_formatter, $user_storage, $user_data, $logger, $flood);
$this->tfaValidationManager = $tfa_validation_manager;
$this->tfaLoginManager = $tfa_plugin_manager;
$this->configFactory = $configFactory;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('config.factory'),
$container->get('date.formatter'),
$container->get('entity_type.manager')->getStorage('user'),
$container->get('user.data'),
$container->get('logger.factory')->get('user'),
$container->get('flood'),
$container->get('plugin.manager.tfa.validation'),
$container->get('plugin.manager.tfa.login'));
$instance = parent::create($container);
$this->tfaLoginManager = $container->get('plugin.manager.tfa.login');
$instance->tfaValidationManager = $container->get('plugin.manager.tfa.validation');
$this->configFactory = $container->get('config.factory');
return $instance;
}
/**
* {@inheritdoc}
*/
public function resetPassLogin($uid, $timestamp, $hash, Request $request) {
/**
*
* @var \Drupal\user\UserInterface $user Current user.
*/
/** @var \Drupal\user\UserInterface $user */
$user = $this->userStorage->load($uid);
// Tfa context service.
$this->tfaContext = new TfaContext($this->tfaValidationManager, $this->tfaLoginManager, $this->configFactory, $user, $this->userData, $request);
// Let Drupal core deal with the one time login,
// if Tfa is not enabled or current user is TFA admin and can skip TFA.
if (!$this->tfaContext->isModuleSetup() || !$this->tfaContext->isTfaRequired() || ($this->tfaContext->canAdminSkip() && $this->tfaContext->isTfaAdmin())) {
if (!$this->tfaContext->isModuleSetup() || !$this->tfaContext->isTfaRequired() || $this->tfaContext->canResetPassSkip()) {
// Let the Drupal core to validate the one time login.
return parent::resetPassLogin($uid, $timestamp, $hash, $request);
}
......
......@@ -170,11 +170,11 @@ class SettingsForm extends ConfigFormBase {
'#required' => FALSE,
];
$form['admin_uli_skip'] = [
$form['reset_pass_skip_enabled'] = [
'#type' => 'checkbox',
'#title' => $this->t('Admin TFA exemption'),
'#default_value' => $config->get('admin_uli_skip') ?? 1,
'#description' => $this->t('Allow TFA admin to skip TFA when resetting password.'),
'#title' => $this->t('Allow TFA bypass during password reset'),
'#default_value' => $config->get('reset_pass_skip_enabled') ?? TRUE,
'#description' => $this->t('Allow TFA to be bypassed during password reset by users with the @role role.', ['@role' => 'Bypass TFA during password reset']),
'#states' => $enabled_state,
'#required' => FALSE,
];
......@@ -445,7 +445,7 @@ class SettingsForm extends ConfigFormBase {
->set('mail.tfa_disabled_configuration.subject', $form_state->getValue('tfa_disabled_configuration_subject'))
->set('mail.tfa_disabled_configuration.body', $form_state->getValue('tfa_disabled_configuration_body'))
->set('help_text', $form_state->getValue('help_text'))
->set('admin_uli_skip', $form_state->getValue('admin_uli_skip'))
->set('reset_pass_skip_enabled', $form_state->getValue('reset_pass_skip_enabled'))
->save();
parent::submitForm($form, $form_state);
......
......@@ -121,40 +121,8 @@ class TfaContext implements TfaContextInterface {
/**
* {@inheritdoc}
*/
public function canAdminSkip() {
return intval($this->tfaSettings->get('admin_uli_skip'));
}
/**
* {@inheritdoc}
*/
public function isTfaAdmin() {
// Current user.
/** @var \Drupal\user\UserInterface */
$user = $this->getUser();
// Permissions required by a TFA admin user.
$admin_permissions = [
'administer tfa for other users',
'admin tfa settings',
'setup own tfa',
];
if ($user) {
// Check if current user has all permissions
// that a TFA admin user should have.
foreach ($admin_permissions as $permission) {
if (!$user->hasPermission($permission)) {
// Current user must have all permissions
// required by a TFA admin user.
return FALSE;
}
}
// The user has all permissions required.
return TRUE;
}
// Current user is not available.
return FALSE;
public function canResetPassSkip() {
return $this->tfaSettings->get('reset_pass_skip_enabled') && $this->getUser()->hasPermission('reset pass skip tfa');
}
/**
......
......@@ -49,12 +49,7 @@ class TfaPasswordResetTest extends TfaTestBase {
$this->webUser = $this->drupalCreateUser(['setup own tfa']);
$this->adminUser = $this->drupalCreateUser(['admin tfa settings']);
$this->superAdmin = $this->drupalCreateUser(
['administer tfa for other users',
'admin tfa settings',
'setup own tfa',
]
);
$this->superAdmin = $this->drupalCreateUser(['reset pass skip tfa']);
$this->canEnableValidationPlugin('tfa_test_plugins_validation');
// Activate user by logging in.
......@@ -121,7 +116,7 @@ class TfaPasswordResetTest extends TfaTestBase {
// and disable admin bypass TFA while resetting password.
$this->drupalLogin($this->adminUser);
$edit = [
'admin_uli_skip' => 0,
'reset_pass_skip_enabled' => FALSE,
];
$this->drupalGet('admin/config/people/tfa');
$this->submitForm($edit, 'Save configuration');
......
......@@ -17,3 +17,8 @@ administer tfa for other users:
title: 'Administer TFA for other users'
description: 'Allow users to edit TFA for other accounts.'
restrict access: TRUE
reset pass skip tfa:
title: 'Bypass TFA during password reset'
description: 'Allows users to bypass TFA when using the one-time login link used in the password reset process, also used by drush uli'
restrict access: TRUE
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment