checklist = $checklist; $this->security = $security; $this->securityReview = $security_review; $this->dateFormatter = $dateFormatter; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), $container->get('security_review.checklist'), $container->get('security_review.security'), $container->get('security_review'), $container->get('date.formatter') ); } /** * {@inheritdoc} */ public function getFormId() { return 'security-review-settings'; } /** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { // Get the list of checks. $checks = $this->checklist->getChecks(); // Get the user roles. $roles = user_roles(); $options = []; foreach ($roles as $rid => $role) { $options[$rid] = $role->label(); } // Notify the user if anonymous users can create accounts. $message = ''; if (in_array(AccountInterface::AUTHENTICATED_ROLE, $this->security->defaultUntrustedRoles())) { $message = $this->t('You have allowed anonymous users to create accounts without approval so the authenticated role defaults to untrusted.'); } // Show the untrusted roles form element. $form['untrusted_roles'] = [ '#type' => 'checkboxes', '#title' => $this->t('Untrusted roles'), '#description' => $this->t( 'Define which roles are for less trusted users. The anonymous role defaults to untrusted. @message Most Security Review checks look for resources usable by untrusted roles.', ['@message' => $message] ), '#options' => $options, '#default_value' => $this->security->untrustedRoles(), ]; $form['advanced'] = [ '#type' => 'details', '#title' => $this->t('Advanced'), '#open' => TRUE, ]; // Show the logging setting. $form['advanced']['logging'] = [ '#type' => 'checkbox', '#title' => $this->t('Log checklist results and skips'), '#description' => $this->t('The result of each check and skip can be logged to watchdog for tracking.'), '#default_value' => $this->securityReview->isLogging(), ]; // Skipped checks. $values = []; $options = []; foreach ($checks as $check) { // Determine if check is being skipped. if ($check->isSkipped()) { $values[] = $check->id(); $label = $this->t( '@name skipped by UID @uid on @date', [ '@name' => $check->getTitle(), '@uid' => $check->skippedBy()->id(), '@date' => $this->dateFormatter->format($check->skippedOn()), ] ); } else { $label = $check->getTitle(); } $options[$check->id()] = $label; } $form['advanced']['skip'] = [ '#type' => 'checkboxes', '#title' => $this->t('Checks to skip'), '#description' => $this->t('Skip running certain checks. This can also be set on the Run & review page. It is recommended that you do not skip any checks unless you know the result is wrong or the process times out while running.'), '#options' => $options, '#default_value' => $values, ]; // Iterate through checklist and get check-specific setting pages. foreach ($checks as $check) { // Get the check's setting form. $check_form = $check->settings()->buildForm(); // If not empty, add it to the form. if (!empty($check_form)) { // If this is the first non-empty setting page initialize the 'details' if (!isset($form['advanced']['check_specific'])) { $form['advanced']['check_specific'] = [ '#type' => 'details', '#title' => $this->t('Check-specific settings'), '#open' => FALSE, '#tree' => TRUE, ]; } // Add the form. $sub_form = &$form['advanced']['check_specific'][$check->id()]; $title = $check->getTitle(); // If it's an external check, show its namespace. if ($check->getMachineNamespace() != 'security_review') { $title .= $this->t('%namespace', [ '%namespace' => $check->getNamespace(), ]); } $sub_form = [ '#type' => 'details', '#title' => $title, '#open' => TRUE, '#tree' => TRUE, 'form' => $check_form, ]; } } // Return the finished form. return parent::buildForm($form, $form_state); } /** * {@inheritdoc} */ public function validateForm(array &$form, FormStateInterface $form_state) { // Run validation for check-specific settings. if (isset($form['advanced']['check_specific'])) { $check_specific_values = $form_state->getValue('check_specific'); foreach ($this->checklist->getChecks() as $check) { $check_form = &$form['advanced']['check_specific'][$check->id()]; if (isset($check_form)) { $check->settings() ->validateForm($check_form, $check_specific_values[$check->id()]); } } } } /** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { // Frequently used configuration items. $check_settings = $this->config('security_review.checks'); // Save that the module has been configured. $this->securityReview->setConfigured(TRUE); // Save the new untrusted roles. $untrusted_roles = array_keys(array_filter($form_state->getValue('untrusted_roles'))); $this->securityReview->setUntrustedRoles($untrusted_roles); // Save the new logging setting. $logging = $form_state->getValue('logging') == 1; $this->securityReview->setLogging($logging); // Skip selected checks. $skipped = array_keys(array_filter($form_state->getValue('skip'))); foreach ($this->checklist->getChecks() as $check) { if (in_array($check->id(), $skipped)) { $check->skip(); } else { $check->enable(); } } // Save the check-specific settings. if (isset($form['advanced']['check_specific'])) { $check_specific_values = $form_state->getValue('check_specific'); foreach ($check_specific_values as $id => $values) { // Get corresponding Check. $check = $this->checklist->getCheckById($id); // Submit parameters. $check_form = &$form['advanced']['check_specific'][$id]['form']; $check_form_values = $check_specific_values[$id]['form']; // Submit. $check->settings()->submitForm($check_form, $check_form_values); } } // Commit the settings. $check_settings->save(); // Finish submitting the form. parent::submitForm($form, $form_state); } /** * {@inheritdoc} */ protected function getEditableConfigNames() { return ['security_review.checks']; } }