class EntryForm in Two-factor Authentication (TFA) 8
TFA entry form.
Hierarchy
- class \Drupal\Core\Form\FormBase implements ContainerInjectionInterface, FormInterface uses DependencySerializationTrait, LoggerChannelTrait, MessengerTrait, LinkGeneratorTrait, RedirectDestinationTrait, UrlGeneratorTrait, StringTranslationTrait
- class \Drupal\tfa\Form\EntryForm
Expanded class hierarchy of EntryForm
1 string reference to 'EntryForm'
File
- src/
Form/ EntryForm.php, line 19
Namespace
Drupal\tfa\FormView source
class EntryForm extends FormBase {
/**
* Validation plugin manager.
*
* @var \Drupal\tfa\TfaValidationPluginManager
*/
protected $tfaValidationManager;
/**
* Login plugin manager.
*
* @var \Drupal\tfa\TfaLoginPluginManager
*/
protected $tfaLoginManager;
/**
* The validation plugin object.
*
* @var \Drupal\tfa\Plugin\TfaValidationInterface
*/
protected $tfaValidationPlugin;
/**
* The login plugins.
*
* @var \Drupal\tfa\Plugin\TfaLoginInterface
*/
protected $tfaLoginPlugins;
/**
* TFA configuration object.
*
* @var \Drupal\Core\Config\ImmutableConfig
*/
protected $tfaSettings;
/**
* The flood control mechanism.
*
* @var \Drupal\Core\Flood\FloodInterface
*/
protected $flood;
/**
* The flood control identifier.
*
* @var string
*/
protected $floodIdentifier;
/**
* The date formatter service.
*
* @var \Drupal\Core\Datetime\DateFormatterInterface
*/
protected $dateFormatter;
/**
* User data service.
*
* @var \Drupal\user\UserDataInterface
*/
protected $userData;
/**
* EntryForm constructor.
*
* @param \Drupal\tfa\TfaValidationPluginManager $tfa_validation_manager
* Plugin manager for validation plugins.
* @param \Drupal\tfa\TfaLoginPluginManager $tfa_login_manager
* Plugin manager for login plugins.
* @param \Drupal\Core\Flood\FloodInterface $flood
* The flood control mechanism.
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
* The date service.
* @param \Drupal\user\UserDataInterface $user_data
* User data service.
*/
public function __construct(TfaValidationPluginManager $tfa_validation_manager, TfaLoginPluginManager $tfa_login_manager, FloodInterface $flood, DateFormatterInterface $date_formatter, UserDataInterface $user_data) {
$this->tfaValidationManager = $tfa_validation_manager;
$this->tfaLoginManager = $tfa_login_manager;
$this->tfaSettings = $this
->config('tfa.settings');
$this->flood = $flood;
$this->dateFormatter = $date_formatter;
$this->userData = $user_data;
}
/**
* Creates service objects for the class constructor.
*
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
* The container to get the required services.
*
* @return static
*/
public static function create(ContainerInterface $container) {
return new static($container
->get('plugin.manager.tfa.validation'), $container
->get('plugin.manager.tfa.login'), $container
->get('flood'), $container
->get('date.formatter'), $container
->get('user.data'));
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'tfa_entry_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, AccountInterface $user = NULL) {
$alternate_plugin = $this
->getRequest()
->get('plugin');
$validation_plugin_definitions = $this->tfaValidationManager
->getDefinitions();
$user_settings = $this->userData
->get('tfa', $user
->id(), 'tfa_user_settings');
$user_enabled_validation_plugins = isset($user_settings['data']['plugins']) ? $user_settings['data']['plugins'] : [];
// Default validation plugin, then check for enabled alternate plugin.
$validation_plugin = $this->tfaSettings
->get('default_validation_plugin');
if ($alternate_plugin && !empty($validation_plugin_definitions[$alternate_plugin]) && !empty($user_enabled_validation_plugins[$alternate_plugin])) {
$validation_plugin = $alternate_plugin;
$form['#cache'] = [
'max-age' => 0,
];
}
// Get current validation plugin form.
$this->tfaValidationPlugin = $this->tfaValidationManager
->createInstance($validation_plugin, [
'uid' => $user
->id(),
]);
$form = $this->tfaValidationPlugin
->getForm($form, $form_state);
$this->tfaLoginPlugins = $this->tfaLoginManager
->getPlugins([
'uid' => $user
->id(),
]);
if ($this->tfaLoginPlugins) {
foreach ($this->tfaLoginPlugins as $login_plugin) {
if (method_exists($login_plugin, 'getForm')) {
$form = $login_plugin
->getForm($form, $form_state);
}
}
}
$form['account'] = [
'#type' => 'value',
'#value' => $user,
];
// Build a list of links for using other enabled validation methods.
$other_validation_plugin_links = [];
foreach ($user_enabled_validation_plugins as $user_enabled_validation_plugin) {
// Do not show the current plugin.
if ($validation_plugin == $user_enabled_validation_plugin) {
continue;
}
// Do not show plugins without labels.
if (empty($validation_plugin_definitions[$user_enabled_validation_plugin]['label'])) {
continue;
}
$other_validation_plugin_links[$user_enabled_validation_plugin] = [
'title' => $validation_plugin_definitions[$user_enabled_validation_plugin]['label'],
'url' => Url::fromRoute('tfa.entry', [
'user' => $user
->id(),
'hash' => $this
->getRequest()
->get('hash'),
'plugin' => $user_enabled_validation_plugin,
]),
];
}
// Show other enabled and configured validation plugins.
$form['validation_plugin'] = [
'#type' => 'value',
'#value' => $validation_plugin,
];
// Don't show an empty fieldset when no other tfa methods are available.
if (!empty($other_validation_plugin_links)) {
$form['change_validation_plugin'] = [
'#type' => 'fieldset',
'#title' => $this
->t('Having Trouble?'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'content' => [
'help' => [
'#markup' => $this
->t('Try one of your other enabled validation methods.'),
],
'other_validation_plugins' => [
'#theme' => 'links',
'#links' => $other_validation_plugin_links,
],
],
];
}
return $form;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
$values = $form_state
->getValues();
$window = $this->tfaSettings
->get('tfa_flood_window') ?: 300;
$threshold = $this->tfaSettings
->get('tfa_flood_threshold') ?: 6;
if ($this->tfaSettings
->get('tfa_flood_uid_only')) {
// Register flood events based on the uid only, so they apply for any
// IP address. This is the most secure option.
$this->floodIdentifier = $values['account']
->id();
}
else {
// The default identifier is a combination of uid and IP address. This
// is less secure but more resistant to denial-of-service attacks that
// could lock out all users with public user names.
$this->floodIdentifier = $values['account']
->id() . '-' . $this
->getRequest()
->getClientIP();
}
// Flood control.
if (!$this->flood
->isAllowed('tfa.failed_validation', $threshold, $window, $this->floodIdentifier)) {
$form_state
->setErrorByName('', $this
->t('Failed validation limit reached. %limit wrong codes in @interval. Try again later.', [
'%limit' => $threshold,
'@interval' => $this->dateFormatter
->formatInterval($window),
]));
return;
}
$validated = $this->tfaValidationPlugin
->validateForm($form, $form_state);
if (!$validated) {
// @todo Either define getErrorMessages in the TfaValidationInterface, or don't use it.
// For now, let's just check that it exists before assuming.
if (method_exists($this->tfaValidationPlugin, 'getErrorMessages')) {
$form_state
->clearErrors();
$errors = $this->tfaValidationPlugin
->getErrorMessages();
$form_state
->setErrorByName(key($errors), current($errors));
}
$this->flood
->register('tfa.failed_validation', $this->tfaSettings
->get('tfa_flood_window'), $this->floodIdentifier);
}
}
/**
* If the form is passes validation, the user should get logged in.
*
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$user = $form_state
->getValue('account');
// @todo This could be improved with EventDispatcher.
if (!empty($this->tfaLoginPlugins)) {
foreach ($this->tfaLoginPlugins as $plugin) {
if (method_exists($plugin, 'submitForm')) {
$plugin
->submitForm($form, $form_state);
}
}
}
user_login_finalize($user);
// @todo Should finalize() be after user_login_finalize or before?!
// @todo This could be improved with EventDispatcher.
$this
->finalize();
$this->flood
->clear('tfa.failed_validation', $this->floodIdentifier);
$form_state
->setRedirect('<front>');
}
/**
* Run TFA process finalization.
*/
public function finalize() {
// Invoke plugin finalize.
if (method_exists($this->tfaValidationPlugin, 'finalize')) {
$this->tfaValidationPlugin
->finalize();
}
// Allow login plugins to act during finalization.
if (!empty($this->tfaLoginPlugins)) {
foreach ($this->tfaLoginPlugins as $plugin) {
if (method_exists($plugin, 'finalize')) {
$plugin
->finalize();
}
}
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
EntryForm:: |
protected | property | The date formatter service. | |
EntryForm:: |
protected | property | The flood control mechanism. | |
EntryForm:: |
protected | property | The flood control identifier. | |
EntryForm:: |
protected | property | Login plugin manager. | |
EntryForm:: |
protected | property | The login plugins. | |
EntryForm:: |
protected | property | TFA configuration object. | |
EntryForm:: |
protected | property | Validation plugin manager. | |
EntryForm:: |
protected | property | The validation plugin object. | |
EntryForm:: |
protected | property | User data service. | |
EntryForm:: |
public | function |
Form constructor. Overrides FormInterface:: |
|
EntryForm:: |
public static | function |
Creates service objects for the class constructor. Overrides FormBase:: |
|
EntryForm:: |
public | function | Run TFA process finalization. | |
EntryForm:: |
public | function |
Returns a unique string identifying the form. Overrides FormInterface:: |
|
EntryForm:: |
public | function |
If the form is passes validation, the user should get logged in. Overrides FormInterface:: |
|
EntryForm:: |
public | function |
Form validation handler. Overrides FormBase:: |
|
EntryForm:: |
public | function | EntryForm constructor. | |
FormBase:: |
protected | property | The config factory. | 1 |
FormBase:: |
protected | property | The request stack. | 1 |
FormBase:: |
protected | property | The route match. | |
FormBase:: |
protected | function | Retrieves a configuration object. | |
FormBase:: |
protected | function | Gets the config factory for this form. | 1 |
FormBase:: |
private | function | Returns the service container. | |
FormBase:: |
protected | function | Gets the current user. | |
FormBase:: |
protected | function | Gets the request object. | |
FormBase:: |
protected | function | Gets the route match. | |
FormBase:: |
protected | function | Gets the logger for a specific channel. | |
FormBase:: |
protected | function |
Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait:: |
|
FormBase:: |
public | function | Resets the configuration factory. | |
FormBase:: |
public | function | Sets the config factory for this form. | |
FormBase:: |
public | function | Sets the request stack object to use. | |
LinkGeneratorTrait:: |
protected | property | The link generator. | 1 |
LinkGeneratorTrait:: |
protected | function | Returns the link generator. | |
LinkGeneratorTrait:: |
protected | function | Renders a link to a route given a route name and its parameters. | |
LinkGeneratorTrait:: |
public | function | Sets the link generator service. | |
LoggerChannelTrait:: |
protected | property | The logger channel factory service. | |
LoggerChannelTrait:: |
protected | function | Gets the logger for a specific channel. | |
LoggerChannelTrait:: |
public | function | Injects the logger channel factory. | |
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
RedirectDestinationTrait:: |
protected | property | The redirect destination service. | 1 |
RedirectDestinationTrait:: |
protected | function | Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url. | |
RedirectDestinationTrait:: |
protected | function | Returns the redirect destination service. | |
RedirectDestinationTrait:: |
public | function | Sets the redirect destination service. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
UrlGeneratorTrait:: |
protected | property | The url generator. | |
UrlGeneratorTrait:: |
protected | function | Returns the URL generator service. | |
UrlGeneratorTrait:: |
public | function | Sets the URL generator service. | |
UrlGeneratorTrait:: |
protected | function | Generates a URL or path for a specific route based on the given parameters. |