|
| 1 | +<?php |
| 2 | + |
| 3 | +/** |
| 4 | + * @file |
| 5 | + * OS2Web SimpleSAML functionality module. |
| 6 | + */ |
| 7 | + |
| 8 | +use Drupal\Core\Form\FormStateInterface; |
| 9 | +use Drupal\Core\Url; |
| 10 | + |
| 11 | +/** |
| 12 | + * Implements hook_form_FORM_ID_alter(). |
| 13 | + * |
| 14 | + * Adds redirect IPs settings to simplesamlphp_auth_local_settings_form. |
| 15 | + */ |
| 16 | +function os2web_simplesaml_form_simplesamlphp_auth_local_settings_form_alter(&$form, FormStateInterface $form_state, $form_id) { |
| 17 | + $config = \Drupal::config('os2web_simplesaml.settings'); |
| 18 | + |
| 19 | + $form['os2web_simplesaml_additional_settings'] = array( |
| 20 | + '#type' => 'fieldset', |
| 21 | + '#title' => t('OS2Web SimpleSAML additional settings'), |
| 22 | + ); |
| 23 | + $form['os2web_simplesaml_additional_settings']['redirect_ips'] = array( |
| 24 | + '#type' => 'textfield', |
| 25 | + '#title' => t("Redirect IP's to SimpleSAML login"), |
| 26 | + '#default_value' => $config->get('redirect_ips'), |
| 27 | + '#description' => t('Comma separated. Ex. 192.168.1.1,192.168.2.1'), |
| 28 | + ); |
| 29 | + $form['os2web_simplesaml_additional_settings']['redirect_trigger_path'] = array( |
| 30 | + '#type' => 'textfield', |
| 31 | + '#title' => t('Redirect triggering path'), |
| 32 | + '#default_value' => $config->get('redirect_trigger_path'), |
| 33 | + '#description' => t('The path that will trigger the redirect. NB! The caching for that path will be programmatically disabled.'), |
| 34 | + '#required' => TRUE, |
| 35 | + ); |
| 36 | + $form['os2web_simplesaml_additional_settings']['redirect_cookies_ttl'] = array( |
| 37 | + '#type' => 'number', |
| 38 | + '#min' => 0, |
| 39 | + '#step' => 10, |
| 40 | + '#title' => t('Redirect cookies time to live (TTL)'), |
| 41 | + '#default_value' => $config->get('redirect_cookies_ttl'), |
| 42 | + '#description' => t('Number of seconds, after which the positive or negative redirect decision will expire. Setting long time improves the performance, but IP rules change will take longer to become active for all users.'), |
| 43 | + '#required' => TRUE, |
| 44 | + ); |
| 45 | + |
| 46 | + $form['#validate'][] = 'os2web_simplesaml_form_validate'; |
| 47 | + $form['#submit'][] = 'os2web_simplesaml_form_submit'; |
| 48 | +} |
| 49 | + |
| 50 | +/** |
| 51 | + * Validation for simplesamlphp_auth_local_settings_form. |
| 52 | + * |
| 53 | + * Checks provided IP list format. |
| 54 | + */ |
| 55 | +function os2web_simplesaml_form_validate(&$form, FormStateInterface $form_state) { |
| 56 | + if ($form_state->hasValue('redirect_ips')) { |
| 57 | + $redirect_ips = $form_state->getValue('redirect_ips'); |
| 58 | + if (preg_match("/[^0-9.,]/", $redirect_ips)) { |
| 59 | + $form_state->setErrorByName('redirect_ips', t('Invalid format, must be comma separated. Ex. 192.168.1.1,192.168.2.1')); |
| 60 | + } |
| 61 | + } |
| 62 | + if ($form_state->hasValue('redirect_trigger_path')) { |
| 63 | + $redirect_trigger_path = $form_state->getValue('redirect_trigger_path'); |
| 64 | + $url = Url::fromUserInput($redirect_trigger_path); |
| 65 | + if (!$url->isRouted()) { |
| 66 | + $form_state->setErrorByName('redirect_trigger_path', t('Invalid URL, this URL does not exist')); |
| 67 | + } |
| 68 | + } |
| 69 | +} |
| 70 | + |
| 71 | +/** |
| 72 | + * Submit for simplesamlphp_auth_local_settings_form. |
| 73 | + * |
| 74 | + * Saves redirect_ips into configuration. |
| 75 | + */ |
| 76 | +function os2web_simplesaml_form_submit(&$form, FormStateInterface $form_state) { |
| 77 | + $redirect_ips = $form_state->getValue('redirect_ips'); |
| 78 | + $redirect_trigger_path = $form_state->getValue('redirect_trigger_path'); |
| 79 | + $redirect_cookies_ttl = $form_state->getValue('redirect_cookies_ttl'); |
| 80 | + |
| 81 | + $config = \Drupal::service('config.factory') |
| 82 | + ->getEditable('os2web_simplesaml.settings'); |
| 83 | + $config->set('redirect_ips', $redirect_ips); |
| 84 | + $config->set('redirect_trigger_path', $redirect_trigger_path); |
| 85 | + $config->set('redirect_cookies_ttl', $redirect_cookies_ttl); |
| 86 | + $config->save(); |
| 87 | + |
| 88 | + // Invalidating router cache, so that new settings are applied. |
| 89 | + \Drupal::service("router.builder")->rebuild(); |
| 90 | +} |
| 91 | + |
| 92 | +/** |
| 93 | + * Implements hook_entity_extra_field_info(). |
| 94 | + */ |
| 95 | +function os2web_simplesaml_entity_extra_field_info() { |
| 96 | + $fields = []; |
| 97 | + $fields['user']['user']['form']['os2web_simplesaml_uid'] = [ |
| 98 | + 'label' => t('SimpleSAML UID'), |
| 99 | + 'description' => '', |
| 100 | + 'weight' => 0, |
| 101 | + 'visible' => TRUE, |
| 102 | + ]; |
| 103 | + return $fields; |
| 104 | +} |
| 105 | + |
| 106 | +/** |
| 107 | + * Implements hook_form_FORM_ID_alter(). |
| 108 | + * |
| 109 | + * @see AccountForm::form() |
| 110 | + * @see os2web_simplesaml_user_form_includes() |
| 111 | + */ |
| 112 | +function os2web_simplesaml_form_user_form_alter(&$form, FormStateInterface $form_state, $form_id) { |
| 113 | + os2web_simplesaml_user_form_includes($form); |
| 114 | + |
| 115 | + // If the user has a simplesamlphp_auth authmap record, then fetch it and |
| 116 | + // prefill the field. |
| 117 | + $authmap = \Drupal::service('externalauth.authmap'); |
| 118 | + $account = $form_state->getFormObject()->getEntity(); |
| 119 | + $authname = $authmap->get($account->id(), 'simplesamlphp_auth'); |
| 120 | + if ($authname) { |
| 121 | + $form['os2web_simplesaml_uid']['#default_value'] = $authname; |
| 122 | + } |
| 123 | +} |
| 124 | + |
| 125 | +/** |
| 126 | + * Implements hook_form_FORM_ID_alter(). |
| 127 | + * |
| 128 | + * @see AccountForm::form() |
| 129 | + * @see os2web_simplesaml_user_form_includes() |
| 130 | + */ |
| 131 | +function os2web_simplesaml_form_user_register_form_alter(&$form, FormStateInterface $form_state, $form_id) { |
| 132 | + os2web_simplesaml_user_form_includes($form); |
| 133 | +} |
| 134 | + |
| 135 | +/** |
| 136 | + * Helper function to include the BC SimpleSAML on user forms. |
| 137 | + * |
| 138 | + * Alters the user register form to include a textfield for providing custom |
| 139 | + * SimpleSAML value. |
| 140 | + * |
| 141 | + * @param array $form |
| 142 | + * The user account form. |
| 143 | + * |
| 144 | + * @see os2web_simplesaml_user_form_submit() |
| 145 | + */ |
| 146 | +function os2web_simplesaml_user_form_includes(&$form) { |
| 147 | + // Getting SimpleSAML existing authname to use as an example. |
| 148 | + $query = \Drupal::database()->select('authmap', 'am') |
| 149 | + ->fields('am', ['authname']) |
| 150 | + ->condition('provider', 'simplesamlphp_auth') |
| 151 | + ->range(0, 1); |
| 152 | + $simplesamlExample = $query->execute()->fetchField(); |
| 153 | + |
| 154 | + $form['os2web_simplesaml_uid'] = [ |
| 155 | + '#type' => 'textfield', |
| 156 | + '#title' => t('SimpleSAML UID'), |
| 157 | + '#access' => \Drupal::currentUser()->hasPermission('change saml authentication setting'), |
| 158 | + '#description' => $simplesamlExample ? t('Example of the existing SimpleSAML entry from authmap table: <b>@simplesaml</b>', array('@simplesaml' => $simplesamlExample)) : t('Provide a string serves the UID of the user.') |
| 159 | + ]; |
| 160 | + |
| 161 | + // Adding custom validation. |
| 162 | + $form['#validate'][] = 'os2web_simplesaml_user_form_validate'; |
| 163 | + |
| 164 | + // Adding custom submit. |
| 165 | + $form['actions']['submit']['#submit'][] = 'os2web_simplesaml_user_form_submit'; |
| 166 | +} |
| 167 | + |
| 168 | +/** |
| 169 | + * Form validation handler for user_form. |
| 170 | + */ |
| 171 | +function os2web_simplesaml_user_form_validate($form, FormStateInterface $form_state) { |
| 172 | + $simplesaml_uid = NULL; |
| 173 | + if ($form_state->getValue('os2web_simplesaml_uid')) { |
| 174 | + $simplesaml_uid = $form_state->getValue('os2web_simplesaml_uid'); |
| 175 | + } |
| 176 | + |
| 177 | + if (!$form_state->getValue('simplesamlphp_auth_user_enable') && !empty($simplesaml_uid)) { |
| 178 | + $form_state->setErrorByName('os2web_simplesaml_uid', t('Field SimpleSAML UID is provided but SAML authentication is not checked, mapping will not be created')); |
| 179 | + } |
| 180 | +} |
| 181 | + |
| 182 | +/** |
| 183 | + * Form submission handler for user_form. |
| 184 | + */ |
| 185 | +function os2web_simplesaml_user_form_submit($form, FormStateInterface $form_state) { |
| 186 | + $authmap = \Drupal::service('externalauth.authmap'); |
| 187 | + $externalauth = \Drupal::service('externalauth.externalauth'); |
| 188 | + |
| 189 | + // Remove this user from the ExternalAuth authmap table. |
| 190 | + $authmap->delete($form_state->getValue('uid')); |
| 191 | + |
| 192 | + if ($form_state->getValue('os2web_simplesaml_uid')) { |
| 193 | + $simplesaml_uid = $form_state->getValue('os2web_simplesaml_uid'); |
| 194 | + } |
| 195 | + |
| 196 | + // Add an authmap entry for this account, so it can leverage SAML |
| 197 | + // authentication. |
| 198 | + if ($simplesaml_uid) { |
| 199 | + $account = $form_state->getFormObject()->getEntity(); |
| 200 | + $externalauth->linkExistingAccount($simplesaml_uid, 'simplesamlphp_auth', $account); |
| 201 | + } |
| 202 | +} |
0 commit comments