class BakeryUncrumbleForm in Bakery Single Sign-On System 8.2
Contribute form.
Hierarchy
- class \Drupal\Core\Form\FormBase implements ContainerInjectionInterface, FormInterface uses DependencySerializationTrait, LoggerChannelTrait, MessengerTrait, LinkGeneratorTrait, RedirectDestinationTrait, UrlGeneratorTrait, StringTranslationTrait
- class \Drupal\bakery\Forms\BakeryUncrumbleForm implements ContainerInjectionInterface
Expanded class hierarchy of BakeryUncrumbleForm
File
- src/
Forms/ BakeryUncrumbleForm.php, line 18
Namespace
Drupal\bakery\FormsView source
class BakeryUncrumbleForm extends FormBase implements ContainerInjectionInterface {
/**
* For generating hashed password we check with database.
*
* @var \Drupal\Core\Password\PasswordInterface
*/
private $passwordHasher;
/**
* @var \Drupal\Core\Database\Connection
*/
private $database;
/**
* @var \Drupal\bakery\Kitchen
*/
private $kitchen;
/**
* Class constructor.
*/
public function __construct(PasswordInterface $password_hasher, Connection $connection, Kitchen $kitchen) {
// TODO some sore of session storage abstraction?
$this->passwordHasher = $password_hasher;
$this->database = $connection;
$this->kitchen = $kitchen;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container
->get('password'), $container
->get('database'), $container
->get('bakery.kitchen'));
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'bakery_forms_uncrumble_form';
}
/**
* Form to let users repair minor problems themselves.
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$cookie = $this->kitchen
->taste(Kitchen::CHOCOLATE_CHIP);
// Analyze.
$query = $this->database
->select('users_field_data', 'u')
->fields('u', [
'uid',
'name',
'mail',
])
->condition('u.uid', 0, '!=')
->condition('u.mail', '', '!=')
->where("LOWER(u.mail) = LOWER(:mail)", [
':mail' => $cookie['mail'],
]);
$result = $query
->execute();
$samemail = $result
->fetchObject();
$query = $this->database
->select('users_field_data', 'u')
->fields('u', [
'uid',
'name',
'mail',
])
->condition('u.uid', 0, '!=')
->where("LOWER(u.name) = LOWER(:name)", [
':name' => $cookie['name'],
]);
$result = $query
->execute();
$samename = $result
->fetchObject();
$form['name'] = [
'#type' => 'textfield',
'#title' => t('Username'),
'#value' => $cookie['name'],
'#disabled' => TRUE,
'#required' => TRUE,
];
$form['mail'] = [
'#type' => 'item',
'#title' => t('Email address'),
'#value' => $cookie['mail'],
'#required' => TRUE,
];
$form['pass'] = [
'#type' => 'password',
'#title' => t('Password'),
'#description' => t('Enter the password that accompanies your username.'),
'#required' => TRUE,
];
$form['submit'] = [
'#type' => 'submit',
'#value' => t('Repair account'),
'#weight' => 2,
];
$help = '';
$count = $this->database
->select('users_field_data', 'u')
->fields('u', [
'uid',
])
->condition('init', $cookie['init'], '=')
->countQuery()
->execute()
->fetchField();
if ($count > 1) {
$this
->messenger()
->addMessage(t('Multiple accounts are associated with your master account. This must be fixed manually. <a href="@contact">Please contact the site administrator.</a>', [
'%email' => $cookie['mail'],
'@contact' => $this
->configFactory()
->get('bakery.settings')
->get('bakery_master') . 'contact',
]));
$form['pass']['#disabled'] = TRUE;
$form['submit']['#disabled'] = TRUE;
}
elseif ($samename && $samemail && $samename->uid != $samemail->uid) {
$this
->messenger()
->addMessage(t('Both an account with matching name and an account with matching email address exist, but they are different accounts. This must be fixed manually. <a href="@contact">Please contact the site administrator.</a>', [
'%email' => $cookie['mail'],
'@contact' => $this
->configFactory()
->get('bakery.settings')
->get('bakery_master') . 'contact',
]));
$form['pass']['#disabled'] = TRUE;
$form['submit']['#disabled'] = TRUE;
}
elseif ($samename) {
$site_name = $this
->configFactory()
->get('system.site')
->get('name');
$help = t("An account with a matching username was found. Repairing it will reset the email address to match your master account. If this is the correct account, please enter your %site password.", [
'%site' => $site_name,
]);
// This is a borderline information leak.
// $form['mail']['#value'] = $samename->mail;.
$form['mail']['#value'] = t('<em>*hidden*</em>');
$form['mail']['#description'] = t('Will change to %new.', [
'%new' => $cookie['mail'],
]);
}
elseif ($samemail) {
$site_name = $this
->configFactory()
->get('system.site')
->get('name');
$help = t("An account with a matching email address was found. Repairing it will reset the username to match your master account. If this is the correct account, please enter your %site password.", [
'%site' => $site_name,
]);
$form['name']['#value'] = $samemail->name;
$form['name']['#description'] = t('Will change to %new.', [
'%new' => $cookie['name'],
]);
}
$form['help'] = [
'#weight' => -10,
'#markup' => $help,
];
return $form;
}
/**
* Validation for bakery_uncrumble form.
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
/*
* We are ignoring blocked status on purpose.
* The user is being repaired, not logged in.
*/
/** @var \Drupal\user\UserInterface|false $account */
$account = user_load_by_name($form_state
->getValue('name'));
if (!($account && $account
->id()) || $this->passwordHasher
->check($form_state
->getValue('pass'), $account
->getPassword())) {
$this
->logger('bakery')
->notice('Login attempt failed for %user while running uncrumble.', [
'%user' => $form_state
->getValue('name'),
]);
/*
* Can't pretend that it was the "username or password"
* so let's be helpful instead.
*/
$form_state
->setErrorByName('pass', t('Sorry, unrecognized password. If you have forgotten your %site password, please <a href="@contact">contact the site administrator.</a>', [
'%site' => $this
->configFactory()
->get('system.site')
->get('name'),
'@contact' => $this
->configFactory()
->get('bakery.settings')
->get('bakery_master') . 'contact',
]));
}
else {
$form_state
->setValue('bakery_uncrumble_account', $account);
}
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$account = $form_state
->getValue('bakery_uncrumble_account');
$form_state
->unsetValue('bakery_uncrumble_account');
$cookie = $this->kitchen
->taste(Kitchen::CHOCOLATE_CHIP);
$this->database
->update('users_field_data')
->fields([
'init' => $cookie['init'],
])
->condition('uid', $account
->id(), '=')
->execute();
$logger = $this
->logger('bakery');
$logger
->notice('uncrumble changed init field for uid %uid from %oldinit to %newinit', [
'%oldinit' => $account
->get('init')->value,
'%newinit' => $cookie['init'],
'%uid' => $account
->id(),
]);
$account
->setEmail($cookie['mail']);
$account
->save();
$logger
->notice('uncrumble updated name %name_old to %name_new, mail %mail_old to %mail_new on uid %uid.', [
'%name_old' => $account
->getAccountName(),
'%name_new' => $cookie['name'],
'%mail_old' => $account
->getEmail(),
'%mail_new' => $cookie['mail'],
'%uid' => $account
->id(),
]);
$this
->messenger()
->addMessage(t('Your account has been repaired.'));
$form_state
->setRedirect('user.page');
}
/**
* Only let people with actual problems mess with uncrumble.
*/
public function uncrumbleAccess(Request $request = NULL) {
// Work around https://www.drupal.org/project/drupal/issues/2786941
$request = $request ?? \Drupal::request();
if ($this
->currentUser()
->isAnonymous() && $request
->getSession()
->get('BAKERY_CRUMBLED', FALSE)) {
return AccessResult::allowed();
}
return AccessResult::forbidden();
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
BakeryUncrumbleForm:: |
private | property | ||
BakeryUncrumbleForm:: |
private | property | ||
BakeryUncrumbleForm:: |
private | property | For generating hashed password we check with database. | |
BakeryUncrumbleForm:: |
public | function |
Form to let users repair minor problems themselves. Overrides FormInterface:: |
|
BakeryUncrumbleForm:: |
public static | function |
Instantiates a new instance of this class. Overrides FormBase:: |
|
BakeryUncrumbleForm:: |
public | function |
Returns a unique string identifying the form. Overrides FormInterface:: |
|
BakeryUncrumbleForm:: |
public | function |
Form submission handler. Overrides FormInterface:: |
|
BakeryUncrumbleForm:: |
public | function | Only let people with actual problems mess with uncrumble. | |
BakeryUncrumbleForm:: |
public | function |
Validation for bakery_uncrumble form. Overrides FormBase:: |
|
BakeryUncrumbleForm:: |
public | function | Class constructor. | |
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 | |
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. |