Score:2

How to remove user role temporarily?

de flag

I need to disable the "administrator" role from user accounts who log into my website from outside my network. For security, I only want users who have this role to be able to use it when they are on my network (determined by some custom PHP code I have).

I know I can remove a role from a user permanently using the appropriate entity methods like this:

<?php
use Drupal\user\Entity\User;

$user = User::load(\Drupal::currentUser()->id());
$user->removeRole('administrator');
$user->save();

But what about to do so temporarily, without updating the user permanently?

Looking at changes made to a user's roles in a custom module using hook_user_login() are permanent. In Drupal 7, I was able to achieve this by modifying the global $user->roles in various hooks.

I am also open to other ways Drupal allows me to meet my needs.

beltouche avatar
cn flag
Possible use case for https://www.drupal.org/project/restrict_by_ip?
Score:3
cn flag

Instead of a Drupal 7 hook you can use the new AccountEvents::SET_USER event:

/src/EventSubscriber/SetAccountSubscriber.php

<?php

namespace Drupal\mymodule\EventSubscriber;

use Drupal\Core\Session\AccountEvents;
use Drupal\Core\Session\AccountSetEvent;
use Drupal\Core\Session\UserSession;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * mymodule event subscriber.
 */
class SetAccountSubscriber implements EventSubscriberInterface {

  /**
   * Account set event handler.
   *
   * @param Drupal\Core\Session\AccountSetEvent $event
   *   Account set event.
   */
  public function onAccountSet(AccountSetEvent $event) {
    $account = $event->getAccount();
    if ($account->isAuthenticated()) {
      $roles = $account->getRoles();
      if (in_array('administrator', $roles)) {
        $roles = array_values(array_diff($roles, ['administrator']));
        $account = new UserSession([
          'uid' => $account->id(),
          'access' => $account->getLastAccessedTime(),
          'roles' => $roles,
          'name' => $account->getAccountName(),
          'preferred_langcode' => $account->getPreferredLangcode(),
          'preferred_admin_langcode' => $account->getPreferredAdminLangcode(),
          'mail' => $account->getEmail(),
          'timezone' => $account->getTimeZone(),
        ]);
        \Drupal::currentUser()->setAccount($account);
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    return [
      AccountEvents::SET_USER => ['onAccountSet'],
    ];
  }

}

mymodule.services.yml

services:
  mymodule.set_account_subscriber:
    class: Drupal\mymodule\EventSubscriber\SetAccountSubscriber
    tags:
      - { name: event_subscriber }  

Be careful to avoid an infinite loop. The last line dispatches the event again and you need a condition preventing the line to be executed a second time, in this case through the removed role.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.