Provide a way to utilise multiple Salesforce auth providers

Created on 16 April 2021, over 3 years ago
Updated 18 May 2023, over 1 year ago

Problem/Motivation

Currently we can have only one default auth provider. Is there way in which we can have multiple auth providers configured for Salesforce and each Salesforce instance can be used for different purposes.

✨ Feature request
Status

Active

Version

4.2

Component

salesforce.module

Created by

🇮🇳India drupalisedmanish

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇮🇳India omsingh89

    Our project had a requirement to map a webform to a different salesforce Instance other than the default salesforce auth provider selected.
    We are using only Salesforce Push trigger option, created a patch for this enhancement:

    • Provided a configration in mapping form '/admin/structure/salesforce/mappings/add' to choose the salesforce auth provider to push the current webform submission
    • Based on the Auth Provider selected, the Salesforce object will load, and also the salesforce fields.
    • Salesforce Push is working.

    Could others try this patch out?

  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.1 & MariaDB 10.3.22
    last update over 1 year ago
    run-tests.sh fatal error
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.1 & MariaDB 10.3.22
    last update over 1 year ago
    73 pass, 8 fail
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.1 & MariaDB 10.3.22
    last update over 1 year ago
    73 pass, 8 fail
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.1 & MariaDB 10.3.22
    last update over 1 year ago
    Patch Failed to Apply
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.1 & MariaDB 10.3.22
    last update over 1 year ago
    73 pass, 8 fail
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.1 & MySQL 8
    last update over 1 year ago
    78 pass, 2 fail
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.1 & MySQL 8
    last update over 1 year ago
    78 pass, 2 fail
  • 🇮🇳India omsingh89

    Patch for 5.0.3 salesforce version.
    Note: This patch is designed to work only for Salesforce Push module and its functionality.

  • 🇺🇸United States AaronBauman Philadelphia
  • 🇮🇳India omsingh89

    Patch for 5.1.0 salesforce version.
    Note: This patch is designed to work only for Salesforce Push module and its functionality.

  • Status changed to Needs work about 1 month ago
  • 🇦🇷Argentina dagmar Argentina

    I've been playing with the latest patch for some time now, my general felling is the approach of making provider_id = '' an optional parameter is very dangerous and complicates a lot the code.

    I think instead the provider_id should be a required parameter, and provide a hook_update_n to create a default one based on the current config. This will of course be a breaking compatibility change for custom code out there, but in the other hand tools like phpstan will allow to detect how to fix this properly.

    The same should apply to auth manager.

    I miss dreditor to review this .patch format, but I will do my best:

    +++ b/modules/salesforce_mapping/src/Entity/MappedObject.php
    @@ -409,7 +409,8 @@ class MappedObject extends RevisionableContentEntityBase implements MappedObject
           $result = $this->client()->objectUpdate(
             $mapping->getSalesforceObjectType(),
             $this->sfid(),
    -        $params->getParams()
    +        $params->getParams(),
    +        $mapping->provider_id
    

    Use $mapping->getProviderId() instead.

    @@ -203,14 +203,17 @@ class RestClient implements RestClientInterface {
       /**
        * {@inheritdoc}
        */
    -  public function isInit() {
    -    if (!$this->authProvider || !$this->authManager) {
    +  public function isInit($provider_id = '') {
    +    if (!$this->authProvider || !$this->authManager->getProvider($provider_id)) {
           return FALSE;
         }
         // If authToken is not set, try refreshing it before failing init.
         if (!$this->authToken) {
           try {
             $this->authToken = $this->authManager->refreshToken();
    +        if (!empty($provider_id)) {
    +          $this->authToken = $this->authManager->refreshToken($provider_id);
    +        }
             return isset($this->authToken);
           }
           catch (\Exception $e) {
    @@ -224,20 +227,26 @@ class RestClient implements RestClientInterface {
       /**
        * {@inheritdoc}
        */
    -  public function apiCall($path, $params = [], $method = 'GET', $returnObject = FALSE, array $headers = []) {
    -    if (!$this->isInit()) {
    +  public function apiCall($path, $params = [], $method = 'GET', $returnObject = FALSE, array $headers = [], $provider_id = '') {
    

    I think the provider Id should be required when initializing the rest client, and the provider id should not be set after the client is initialized, this allows to remove provider_id from all the methods of this class.

  • 🇺🇸United States jrearick Iowa

    We've been trying to use this patch, and found there is an issue salesforceClient->objectDescribe() in RestClient.php.

    On the initial call, it uses $provider_id to make the apiCall, but caches it without the provider_id context. When this is called later and uses the cached object, it's not aware of the provider id and may load the incorrect response from the cache. The symptom for us was that some salesforce leads were coming in with incomplete fields depending on what response was in the cache.

    We can't really make an assumption of provider_id here, so this also points towards provider_id being a required parameter.

        if (!$reset && ($cache = $this->cache->get('salesforce:object:' . $name))) {
          return $cache->data;
        }
        else {
          $response = new RestResponseDescribe($this->apiCall("sobjects/{$name}/describe", [], 'GET', TRUE, [], $provider_id));
    
          $this->cache->set('salesforce:object:' . $name, $response, $this->getRequestTime() + $this->getShortTermCacheLifetime(), ['salesforce']);
          return $response;
        }
    

    I think the proposal make provider_id requried for the rest client might help with this issue.

  • 🇺🇸United States jrearick Iowa

    If there are others trying to use the current patch for 5.1.x, I created a new patch to make objectDescribe require a provider_id and updated most of the internal calls to it. It also creates separate cache buckets for each provider ID. I feel this is more of a band-aid until a more resilient solution comes along.

  • Pipeline finished with Failed
    about 1 month ago
    Total: 226s
    #347350
  • Pipeline finished with Failed
    26 days ago
    Total: 242s
    #350930
  • Pipeline finished with Failed
    26 days ago
    Total: 193s
    #350950
  • 🇦🇷Argentina dagmar Argentina

    Alright. I finished my idea in the merge request.

    The plan is to override the default auth provider if needed. So, no api changes, and safe defaults for sites that do not specify any override.

    For developers the only new api change is the method

    $restClient->overrideAuthProvider('provider_id');
    

    Which changes the auth provider.

    I haven't had the change to fix the test yet, but if someone want's to take it, feel free to do it.

    The UI has been also modified to make clear that the auth provider set is overriding the default one.

  • Pipeline finished with Failed
    4 days ago
    Total: 247s
    #372862
  • Pipeline finished with Failed
    3 days ago
    Total: 199s
    #373925
  • Pipeline finished with Failed
    3 days ago
    Total: 243s
    #373972
Production build 0.71.5 2024