Support switching the account that runs the operation

Created on 30 August 2023, over 1 year ago

Problem/Motivation

Running operations as the anonymous user e.g. via Drush or cron, can result in problems with access to entities being imported. Support switching to another user in a pre-initiate event.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Feature request
Status

Active

Version

4.0

Component

Code

Created by

🇵🇪Peru krystalcode

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

Merge Requests

Comments & Activities

  • Issue created by @krystalcode
  • 🇵🇪Peru krystalcode

    The current implementation on the MRs does the account switching in an event subscriber. This, however, causes a problem in that
    switching back will not happen if there's an error in the following cases:

    - If an operation is cancelled by a pre-initiate subscriber.
    - If there's a fatal error in another pre-initiate subscriber.
    - If there's a fatal error in another post-terminate subscriber.

    Here's example code.

    $cancel = $this->preInitiate(
          Events::REMOTE_LIST_PRE_INITIATE,
          'import_list',
          $context,
          $sync
        );
        if ($cancel) {
          return;
        }
    
        try {
          $this->doImportRemoteList($sync, $filters, $options, $context);
        }
        finally {
          // Notify subscribers that the operation has terminated.
          $this->postTerminate(
            Events::REMOTE_LIST_POST_TERMINATE,
            'import_list',
            $context,
            $sync
          );
        }
    

    We therefore need to move account switching from an event subscriber to a service that is used by the import/export manager.

    - Move the logic to a service called AccountSwitcher
    - In all relevant places in both the import and the export manager, switch accounts before pre-iniate events.
    - Wrap pre-initiate events in try/catch, switch back accounts, re-throw the error.
    - Switch back accounts if the operation is cancelled.
    - Wrap post-terminate events in try/catch, switch back accounts, re-throw the error.

    Now, here's the other complexity. An operation can have dependent operations i.e. it can call or be called within the exeuction of another operation. That's actually a pretty common use case.

    Imagine the following:

    - Operation A switches from user 0 to user 1.
    - Operation A runs.
    - Before terminating, operation A triggers the execution of operation B.
    - Operation B switches from user 1 to user 12.
    - Operation B runs.
    - Operation B terminates, at which point needs to switch back from user 12 to user 1.
    - Operation A terminates, at which point needs to switch back from user 1 to user 0.

    We therefore need to track in a variable whether the account switched and then use that result to switch back.

Production build 0.71.5 2024