You are here

public function KeyEntityFormEnhancer::validateForm in Apigee Edge 8

Additional validation handler for Apigee Edge authentication key forms.

Parameters

array $form: Form render array.

\Drupal\Core\Form\FormStateInterface $form_state: Form state object.

File

src/KeyEntityFormEnhancer.php, line 275

Class

KeyEntityFormEnhancer
Enhances Apigee Edge related Key entity add/edit forms.

Namespace

Drupal\apigee_edge

Code

public function validateForm(array &$form, FormStateInterface $form_state) : void {

  // Sanity check, if this is not a Apigee Edge Authentication key form
  // do nothing.
  if (!$this
    ->isApigeeKeyTypeAuthForm($form_state)) {
    return;
  }

  // Only call this when form is saved or "Test connection" is clicked.
  if (!in_array($form_state
    ->getTriggeringElement()['#name'] ?? [], [
    'test_connection',
    'op',
  ])) {
    return;
  }

  // If there is a form error already do not continue.
  if (!empty($form_state
    ->getErrors())) {
    return;
  }

  /** @var \Drupal\key\KeyInterface $key */
  $key = $form_state
    ->getFormObject()
    ->getEntity();

  // Check whether or not we know how to write to this key.
  if ($this
    ->keyIsWritable($key)) {

    // When form gets saved, key values are already processed.
    if (isset($form_state
      ->getStorage()['key_value']['processed_submitted'])) {
      $key_value = $form_state
        ->getStorage()['key_value']['processed_submitted'];
    }
    else {

      // When "Test connection" reloads the page they are not yet processed.
      // @see \Drupal\key\Form\KeyFormBase::createPluginFormState()
      $key_input_plugin_form_state = clone $form_state;
      $key_input_plugin_form_state
        ->setValues($form_state
        ->getValue('key_input_settings', []));

      // @see \Drupal\key\Form\KeyFormBase::validateForm()
      $key_input_processed_values = $key
        ->getKeyInput()
        ->processSubmittedKeyValue($key_input_plugin_form_state);
      $key_value = $key_input_processed_values['processed_submitted'];

      // Although, if the key exists, the key_value storage contains the
      // saved key. We must remove that from the storage otherwise an
      // invalid combination of the saved key values and the new values from
      // the input fields gets sent to Apigee Edge.
      $key_value_from_storage =& $form_state
        ->get('key_value');
      unset($key_value_from_storage['original'], $key_value_from_storage['processed_original']);
    }

    // Create a temp key for testing without saving it.
    $random = new Random();

    /** @var \Drupal\key\KeyInterface $test_key */
    $test_key = $this->entityTypeManager
      ->getStorage('key')
      ->create([
      'id' => strtolower($random
        ->name(16)),
      'key_type' => $key
        ->getKeyType()
        ->getPluginID(),
      'key_input' => $key
        ->getKeyInput()
        ->getPluginID(),
      'key_provider' => 'config',
      'key_provider_settings' => [
        'key_value' => $key_value,
      ],
    ]);
  }
  else {

    // There will be no input form for the key since it's not writable so
    // just use the actual key for testing.
    $test_key = clone $key;
  }

  /** @var \Drupal\apigee_edge\Plugin\KeyType\ApigeeAuthKeyType $test_key_type */
  $test_key_type = $test_key
    ->getKeyType();
  $test_auth_type = $test_key_type
    ->getAuthenticationType($test_key);
  try {
    if (in_array($test_auth_type, [
      EdgeKeyTypeInterface::EDGE_AUTH_TYPE_OAUTH,
      EdgeKeyTypeInterface::EDGE_AUTH_TYPE_JWT,
    ])) {

      // Check the requirements first.
      $this->oauthTokenStorage
        ->checkRequirements();

      // Clear existing OAuth token data.
      $this
        ->cleanUpOauthTokenData();
    }

    // Test the connection.
    $this->connector
      ->testConnection($test_key);
    $this
      ->messenger()
      ->addStatus($this
      ->t('Connection successful.'));

    // Based on type of organization, cache needs to clear.
    drupal_flush_all_caches();
  } catch (\Exception $exception) {
    watchdog_exception('apigee_edge', $exception);
    $form_state
      ->setError($form, $this
      ->t('@suggestion Error message: %response', [
      '@suggestion' => $this
        ->createSuggestion($exception, $test_key),
      '%response' => $exception
        ->getMessage(),
    ]));

    // Display debug information.
    $form['settings']['debug']['#access'] = $form['settings']['debug']['debug_text']['#access'] = TRUE;
    $form['settings']['debug']['debug_text']['#value'] = $this
      ->createDebugText($exception, $test_key);

    // In case of a form validation error the password field should
    // still not clear the submitted value.
    // \Drupal\apigee_edge\Plugin\KeyInput\ApigeeAuthKeyInput::buildConfigurationForm()
    // does not get called in this case.
    $is_provider_env = $test_key && $test_key
      ->getKeyProvider()
      ->getPluginId() === 'env';
    $is_provider_file = $test_key && $test_key
      ->getKeyProvider()
      ->getPluginId() === 'file';
    if ($test_key_type
      ->getInstanceType($test_key) != EdgeKeyTypeInterface::INSTANCE_TYPE_HYBRID && !$is_provider_env && !$is_provider_file) {
      $form['settings']['input_section']['key_input_settings']['password']['#attributes']['value'] = $test_key_type
        ->getPassword($test_key);
    }
  } finally {

    // Clear Oauth token data that may have been saved during testing
    // connection or left behind when authentication type changed from OAuth
    // to basic.
    $this
      ->cleanUpOauthTokenData();
  }
}