Including security review as a submodule - with patched for Yaffs.
[yaffs-website] / web / modules / contrib / security_review / src / Form / SettingsForm.php
1 <?php
2
3 /**
4  * @file
5  * Contains \Drupal\security_review\Form\SettingsForm.
6  */
7
8 namespace Drupal\security_review\Form;
9
10 use Drupal\Component\Utility\SafeMarkup;
11 use Drupal\Core\Config\ConfigFactoryInterface;
12 use Drupal\Core\Form\ConfigFormBase;
13 use Drupal\Core\Form\FormStateInterface;
14 use Drupal\Core\Session\AccountInterface;
15 use Drupal\security_review\Checklist;
16 use Drupal\security_review\Security;
17 use Drupal\security_review\SecurityReview;
18 use Symfony\Component\DependencyInjection\ContainerInterface;
19
20 /**
21  * Settings page for Security Review.
22  */
23 class SettingsForm extends ConfigFormBase {
24
25   /**
26    * The security_review.checklist service.
27    *
28    * @var \Drupal\security_review\Checklist
29    */
30   protected $checklist;
31
32   /**
33    * The security_review.security service.
34    *
35    * @var \Drupal\security_review\Security
36    */
37   protected $security;
38
39   /**
40    * The security_review service.
41    *
42    * @var \Drupal\security_review\SecurityReview
43    */
44   protected $securityReview;
45
46   /**
47    * Constructs a SettingsForm.
48    *
49    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
50    *   The config factory.
51    * @param \Drupal\security_review\Checklist $checklist
52    *   The security_review.checklist service.
53    * @param \Drupal\security_review\Security $security
54    *   The security_review.security service.
55    * @param \Drupal\security_review\SecurityReview $security_review
56    *   The security_review service.
57    */
58   public function __construct(ConfigFactoryInterface $config_factory, Checklist $checklist, Security $security, SecurityReview $security_review) {
59     parent::__construct($config_factory);
60     $this->checklist = $checklist;
61     $this->security = $security;
62     $this->securityReview = $security_review;
63   }
64
65   /**
66    * {@inheritdoc}
67    */
68   public static function create(ContainerInterface $container) {
69     return new static(
70       $container->get('config.factory'),
71       $container->get('security_review.checklist'),
72       $container->get('security_review.security'),
73       $container->get('security_review')
74     );
75   }
76
77   /**
78    * {@inheritdoc}
79    */
80   public function getFormId() {
81     return 'security-review-settings';
82   }
83
84   /**
85    * {@inheritdoc}
86    */
87   public function buildForm(array $form, FormStateInterface $form_state) {
88     // Get the list of checks.
89     $checks = $this->checklist->getChecks();
90
91     // Get the user roles.
92     $roles = user_roles();
93     $options = [];
94     foreach ($roles as $rid => $role) {
95       $options[$rid] = SafeMarkup::checkPlain($role->label());
96     }
97
98     // Notify the user if anonymous users can create accounts.
99     $message = '';
100     if (in_array(AccountInterface::AUTHENTICATED_ROLE, $this->security->defaultUntrustedRoles())) {
101       $message = $this->t('You have allowed anonymous users to create accounts without approval so the authenticated role defaults to untrusted.');
102     }
103
104     // Show the untrusted roles form element.
105     $form['untrusted_roles'] = [
106       '#type' => 'checkboxes',
107       '#title' => $this->t('Untrusted roles'),
108       '#description' => $this->t(
109         '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.',
110         ['@message' => $message]
111       ),
112       '#options' => $options,
113       '#default_value' => $this->security->untrustedRoles(),
114     ];
115
116     $form['advanced'] = [
117       '#type' => 'details',
118       '#title' => $this->t('Advanced'),
119       '#open' => TRUE,
120     ];
121
122     // Show the logging setting.
123     $form['advanced']['logging'] = [
124       '#type' => 'checkbox',
125       '#title' => $this->t('Log checklist results and skips'),
126       '#description' => $this->t('The result of each check and skip can be logged to watchdog for tracking.'),
127       '#default_value' => $this->securityReview->isLogging(),
128     ];
129
130     // Skipped checks.
131     $values = [];
132     $options = [];
133     foreach ($checks as $check) {
134       // Determine if check is being skipped.
135       if ($check->isSkipped()) {
136         $values[] = $check->id();
137         $label = $this->t(
138           '@name <em>skipped by UID @uid on @date</em>',
139           [
140             '@name' => $check->getTitle(),
141             '@uid' => $check->skippedBy()->id(),
142             '@date' => format_date($check->skippedOn()),
143           ]
144         );
145       }
146       else {
147         $label = $check->getTitle();
148       }
149       $options[$check->id()] = $label;
150     }
151     $form['advanced']['skip'] = [
152       '#type' => 'checkboxes',
153       '#title' => $this->t('Checks to skip'),
154       '#description' => $this->t('Skip running certain checks. This can also be set on the <em>Run & review</em> 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.'),
155       '#options' => $options,
156       '#default_value' => $values,
157     ];
158
159     // Iterate through checklist and get check-specific setting pages.
160     foreach ($checks as $check) {
161       // Get the check's setting form.
162       $check_form = $check->settings()->buildForm();
163
164       // If not empty, add it to the form.
165       if (!empty($check_form)) {
166         // If this is the first non-empty setting page initialize the 'details'
167         if (!isset($form['advanced']['check_specific'])) {
168           $form['advanced']['check_specific'] = [
169             '#type' => 'details',
170             '#title' => $this->t('Check-specific settings'),
171             '#open' => FALSE,
172             '#tree' => TRUE,
173           ];
174         }
175
176         // Add the form.
177         $sub_form = &$form['advanced']['check_specific'][$check->id()];
178
179         $title = $check->getTitle();
180         // If it's an external check, show its namespace.
181         if ($check->getMachineNamespace() != 'security_review') {
182           $title .= $this->t('%namespace', [
183             '%namespace' => $check->getNamespace(),
184           ]);
185         }
186         $sub_form = [
187           '#type' => 'details',
188           '#title' => $title,
189           '#open' => TRUE,
190           '#tree' => TRUE,
191           'form' => $check_form,
192         ];
193       }
194     }
195
196     // Return the finished form.
197     return parent::buildForm($form, $form_state);
198   }
199
200   /**
201    * {@inheritdoc}
202    */
203   public function validateForm(array &$form, FormStateInterface $form_state) {
204     // Run validation for check-specific settings.
205     if (isset($form['advanced']['check_specific'])) {
206       $check_specific_values = $form_state->getValue('check_specific');
207       foreach ($this->checklist->getChecks() as $check) {
208         $check_form = &$form['advanced']['check_specific'][$check->id()];
209         if (isset($check_form)) {
210           $check->settings()
211             ->validateForm($check_form, $check_specific_values[$check->id()]);
212         }
213       }
214     }
215   }
216
217   /**
218    * {@inheritdoc}
219    */
220   public function submitForm(array &$form, FormStateInterface $form_state) {
221     // Frequently used configuration items.
222     $check_settings = $this->config('security_review.checks');
223
224     // Save that the module has been configured.
225     $this->securityReview->setConfigured(TRUE);
226
227     // Save the new untrusted roles.
228     $untrusted_roles = array_keys(array_filter($form_state->getValue('untrusted_roles')));
229     $this->securityReview->setUntrustedRoles($untrusted_roles);
230
231     // Save the new logging setting.
232     $logging = $form_state->getValue('logging') == 1;
233     $this->securityReview->setLogging($logging);
234
235     // Skip selected checks.
236     $skipped = array_keys(array_filter($form_state->getValue('skip')));
237     foreach ($this->checklist->getChecks() as $check) {
238       if (in_array($check->id(), $skipped)) {
239         $check->skip();
240       }
241       else {
242         $check->enable();
243       }
244     }
245
246     // Save the check-specific settings.
247     if (isset($form['advanced']['check_specific'])) {
248       $check_specific_values = $form_state->getValue('check_specific');
249       foreach ($check_specific_values as $id => $values) {
250         // Get corresponding Check.
251         $check = $this->checklist->getCheckById($id);
252
253         // Submit parameters.
254         $check_form = &$form['advanced']['check_specific'][$id]['form'];
255         $check_form_values = $check_specific_values[$id]['form'];
256
257         // Submit.
258         $check->settings()->submitForm($check_form, $check_form_values);
259       }
260     }
261
262     // Commit the settings.
263     $check_settings->save();
264
265     // Finish submitting the form.
266     parent::submitForm($form, $form_state);
267   }
268
269   /**
270    * {@inheritdoc}
271    */
272   protected function getEditableConfigNames() {
273     return ['security_review.checks'];
274   }
275
276 }