You are here

public function SettingsForm::buildForm in Two-factor Authentication (TFA) 8

Form constructor.

Parameters

array $form: An associative array containing the structure of the form.

\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.

Return value

array The form structure.

Overrides ConfigFormBase::buildForm

File

src/Form/SettingsForm.php, line 121

Class

SettingsForm
The admin configuration page.

Namespace

Drupal\tfa\Form

Code

public function buildForm(array $form, FormStateInterface $form_state) {
  $config = $this
    ->config('tfa.settings');
  $form = [];

  // Get Login Plugins.
  $login_plugins = $this->tfaLogin
    ->getDefinitions();

  // Get Send Plugins.
  $send_plugins = $this->tfaSend
    ->getDefinitions();

  // Get Validation Plugins.
  $validation_plugins = $this->tfaValidation
    ->getDefinitions();

  // Get validation plugin labels.
  $validation_plugins_labels = [];
  foreach ($validation_plugins as $key => $plugin) {
    $validation_plugins_labels[$plugin['id']] = $plugin['label']
      ->render();
  }

  // Fetching all available encryption profiles.
  $encryption_profiles = $this->encryptionProfileManager
    ->getAllEncryptionProfiles();
  $plugins_empty = $this
    ->dataEmptyCheck($validation_plugins, $this
    ->t('No plugins available for validation. See the TFA help documentation for setup.'));
  $encryption_profiles_empty = $this
    ->dataEmptyCheck($encryption_profiles, $this
    ->t('No Encryption profiles available. <a href=":add_profile_url">Add an encryption profile</a>.', [
    ':add_profile_url' => Url::fromRoute('entity.encryption_profile.add_form')
      ->toString(),
  ]));
  if ($plugins_empty || $encryption_profiles_empty) {
    $form_state
      ->cleanValues();

    // Return form instead of parent::BuildForm to avoid the save button.
    return $form;
  }

  // Enable TFA checkbox.
  $form['tfa_enabled'] = [
    '#type' => 'checkbox',
    '#title' => $this
      ->t('Enable TFA'),
    '#default_value' => $config
      ->get('enabled') && !empty($encryption_profiles),
    '#description' => $this
      ->t('Enable TFA for account authentication.'),
    '#disabled' => empty($encryption_profiles),
  ];
  $enabled_state = [
    'visible' => [
      ':input[name="tfa_enabled"]' => [
        'checked' => TRUE,
      ],
    ],
  ];
  $form['tfa_required_roles'] = [
    '#type' => 'checkboxes',
    '#title' => $this
      ->t('Roles required to set up TFA'),
    '#options' => array_map('\\Drupal\\Component\\Utility\\Html::escape', user_role_names(TRUE)),
    '#default_value' => $config
      ->get('required_roles') ?: [],
    '#description' => $this
      ->t('Require users with these roles to set up TFA'),
    '#states' => $enabled_state,
    '#required' => FALSE,
  ];
  $form['tfa_allowed_validation_plugins'] = [
    '#type' => 'checkboxes',
    '#title' => $this
      ->t('Allowed Validation plugins'),
    '#options' => $validation_plugins_labels,
    '#default_value' => $config
      ->get('allowed_validation_plugins') ?: [
      'tfa_totp',
    ],
    '#description' => $this
      ->t('Plugins that can be setup by users for various TFA processes.'),
    // Show only when TFA is enabled.
    '#states' => $enabled_state,
    '#required' => TRUE,
  ];
  $form['tfa_validate'] = [
    '#type' => 'select',
    '#title' => $this
      ->t('Default Validation plugin'),
    '#options' => $validation_plugins_labels,
    '#default_value' => $config
      ->get('default_validation_plugin') ?: 'tfa_totp',
    '#description' => $this
      ->t('Plugin that will be used as the default TFA process.'),
    // Show only when TFA is enabled.
    '#states' => $enabled_state,
    '#required' => TRUE,
  ];

  // Validation plugin related settings.
  // $validation_plugins_labels has the plugin ids as the key.
  $form['validation_plugin_settings'] = [
    '#type' => 'fieldset',
    '#title' => $this
      ->t('Extra Settings'),
    '#descrption' => $this
      ->t('Extra plugin settings.'),
    '#tree' => TRUE,
    '#states' => $enabled_state,
  ];
  foreach ($validation_plugins_labels as $key => $val) {
    $instance = $this->tfaValidation
      ->createInstance($key, [
      'uid' => $this
        ->currentUser()
        ->id(),
    ]);
    if (method_exists($instance, 'buildConfigurationForm')) {
      $validation_enabled_state = [
        'visible' => [
          [
            ':input[name="tfa_enabled"]' => [
              'checked' => TRUE,
            ],
            ':input[name="tfa_allowed_validation_plugins[' . $key . ']"]' => [
              'checked' => TRUE,
            ],
          ],
          [
            'select[name="tfa_validate"]' => [
              'value' => $key,
            ],
          ],
        ],
      ];
      $form['validation_plugin_settings'][$key . '_container'] = [
        '#type' => 'container',
        '#states' => $validation_enabled_state,
      ];
      $form['validation_plugin_settings'][$key . '_container']['title'] = [
        '#type' => 'html_tag',
        '#tag' => 'h3',
        '#value' => $val,
      ];
      $form['validation_plugin_settings'][$key . '_container']['form'] = $instance
        ->buildConfigurationForm($config, $validation_enabled_state);
      $form['validation_plugin_settings'][$key . '_container']['form']['#parents'] = [
        'validation_plugin_settings',
        $key,
      ];
    }
  }

  // The encryption profiles select box.
  $encryption_profile_labels = [];
  foreach ($encryption_profiles as $encryption_profile) {
    $encryption_profile_labels[$encryption_profile
      ->id()] = $encryption_profile
      ->label();
  }
  $form['encryption_profile'] = [
    '#type' => 'select',
    '#title' => $this
      ->t('Encryption Profile'),
    '#options' => $encryption_profile_labels,
    '#description' => $this
      ->t('Encryption profiles to encrypt the secret'),
    '#default_value' => $config
      ->get('encryption'),
    '#states' => $enabled_state,
    '#required' => TRUE,
  ];
  $skip_value = $config
    ->get('validation_skip');
  $form['validation_skip'] = [
    '#type' => 'number',
    '#title' => $this
      ->t('Skip Validation'),
    '#default_value' => isset($skip_value) ? $skip_value : 3,
    '#description' => $this
      ->t('No. of times a user without having setup tfa validation can login.'),
    '#size' => 2,
    '#states' => $enabled_state,
    '#required' => TRUE,
  ];

  // Enable login plugins.
  $login_form_array = [];
  foreach ($login_plugins as $login_plugin) {
    $id = $login_plugin['id'];
    $title = $login_plugin['label']
      ->render();
    $login_form_array[$id] = (string) $title;
  }
  $form['tfa_login'] = [
    '#type' => 'checkboxes',
    '#title' => $this
      ->t('Login plugins'),
    '#options' => $login_form_array,
    '#default_value' => $config
      ->get('login_plugins') ? $config
      ->get('login_plugins') : [],
    '#description' => $this
      ->t('Plugins that can allow a user to skip the TFA process. If any plugin returns true the user will not be required to follow TFA. <strong>Use with caution.</strong>'),
  ];

  // Enable send plugins.
  if (count($send_plugins)) {
    $send_form_array = [];
    foreach ($send_plugins as $send_plugin) {
      $id = $send_plugin['id'];
      $title = $send_plugin['label']
        ->render();
      $send_form_array[$id] = (string) $title;
    }
    $form['tfa_send'] = [
      '#type' => 'checkboxes',
      '#title' => $this
        ->t('Send plugins'),
      '#options' => $send_form_array,
      '#default_value' => $config
        ->get('send_plugins') ? $config
        ->get('send_plugins') : [],
      '#description' => $this
        ->t('TFA Send Plugins, like TFA Twilio'),
    ];
  }
  $form['tfa_flood'] = [
    '#type' => 'fieldset',
    '#title' => $this
      ->t('TFA Flood Settings'),
    '#description' => $this
      ->t('Configure the TFA Flood Settings.'),
    '#states' => $enabled_state,
  ];

  // Flood control identifier.
  $form['tfa_flood']['tfa_flood_uid_only'] = [
    '#type' => 'checkbox',
    '#title' => $this
      ->t('Flood Control With UID Only'),
    '#default_value' => $config
      ->get('tfa_flood_uid_only') ?: 0,
    '#description' => $this
      ->t('Flood control on the basis of uid only.'),
  ];

  // Flood window. Defaults to 5min.
  $form['tfa_flood']['tfa_flood_window'] = [
    '#type' => 'number',
    '#title' => $this
      ->t('TFA Flood Window'),
    '#default_value' => $config
      ->get('tfa_flood_window') ?: 300,
    '#description' => $this
      ->t('TFA Flood Window.'),
    '#min' => 1,
    '#size' => 5,
    '#required' => TRUE,
  ];

  // Flood threshold. Defaults to 6 failed attempts.
  $form['tfa_flood']['tfa_flood_threshold'] = [
    '#type' => 'number',
    '#title' => $this
      ->t('TFA Flood Threshold'),
    '#default_value' => $config
      ->get('tfa_flood_threshold') ?: 6,
    '#description' => $this
      ->t('TFA Flood Threshold.'),
    '#min' => 1,
    '#size' => 2,
    '#required' => TRUE,
  ];

  // Email configurations.
  if ($config
    ->get('mail') === NULL) {
    $message = $this
      ->t('Email settings missing. If this is the first time you are seeing this error after upgrading the TFA module, then please make sure you have run the required @update_link function.', [
      '@update_link' => Link::createFromRoute('update', 'system.status')
        ->toString(),
    ]);
    $this
      ->messenger()
      ->addError($message);
  }
  $form['mail'] = [
    '#type' => 'vertical_tabs',
    '#title' => $this
      ->t('Emails'),
    '#default_tab' => 'edit-tfa-enabled-configuration',
  ];
  $form['tfa_enabled_configuration'] = [
    '#type' => 'details',
    '#title' => $this
      ->t('User enabled TFA validation method'),
    '#description' => $this
      ->t('This email is sent to the user when they enable a TFA validation method on their account. Available tokens are: [site] and [user]. Common variables are: [site:name], [site:url], [user:display-name], [user:account-name], and [user:mail].'),
    '#group' => 'mail',
    'tfa_enabled_configuration_subject' => [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Subject'),
      '#default_value' => $config
        ->get('mail.tfa_enabled_configuration.subject'),
      '#required' => TRUE,
    ],
    'tfa_enabled_configuration_body' => [
      '#type' => 'textarea',
      '#title' => $this
        ->t('Body'),
      '#default_value' => $config
        ->get('mail.tfa_enabled_configuration.body'),
      '#required' => TRUE,
      '#attributes' => [
        'rows' => 10,
      ],
    ],
  ];
  $form['tfa_disabled_configuration'] = [
    '#type' => 'details',
    '#title' => $this
      ->t('User disabled TFA validation method'),
    '#description' => $this
      ->t('This email is sent to the user when they disable a TFA validation method on their account. Available tokens are: [site] and [user]. Common variables are: [site:name], [site:url], [user:display-name], [user:account-name], and [user:mail].'),
    '#group' => 'mail',
    'tfa_disabled_configuration_subject' => [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Subject'),
      '#default_value' => $config
        ->get('mail.tfa_disabled_configuration.subject'),
      '#required' => TRUE,
    ],
    'tfa_disabled_configuration_body' => [
      '#type' => 'textarea',
      '#title' => $this
        ->t('Body'),
      '#default_value' => $config
        ->get('mail.tfa_disabled_configuration.body'),
      '#required' => TRUE,
      '#attributes' => [
        'rows' => 10,
      ],
    ],
  ];
  $form['help_text'] = [
    '#type' => 'textfield',
    '#title' => $this
      ->t('Help text'),
    '#description' => $this
      ->t('Text to display when a user is locked out and blocked from logging in.'),
    '#default_value' => $config
      ->get('help_text'),
    '#required' => TRUE,
  ];
  return parent::buildForm($form, $form_state);
}