Commit fcddfd7c authored by Larisse Amorim's avatar Larisse Amorim Committed by Phil Norton
Browse files

Issue #3272786 by larisse: 'Delete All Sessions' Option

parent ce37f0e9
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -31,3 +31,16 @@ session_inspector.config:
    _title: 'Session Inspector Configuration'
  requirements:
    _permission: 'administer session inspector configuration'

session_inspector.delete_all:
  path: '/user/{user}/sessions/{sid}/delete-all'
  defaults:
    _form: '\Drupal\session_inspector\Form\DeleteAllSessionsForm'
    _title: 'Delete all active sessions'
  requirements:
    _session_inspector_access_check: 'TRUE'
  options:
    parameters:
      user:
        type: entity:user
    _admin_route: TRUE
+5 −1
Original line number Diff line number Diff line
services:
  session_inspector:
    class: Drupal\session_inspector\SessionInspector
    arguments: ['@database', '@module_handler']
    arguments: ['@database', '@module_handler', '@session_manager']

  session_inspector.access_checker:
    class: Drupal\session_inspector\Access\SessionInspectorAccessCheck
@@ -15,3 +15,7 @@ services:
  plugin.manager.session_inspector.hostname_format:
    class: Drupal\session_inspector\Plugin\HostnameFormatManager
    parent: default_plugin_manager

  session_inspector.delete_all_sessions:
    class: Drupal\session_inspector\SessionInspectorDeleteAllSessions
    arguments: ['@entity_type.manager', '@session_inspector', '@database']
+33 −28
Original line number Diff line number Diff line
@@ -5,13 +5,11 @@ namespace Drupal\session_inspector\Controller;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Link;
use Drupal\Core\Session\SessionManagerInterface;
use Drupal\session_inspector\Plugin\BrowserFormatManager;
use Drupal\session_inspector\Plugin\HostnameFormatManager;
use Drupal\session_inspector\SessionInspectorInterface;
use Drupal\user\UserInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Datetime\DateFormatterInterface;

/**
@@ -35,13 +33,6 @@ class UserSessionInspector extends ControllerBase {
   */
  protected $sessionInspector;

  /**
   * The session manager service.
   *
   * @var \Drupal\Core\Session\SessionManagerInterface
   */
  protected $sessionManager;

  /**
   * The config factory object.
   *
@@ -75,8 +66,6 @@ class UserSessionInspector extends ControllerBase {
   *
   * @param \Drupal\session_inspector\SessionInspectorInterface $session_inspector
   *   The SessionInspector service.
   * @param \Drupal\Core\Session\SessionManagerInterface $session_manager
   *   The session manager service.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The configuration factory.
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
@@ -86,9 +75,8 @@ class UserSessionInspector extends ControllerBase {
   * @param \Drupal\session_inspector\Plugin\HostnameFormatManager $hostname_format_manager
   *   The hostname format manager.
   */
  public function __construct(SessionInspectorInterface $session_inspector, SessionManagerInterface $session_manager, ConfigFactoryInterface $config_factory, DateFormatterInterface $date_formatter, BrowserFormatManager $browser_format_manager, HostnameFormatManager $hostname_format_manager) {
  public function __construct(SessionInspectorInterface $session_inspector, ConfigFactoryInterface $config_factory, DateFormatterInterface $date_formatter, BrowserFormatManager $browser_format_manager, HostnameFormatManager $hostname_format_manager) {
    $this->sessionInspector = $session_inspector;
    $this->sessionManager = $session_manager;
    $this->configFactory = $config_factory;
    $this->dateFormatter = $date_formatter;
    $this->browserFormatManager = $browser_format_manager;
@@ -101,7 +89,6 @@ class UserSessionInspector extends ControllerBase {
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('session_inspector'),
      $container->get('session_manager'),
      $container->get('config.factory'),
      $container->get('date.formatter'),
      $container->get('plugin.manager.session_inspector.browser_format'),
@@ -146,7 +133,7 @@ class UserSessionInspector extends ControllerBase {

      foreach ($sessions as $i => $session) {
        $rows[] = [
          $this->isCurrentSession($session['sid']) ? 'YES' : '',
          $this->sessionInspector->isCurrentSession($session['sid']) ? $this->t('YES') : '',
          $hostnameFormatter->formatHostname($session['hostname']),
          $this->formatTimestamp($session['timestamp'], $dateFromat, $dateIntervalInclude),
          $browserFormatter->formatBrowser($session['browser']),
@@ -156,6 +143,16 @@ class UserSessionInspector extends ControllerBase {
          ],
        ];
      }
      $rows[] = [
        $this->t('Delete all active sessions listed, except the current session'),
        NULL,
        NULL,
        NULL,
        [
          'data' => $this->deleteAllSessionsLink($user, $session['sid']),
          'data-test' => ['session-operation'],
        ],
      ];
    }

    $sessionsTable = [
@@ -182,19 +179,6 @@ class UserSessionInspector extends ControllerBase {
    ];
  }

  /**
   * Is a session ID the currently used session?
   *
   * @param string $sessionId
   *   The session ID to inspect.
   *
   * @return bool
   *   Returns true if the session ID is the currently used one.
   */
  public function isCurrentSession(string $sessionId):bool {
    return Crypt::hashBase64($this->sessionManager->getId()) === $sessionId;
  }

  /**
   * Format a timestamp to a format.
   *
@@ -242,4 +226,25 @@ class UserSessionInspector extends ControllerBase {
    return $linkObject->toRenderable();
  }

  /**
   * Create a delete all sessions link.
   *
   * Given a user object to create a delete all sessions link for the
   * sessions table.
   *
   * @param \Drupal\user\UserInterface $user
   *   The current user.
   * @param string $sessionId
   *   The session ID.
   *
   * @return array
   *   The link as a render array.
   */
  public function deleteAllSessionsLink(UserInterface $user, string $sessionId) {
    $options = ['user' => $user->id(), 'sid' => $sessionId];
    $linkObject = Link::createFromRoute('Delete all sessions', 'session_inspector.delete_all', $options);

    return $linkObject->toRenderable();
  }

}
+103 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\session_inspector\Form;

use Drupal\Core\Form\ConfirmFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\session_inspector\SessionInspectorDeleteAllSessionsInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * The class to delete all active sessions form.
 *
 * @package Drupal\session_inspector\Form
 */
class DeleteAllSessionsForm extends ConfirmFormBase {

  /**
   * The User entity.
   *
   * @var \Drupal\user\Entity\User
   */
  protected $user;

  /**
   * The session ID.
   *
   * @var string
   */
  protected $sessionId;

  /**
   * The session inspector delete all sessions service.
   *
   * @var \Drupal\session_inspector\SessionInspectorDeleteAllSessionsInterface
   */
  protected $deleteAllSessionsService;

  /**
   * Constructs a DeleteAllSessionsForm object.
   *
   * @param \Drupal\session_inspector\SessionInspectorDeleteAllSessionsInterface $deleteAllSessionsService
   *   The session inspector delete all sessions service.
   */
  public function __construct(SessionInspectorDeleteAllSessionsInterface $deleteAllSessionsService) {
    $this->deleteAllSessionsService = $deleteAllSessionsService;
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, $user = NULL, $sid = NULL) {
    $this->user = $user;
    $this->sessionId = $sid;
    return parent::buildForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('session_inspector.delete_all_sessions')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'session_inspector_delete_confirm_form';
  }

  /**
   * {@inheritDoc}
   */
  public function getDescription() {
    return $this->t('This action will delete all active sessions and cannot be undone.');
  }

  /**
   * {@inheritDoc}
   */
  public function getQuestion() {
    return $this->t('Delete all sessions?');
  }

  /**
   * {@inheritDoc}
   */
  public function getCancelUrl() {
    return new Url('session_inspector.manage', ['user' => $this->user->id()]);
  }

  /**
   * {@inheritDoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $this->deleteAllSessionsService->deleteAllSessions($this->user, $this->sessionId);
    $form_state->setRedirectUrl($this->getCancelUrl());
  }

}
+15 −3
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\session_inspector\Event\SessionEvent;
use Drupal\session_inspector\Event\SessionInspectorEvents;
use Drupal\session_inspector\SessionInspectorDeleteAllSessionsInterface;
use Drupal\session_inspector\SessionInspectorInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -46,6 +47,13 @@ class UserSessionDeleteForm extends ConfirmFormBase {
   */
  protected $eventDispatcher;

  /**
   * The session inspector delete all sessions service.
   *
   * @var \Drupal\session_inspector\SessionInspectorDeleteAllSessionsInterface
   */
  protected $deleteAllSessionsService;

  /**
   * Constructs a UserSessionDeleteForm object.
   *
@@ -53,10 +61,13 @@ class UserSessionDeleteForm extends ConfirmFormBase {
   *   The SessionInspector service.
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
   *   The event dispatcher.
   * @param \Drupal\session_inspector\SessionInspectorDeleteAllSessionsInterface $deleteAllSessionsService
   *   The session delete interface.
   */
  public function __construct(SessionInspectorInterface $session_inspector, EventDispatcherInterface $event_dispatcher) {
  public function __construct(SessionInspectorInterface $session_inspector, EventDispatcherInterface $event_dispatcher, SessionInspectorDeleteAllSessionsInterface $deleteAllSessionsService) {
    $this->sessionInspector = $session_inspector;
    $this->eventDispatcher = $event_dispatcher;
    $this->deleteAllSessionsService = $deleteAllSessionsService;
  }

  /**
@@ -74,7 +85,8 @@ class UserSessionDeleteForm extends ConfirmFormBase {
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('session_inspector'),
      $container->get('event_dispatcher')
      $container->get('event_dispatcher'),
      $container->get('session_inspector.delete_all_sessions')
    );
  }

@@ -115,7 +127,7 @@ class UserSessionDeleteForm extends ConfirmFormBase {
    $sessionEvent = new SessionEvent($sessionData['uid'], $sessionData['sid'], $sessionData['hostname'], $sessionData['timestamp']);

    // Destroy the session.
    $this->sessionInspector->destroySession($this->sessionId);
    $this->deleteAllSessionsService->destroySession($this->sessionId);

    // Trigger the session event.
    $this->eventDispatcher->dispatch($sessionEvent, SessionInspectorEvents::SESSION_DESTROYED);
Loading