Skip to content
Snippets Groups Projects
SalesforceAuthProviderPluginBase.php 8.24 KiB
Newer Older
<?php

namespace Drupal\salesforce;

use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\Core\Routing\TrustedRedirectResponse;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\salesforce\Rest\SalesforceIdentity;
use Drupal\salesforce\Storage\SalesforceAuthTokenStorageInterface;
use OAuth\Common\Http\Client\ClientInterface;
use OAuth\Common\Http\Uri\Uri;
use OAuth\Common\Token\TokenInterface;
use OAuth\OAuth2\Service\Salesforce;
use Symfony\Component\DependencyInjection\ContainerInterface;
Aaron Bauman's avatar
Aaron Bauman committed
/**
 * Shared methods for auth providers.
 */
abstract class SalesforceAuthProviderPluginBase extends Salesforce implements SalesforceAuthProviderInterface {

  use StringTranslationTrait;
  use DependencySerializationTrait;
  use MessengerTrait;

  /**
Aaron Bauman's avatar
Aaron Bauman committed
   * Credentials.
   *
   * @var \Drupal\salesforce\Consumer\SalesforceCredentials
   */
  protected $credentials;

Aaron Bauman's avatar
Aaron Bauman committed
  /**
   * Configuration.
   *
   * @var array
   */
  protected $configuration;

Aaron Bauman's avatar
Aaron Bauman committed
  /**
   * Token storage.
   *
   * @var \Drupal\salesforce\Storage\SalesforceAuthTokenStorageInterface
   */
  protected $storage;

Aaron Bauman's avatar
Aaron Bauman committed
  /**
   * Provider id, e.g. jwt, oauth.
   *
   * @var string
   */
  protected $pluginId;

  /**
   * Plugin definition.
   *
   * @var array
   */
  protected $pluginDefinition;

  /**
   * Instance id, e.g. "sandbox1" or "production".
Aaron Bauman's avatar
Aaron Bauman committed
   *
   * @var string
   */
  /**
   * SalesforceOAuthPlugin constructor.
   *
   * @param array $configuration
   *   Plugin configuration.
   * @param string $plugin_id
   *   Plugin id.
   * @param mixed $plugin_definition
   *   Plugin definition.
   * @param \OAuth\Common\Http\Client\ClientInterface $httpClient
   *   The oauth http client.
   * @param \Drupal\salesforce\Storage\SalesforceAuthTokenStorageInterface $storage
   *   Auth token storage service.
   *
   * @throws \OAuth\OAuth2\Service\Exception\InvalidScopeException
   *   Comment.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, ClientInterface $httpClient, SalesforceAuthTokenStorageInterface $storage) {
Aaron Bauman's avatar
Aaron Bauman committed
    $this->id = !empty($configuration['id']) ? $configuration['id'] : NULL;
    $this->configuration = $configuration;
    $this->pluginDefinition = $plugin_definition;
    $this->pluginId = $plugin_id;
    $this->credentials = $this->getCredentials();
    parent::__construct($this->getCredentials(), $httpClient, $storage, [], new Uri($this->getCredentials()->getLoginUrl()));
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    $configuration = array_merge(static::defaultConfiguration(), $configuration);
    return new static($configuration, $plugin_id, $plugin_definition, $container->get('salesforce.http_client_wrapper'), $container->get('salesforce.auth_token_storage'));
  }

Aaron Bauman's avatar
Aaron Bauman committed
  /**
   * {@inheritdoc}
   */
  public static function defaultConfiguration() {
    return [
      'consumer_key' => '',
      'login_url' => 'https://test.salesforce.com',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function label() {
    return $this->getPluginDefinition()['label'];
  }

  /**
   * {@inheritdoc}
   */
  public function id() {
    return $this->id;
  }

  /**
   * {@inheritdoc}
   */
  public function getPluginId() {
  }

  /**
   * {@inheritdoc}
   */
  public function getPluginDefinition() {
  }

  /**
   * {@inheritdoc}
   */
  public function getConfiguration($key = NULL) {
    if ($key !== NULL) {
      return !empty($this->configuration[$key]) ? $this->configuration[$key] : NULL;
    }
    return $this->configuration;
  }

  /**
   * {@inheritdoc}
   */
  public function setConfiguration(array $configuration) {
    $this->configuration = $configuration;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {

  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $this->setConfiguration($form_state->getValue('provider_settings'));
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
    if ($form_state->getResponse() instanceof TrustedRedirectResponse) {
      // If we're redirecting off-site, do not proceed with save operation.
      // We'll finish saving form input when we complete the OAuth handshake
      // from Salesforce.
      return FALSE;
    }

    // Initialize identity if token is available.
    if (!$this->hasAccessToken()) {
      return TRUE;
    }
Aaron Bauman's avatar
Aaron Bauman committed
    $token = $this->getAccessToken();
    }
    catch (\Exception $e) {
      watchdog_exception('salesforce', $e);
      $this->messenger()->addError($e->getMessage());
      $form_state->disableRedirect();
      return FALSE;
    }
Aaron Bauman's avatar
Aaron Bauman committed
    return TRUE;
  /**
   * {@inheritdoc}
   */
  public function requestAccessToken($code, $state = NULL) {
    $token = parent::requestAccessToken($code, $state);
    $this->refreshIdentity($token);
    return $token;
  }

  /**
   * {@inheritdoc}
   */
  public function refreshAccessToken(TokenInterface $token) {
    $token = parent::refreshAccessToken($token);
    $this->refreshIdentity($token);
    return $token;
  }

  /**
   * {@inheritdoc}
   */
  public function refreshIdentity(TokenInterface $token) {
    $headers = [
      'Authorization' => 'OAuth ' . $token->getAccessToken(),
      'Content-type' => 'application/json',
    ];
    $data = $token->getExtraParams();
    $response = $this->httpClient->retrieveResponse(new Uri($data['id']), [], $headers);
    $identity = new SalesforceIdentity($response);
    $this->storage->storeIdentity($this->service(), $identity);
    return $identity;
  }

Aaron Bauman's avatar
Aaron Bauman committed
  /**
   * {@inheritdoc}
   */
    if (empty($this->credentials) || !$this->credentials->isValid()) {
      $pluginDefinition = $this->getPluginDefinition();
      $this->credentials = $pluginDefinition['credentials_class']::create($this->configuration);
    }
    return $this->credentials;
  }

  /**
   * {@inheritdoc}
   */
  public function getAuthorizationEndpoint() {
    return new Uri($this->getCredentials()->getLoginUrl() . static::AUTH_ENDPOINT_PATH);
  }

  /**
   * {@inheritdoc}
   */
  public function getAccessTokenEndpoint() {
    return new Uri($this->getCredentials()->getLoginUrl() . static::AUTH_TOKEN_PATH);
  }

  /**
   * {@inheritdoc}
   */
  public function hasAccessToken() {
    return $this->storage ? $this->storage->hasAccessToken($this->id()) : FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function getAccessToken() {
    return $this->storage->retrieveAccessToken($this->id());
  }

Aaron Bauman's avatar
Aaron Bauman committed
  /**
   * {@inheritdoc}
   */
  public function revokeAccessToken() {
    return $this->storage->clearToken($this->id());
  }

  /**
   * {@inheritdoc}
   */
  public function getInstanceUrl() {
    return $this->getAccessToken()->getExtraParams()['instance_url'] ?? '';
Aaron Bauman's avatar
Aaron Bauman committed
  /**
   * {@inheritdoc}
   */
  public function getApiEndpoint($api_type = 'rest') {
    $identity = $this->getIdentity();
    if (empty($identity)) {
      throw new IdentityNotFoundException();
Aaron Bauman's avatar
Aaron Bauman committed
    }
    return $identity->getUrl($api_type, $this->getApiVersion());
Aaron Bauman's avatar
Aaron Bauman committed
  }

  /**
   * {@inheritdoc}
   */
  public function getApiVersion() {
    $version = \Drupal::config('salesforce.settings')->get('rest_api_version.version');
    if (empty($version) || \Drupal::config('salesforce.settings')->get('use_latest')) {
      return self::LATEST_API_VERSION;
    }
    return \Drupal::config('salesforce.settings')->get('rest_api_version.version');
  }

  /**
   * {@inheritdoc}
   */
  public function getIdentity() {
    $identity = $this->storage->retrieveIdentity($this->id());
    if (empty($identity)) {
      throw new IdentityNotFoundException();
    }
    return $identity;
  }

  /**
   * {@inheritdoc}
   */
  public function service() {
    return $this->id();
  }

  /**
Aaron Bauman's avatar
Aaron Bauman committed
   * Accessor to the storage adapter to be able to retrieve tokens.
   *
   * @return \Drupal\salesforce\Storage\SalesforceAuthTokenStorageInterface
Aaron Bauman's avatar
Aaron Bauman committed
   *   The token storage.
   */
  public function getStorage() {
    return $this->storage;
  }

Aaron Bauman's avatar
Aaron Bauman committed
}