TransWikia.com

How to render a node on behalf of another user (as an admin or without accessCheck)

Drupal Answers Asked on October 26, 2021

Context : I use the following code to replace a token by a rendered node.

The resulted text is sent by email

$renderable = $view_builder->view($node, 'token', $langcode);
$replacements[$original] = Drupal::service('renderer')->renderPlain($renderable);

This is working fine except when I am queuing the mails to be sent

Because, in this case, the upper code runs in a queue and NodeAccessControlHandler::checkAccess and NodeAccessControlHandler::checkFieldAccess are called with an anonymous account (id=0).

This leads to an AccessRessult::forbidden() (because in my setup, anonymous can’t see those fields and/or this node) and the rendered node is empty…

Thus my question is:

How to render a node (in a queue) "in behalf of" an admin user?

or

How to explain to my overrided NodeAccessControlHandler that we are in a queue and that it can safely give access (without security concerns)

One Answer

Thanks to the comment of @No Sssweat I could find a solution:

Summary: the problem appeared when emails were sent via a queue in a cron. The cron is running as an anonymous user, and, in this case, the drupal viewBuilder/Rendering system doesn't have enough permission to display some fields/nodes.

Solution: Adapt the processItem function of the QueueWorker in order to switch the current user into an admin user at the beginning of the process and switch back at the end.

I my use case, I overrode the QueueWorker provided by another module. Here is my code with the injection of the switcher service: (feel free to comment)

/**
 * The account switcher service.
 *
 * @var DrupalCoreSessionAccountSwitcherInterface
 */
protected $accountSwitcher;

public function __construct(array $configuration, $plugin_id, $plugin_definition, SubscribersInterface $subscribers, AccountSwitcherInterface $account_switcher)
{
    parent::__construct($configuration, $plugin_id, $plugin_definition, $subscribers);
    $this->accountSwitcher = $account_switcher;
}

public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition)
{
    return new static($configuration, $plugin_id, $plugin_definition, $container->get('message_subscribe.subscribers'), $container->get('account_switcher'));
}

public function processItem($data)
{
    $this->accountSwitcher->switchTo(new UserSession([
        'uid' => 1,
        'name' => 'cron_admin',
        'roles' => ['administrator'],
    ]));
    parent::processItem($data);
    $this->accountSwitcher->switchBack();
}

Answered by Baud on October 26, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP