diff --git a/masquerade.services.yml b/masquerade.services.yml index 6bfacc5..c6ebb29 100644 --- a/masquerade.services.yml +++ b/masquerade.services.yml @@ -26,4 +26,9 @@ services: parent: user_last_access_subscriber public: false calls: - - [setConfigFactory, ['@config.factory']] + - [setMasquerade, ['@masquerade', '@config.factory']] + masquerade.session_manager.metadata_bag: + class: Drupal\masquerade\Session\MetadataBag + decorates: session_manager.metadata_bag + parent: session_manager.metadata_bag + public: false diff --git a/src/Cache/MasqueradeCacheContext.php b/src/Cache/MasqueradeCacheContext.php index f40322d..808df4a 100644 --- a/src/Cache/MasqueradeCacheContext.php +++ b/src/Cache/MasqueradeCacheContext.php @@ -26,8 +26,9 @@ class MasqueradeCacheContext extends RequestStackCacheContextBase implements Cac */ public function getContext() { if ($request = $this->requestStack->getCurrentRequest()) { - if ($request->hasSession() && ($session = $request->getSession())) { - if ($session->has('masquerading')) { + if ($request->hasSession() && ($bag = $request->getSession()->getMetadataBag())) { + /** @var \Drupal\masquerade\Session\MetadataBag $bag */ + if ($bag->getMasquerade()) { // Previous account supposed to be Authenticated. return '1'; } diff --git a/src/EventSubscriber/MasqueradeUserRequestSubscriber.php b/src/EventSubscriber/MasqueradeUserRequestSubscriber.php index e9038a0..155da96 100644 --- a/src/EventSubscriber/MasqueradeUserRequestSubscriber.php +++ b/src/EventSubscriber/MasqueradeUserRequestSubscriber.php @@ -23,26 +23,35 @@ class MasqueradeUserRequestSubscriber extends UserRequestSubscriber { protected $configFactory; /** - * Sets the config factory. + * The masquerade service. * - * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory - * The config factory. + * @var \Drupal\masquerade\Masquerade */ - public function setConfigFactory(ConfigFactoryInterface $configFactory) { - $this->configFactory = $configFactory; - } + protected $masquerade; /** * {@inheritdoc} */ public function onKernelTerminate(PostResponseEvent $event) { - $session = $event->getRequest()->getSession(); $force = (bool) $this->configFactory ->get('masquerade.settings') ->get('update_user_last_access'); - if (!$session->has('masquerading') || $force) { + if (!$this->masquerade->isMasquerading() || $force) { parent::onKernelTerminate($event); } } + /** + * Initialises masquerade required services. + * + * @param \Drupal\masquerade\Masquerade $masquerade + * The masquerade service. + * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory + * The config factory. + */ + public function setMasquerade(Masquerade $masquerade, ConfigFactoryInterface $configFactory) { + $this->masquerade = $masquerade; + $this->configFactory = $configFactory; + } + } diff --git a/src/Masquerade.php b/src/Masquerade.php index 2b3efc5..8dac8d8 100644 --- a/src/Masquerade.php +++ b/src/Masquerade.php @@ -126,6 +126,19 @@ class Masquerade { return $previous; } + /** + * Returns the masquerading identifier. + * + * @return string|null + * The per-session masquerade identifier or null when no value is set. + * + * @see \Drupal\masquerade\Session\MetadataBag::getMasquerade() + */ + protected function getMasquerade() { + // Accessing metadata does not try to start session. + return $this->session->getMetadataBag()->getMasquerade(); + } + /** * Returns whether the current user is masquerading. * @@ -133,8 +146,7 @@ class Masquerade { * TRUE when already masquerading, FALSE otherwise. */ public function isMasquerading() { - // Do not start new session trying to access its attributes. - return $this->session->isStarted() && $this->session->has('masquerading'); + return (bool) $this->getMasquerade(); } /** @@ -145,13 +157,15 @@ class Masquerade { * * @return bool * TRUE when masqueraded, FALSE otherwise. + * + * @see \Drupal\masquerade\Session\MetadataBag::setMasquerade() */ public function switchTo(UserInterface $target_account) { // Save previous account ID to session storage, set this before // switching so that other modules can react to it, e.g. during // hook_user_logout(). - $this->session->set('masquerading', $this->currentUser->id()); + $this->session->getMetadataBag()->setMasquerade($this->currentUser->id()); $account = $this->switchUser($target_account); @@ -168,13 +182,15 @@ class Masquerade { * * @return bool * TRUE when switched back, FALSE otherwise. + * + * @see \Drupal\masquerade\Session\MetadataBag::clearMasquerade() */ public function switchBack() { - if (!$this->session->isStarted() && !$this->session->has('masquerading')) { + if (!$this->isMasquerading()) { return FALSE; } // Load previous user account. - $user = $this->userStorage->load($this->session->get('masquerading')); + $user = $this->userStorage->load($this->getMasquerade()); if (!$user) { // Ensure the flag is cleared. $this->session->remove('masquerading'); @@ -186,7 +202,7 @@ class Masquerade { // Clear the masquerading flag after switching the user so that hook // implementations can differentiate this from a real logout/login. - $this->session->remove('masquerading'); + $this->session->getMetadataBag()->clearMasquerade(); $this->logger->info('User %username stopped masquerading as %old_username.', [ '%username' => $user->getDisplayName(), diff --git a/src/Session/MetadataBag.php b/src/Session/MetadataBag.php new file mode 100644 index 0000000..f22b0c8 --- /dev/null +++ b/src/Session/MetadataBag.php @@ -0,0 +1,49 @@ +meta[static::MASQUERADE] = $uid; + } + + /** + * Get the masquerading identifier. + * + * @return string|null + * The per-session masquerade identifier or null when no value is set. + */ + public function getMasquerade() { + if (isset($this->meta[static::MASQUERADE])) { + return $this->meta[static::MASQUERADE]; + } + } + + /** + * Clear the masquerade identifier. + */ + public function clearMasquerade() { + unset($this->meta[static::MASQUERADE]); + } + +}