From 1e770ce9f11fe1f54f61b7abd38df5e9fa00296d Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Thu, 28 Jul 2016 18:53:42 +0100 Subject: [PATCH] Revert "Issue #2403307 by dawehner, marthinal, tedbow, clemens.tolboom, Wim Leers, neclimdul, Crell, klausi, andypost, e0ipso: RPC endpoints for user authentication: log in, check login status, log out" This reverts commit 18feefc30246e0e2c94a3fa7cba02d533061bce9. --- core/core.services.yml | 5 +- core/includes/bootstrap.inc | 44 +- .../ExceptionJsonSubscriber.php | 11 - .../MaintenanceModeSubscriber.php | 24 +- .../Installer/InstallerServiceProvider.php | 4 - .../Core/Messenger/MessengerInterface.php | 84 ---- .../Core/Messenger/SessionMessenger.php | 94 ---- .../Drupal/Core/Messenger/StaticMessenger.php | 104 ----- .../serialization/serialization.services.yml | 10 - .../DefaultExceptionSubscriber.php | 10 - .../UserRouteAlterSubscriber.php | 72 --- .../UserAuthenticationController.php | 345 -------------- .../src/Functional/UserLoginHttpTest.php | 421 ------------------ core/modules/user/user.routing.yml | 28 -- .../Core/Messenger/SessionMessengerTest.php | 100 ----- .../Core/Messenger/StaticMessengerTest.php | 80 ---- 16 files changed, 38 insertions(+), 1398 deletions(-) delete mode 100644 core/lib/Drupal/Core/Messenger/MessengerInterface.php delete mode 100644 core/lib/Drupal/Core/Messenger/SessionMessenger.php delete mode 100644 core/lib/Drupal/Core/Messenger/StaticMessenger.php delete mode 100644 core/modules/serialization/src/EventSubscriber/UserRouteAlterSubscriber.php delete mode 100644 core/modules/user/src/Controller/UserAuthenticationController.php delete mode 100644 core/modules/user/tests/src/Functional/UserLoginHttpTest.php delete mode 100644 core/tests/Drupal/Tests/Core/Messenger/SessionMessengerTest.php delete mode 100644 core/tests/Drupal/Tests/Core/Messenger/StaticMessengerTest.php diff --git a/core/core.services.yml b/core/core.services.yml index c63bde7a4136..70c6441f91e0 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1126,7 +1126,7 @@ services: arguments: ['@state', '@current_user'] maintenance_mode_subscriber: class: Drupal\Core\EventSubscriber\MaintenanceModeSubscriber - arguments: ['@maintenance_mode', '@config.factory', '@string_translation', '@url_generator', '@current_user', '@bare_html_page_renderer', '@messenger'] + arguments: ['@maintenance_mode', '@config.factory', '@string_translation', '@url_generator', '@current_user', '@bare_html_page_renderer'] tags: - { name: event_subscriber } path_subscriber: @@ -1631,6 +1631,3 @@ services: arguments: ['@current_user', '@path.current', '@path.matcher', '@language_manager'] tags: - { name: event_subscriber } - messenger: - class: Drupal\Core\Messenger\SessionMessenger - arguments: ['@page_cache_kill_switch'] diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 4599b2b828e3..ec1209740d76 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -9,6 +9,8 @@ use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\Unicode; use Drupal\Core\Logger\RfcLogLevel; +use Drupal\Core\Render\Markup; +use Drupal\Component\Render\MarkupInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Site\Settings; use Drupal\Core\Utility\Error; @@ -435,15 +437,30 @@ function watchdog_exception($type, Exception $exception, $message = NULL, $varia * * @see drupal_get_messages() * @see status-messages.html.twig - * - * @deprecated Deprecated as of Drupal 8.2. - * Use \Drupal::service('messenger')->addMessage() instead. */ function drupal_set_message($message = NULL, $type = 'status', $repeat = FALSE) { - /* @var \Drupal\Core\Messenger\MessengerInterface $messenger */ - $messenger = \Drupal::service('messenger'); - $messenger->addMessage($message, $type, $repeat); - return $messenger->getMessages(); + if (isset($message)) { + if (!isset($_SESSION['messages'][$type])) { + $_SESSION['messages'][$type] = array(); + } + + // Convert strings which are safe to the simplest Markup objects. + if (!($message instanceof Markup) && $message instanceof MarkupInterface) { + $message = Markup::create((string) $message); + } + + // Do not use strict type checking so that equivalent string and + // MarkupInterface objects are detected. + if ($repeat || !in_array($message, $_SESSION['messages'][$type])) { + $_SESSION['messages'][$type][] = $message; + } + + // Mark this page as being uncacheable. + \Drupal::service('page_cache_kill_switch')->trigger(); + } + + // Messages not set when DB connection fails. + return isset($_SESSION['messages']) ? $_SESSION['messages'] : NULL; } /** @@ -470,19 +487,12 @@ function drupal_set_message($message = NULL, $type = 'status', $repeat = FALSE) * * @see drupal_set_message() * @see status-messages.html.twig - * - * @deprecated Deprecated as of Drupal 8.2. - * Use \Drupal::service('messenger')->getMessages() or - * \Drupal::service('messenger')->getMessagesByType() instead. */ function drupal_get_messages($type = NULL, $clear_queue = TRUE) { - /** @var \Drupal\Core\Messenger\MessengerInterface $messenger */ - $messenger = \Drupal::service('messenger'); - - if ($messages = $messenger->getMessages()) { + if ($messages = drupal_set_message()) { if ($type) { if ($clear_queue) { - $messenger->deleteMessagesByType($type); + unset($_SESSION['messages'][$type]); } if (isset($messages[$type])) { return array($type => $messages[$type]); @@ -490,7 +500,7 @@ function drupal_get_messages($type = NULL, $clear_queue = TRUE) { } else { if ($clear_queue) { - $messenger->deleteMessages(); + unset($_SESSION['messages']); } return $messages; } diff --git a/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php index 34eda1f8674f..01f36202de90 100644 --- a/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php @@ -27,17 +27,6 @@ protected static function getPriority() { return -75; } - /** - * Handles a 400 error for JSON. - * - * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event - * The event to process. - */ - public function on400(GetResponseForExceptionEvent $event) { - $response = new JsonResponse(array('message' => $event->getException()->getMessage()), Response::HTTP_BAD_REQUEST); - $event->setResponse($response); - } - /** * Handles a 403 error for JSON. * diff --git a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php index 2e9f6fd5abc2..57d43ec0be11 100644 --- a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php @@ -5,7 +5,6 @@ use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Render\BareHtmlPageRendererInterface; -use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\Routing\RouteMatch; use Drupal\Core\Routing\UrlGeneratorInterface; use Drupal\Core\Session\AccountInterface; @@ -59,13 +58,6 @@ class MaintenanceModeSubscriber implements EventSubscriberInterface { */ protected $bareHtmlPageRenderer; - /** - * The messenger. - * - * @var \Drupal\Core\Messenger\MessengerInterface - */ - protected $messenger; - /** * Constructs a new MaintenanceModeSubscriber. * @@ -81,17 +73,14 @@ class MaintenanceModeSubscriber implements EventSubscriberInterface { * The current user. * @param \Drupal\Core\Render\BareHtmlPageRendererInterface $bare_html_page_renderer * The bare HTML page renderer. - * @param \Drupal\Core\Messenger\MessengerInterface $messenger - * The messenger. */ - public function __construct(MaintenanceModeInterface $maintenance_mode, ConfigFactoryInterface $config_factory, TranslationInterface $translation, UrlGeneratorInterface $url_generator, AccountInterface $account, BareHtmlPageRendererInterface $bare_html_page_renderer, MessengerInterface $messenger) { + public function __construct(MaintenanceModeInterface $maintenance_mode, ConfigFactoryInterface $config_factory, TranslationInterface $translation, UrlGeneratorInterface $url_generator, AccountInterface $account, BareHtmlPageRendererInterface $bare_html_page_renderer) { $this->maintenanceMode = $maintenance_mode; $this->config = $config_factory; $this->stringTranslation = $translation; $this->urlGenerator = $url_generator; $this->account = $account; $this->bareHtmlPageRenderer = $bare_html_page_renderer; - $this->messenger = $messenger; } /** @@ -129,10 +118,10 @@ public function onKernelRequestMaintenance(GetResponseEvent $event) { // settings page. if ($route_match->getRouteName() != 'system.site_maintenance_mode') { if ($this->account->hasPermission('administer site configuration')) { - $this->messenger->addMessage($this->t('Operating in maintenance mode. <a href=":url">Go online.</a>', [':url' => $this->urlGenerator->generate('system.site_maintenance_mode')]), 'status', FALSE); + $this->drupalSetMessage($this->t('Operating in maintenance mode. <a href=":url">Go online.</a>', array(':url' => $this->urlGenerator->generate('system.site_maintenance_mode'))), 'status', FALSE); } else { - $this->messenger->addMessage($this->t('Operating in maintenance mode.'), 'status', FALSE); + $this->drupalSetMessage($this->t('Operating in maintenance mode.'), 'status', FALSE); } } } @@ -151,6 +140,13 @@ protected function getSiteMaintenanceMessage() { )); } + /** + * Wraps the drupal_set_message function. + */ + protected function drupalSetMessage($message = NULL, $type = 'status', $repeat = FALSE) { + return drupal_set_message($message, $type, $repeat); + } + /** * {@inheritdoc} */ diff --git a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php index f5fcf786a5a6..1ace991de83c 100644 --- a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php +++ b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php @@ -5,7 +5,6 @@ use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\DependencyInjection\ServiceProviderInterface; use Drupal\Core\DependencyInjection\ServiceModifierInterface; -use Drupal\Core\Messenger\StaticMessenger; use Symfony\Component\DependencyInjection\Reference; /** @@ -35,9 +34,6 @@ public function register(ContainerBuilder $container) { ->register('keyvalue', 'Drupal\Core\KeyValueStore\KeyValueMemoryFactory'); $container ->register('keyvalue.expirable', 'Drupal\Core\KeyValueStore\KeyValueNullExpirableFactory'); - $definition = $container->getDefinition('messenger'); - $definition->setClass(StaticMessenger::class); - $definition->setArguments([new Reference('page_cache_kill_switch')]); // Replace services with no-op implementations. $container diff --git a/core/lib/Drupal/Core/Messenger/MessengerInterface.php b/core/lib/Drupal/Core/Messenger/MessengerInterface.php deleted file mode 100644 index da36f04216cd..000000000000 --- a/core/lib/Drupal/Core/Messenger/MessengerInterface.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -namespace Drupal\Core\Messenger; - -/** - * Stores runtime messages sent out to individual users on the page. - * - * An example for these messages is for example: "Content X got saved". - */ -interface MessengerInterface { - - /** - * A status message. - */ - const TYPE_STATUS = 'status'; - - /** - * A warning. - */ - const TYPE_WARNING = 'warning'; - - /** - * An error. - */ - const TYPE_ERROR = 'error'; - - /** - * Adds a new message to the queue. - * - * @param string|\Drupal\Component\Render\MarkupInterface $message - * (optional) The translated message to be displayed to the user. For - * consistency with other messages, it should begin with a capital letter - * and end with a period. - * @param string $type - * (optional) The message's type. Either self::TYPE_STATUS, - * self::TYPE_WARNING, or self::TYPE_ERROR. - * @param bool $repeat - * (optional) If this is FALSE and the message is already set, then the - * message won't be repeated. Defaults to FALSE. - * - * @return $this - */ - public function addMessage($message, $type = self::TYPE_STATUS, $repeat = FALSE); - - /** - * Gets all messages. - * - * @return string[][]|\Drupal\Component\Render\MarkupInterface[][] - * Keys are message types and values are indexed arrays of messages. Message - * types are either self::TYPE_STATUS, self::TYPE_WARNING, or - * self::TYPE_ERROR. - */ - public function getMessages(); - - /** - * Gets all messages of a certain type. - * - * @param string $type - * The messages' type. Either self::TYPE_STATUS, self::TYPE_WARNING, - * or self::TYPE_ERROR. - * - * @return string[]|\Drupal\Component\Render\MarkupInterface[] - */ - public function getMessagesByType($type); - - /** - * Deletes all messages. - * - * @return $this - */ - public function deleteMessages(); - - /** - * Deletes all messages of a certain type. - * - * @param string $type - * The messages' type. Either self::TYPE_STATUS, self::TYPE_WARNING, or - * self::TYPE_ERROR. - * - * @return $this - */ - public function deleteMessagesByType($type); - -} diff --git a/core/lib/Drupal/Core/Messenger/SessionMessenger.php b/core/lib/Drupal/Core/Messenger/SessionMessenger.php deleted file mode 100644 index fc858fda513f..000000000000 --- a/core/lib/Drupal/Core/Messenger/SessionMessenger.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php - -namespace Drupal\Core\Messenger; - -use Drupal\Component\Render\MarkupInterface; -use Drupal\Core\PageCache\ResponsePolicy\KillSwitch; -use Drupal\Core\Render\Markup; - -/** - * Provides a session-based messenger. - */ -class SessionMessenger implements MessengerInterface { - - /** - * The page caching kill switch. - * - * @var \Drupal\Core\PageCache\ResponsePolicy\KillSwitch - */ - protected $pageCacheKillSwitch; - - /** - * Constructs a new instance. - * - * @param \Drupal\Core\Session\SessionManagerInterface - * @param \Drupal\Core\PageCache\ResponsePolicy\KillSwitch $page_cache_kill_switch - * The page caching kill switch. - */ - public function __construct(KillSwitch $page_cache_kill_switch) { - $this->pageCacheKillSwitch = $page_cache_kill_switch; - } - - /** - * {@inheritdoc} - */ - public function addMessage($message, $type = self::TYPE_STATUS, $repeat = FALSE) { - if (!isset($_SESSION['messages'][$type])) { - $_SESSION['messages'][$type] = []; - } - - // Convert strings which are safe to the simplest Markup objects. - if (!($message instanceof Markup) && $message instanceof MarkupInterface) { - $message = Markup::create((string) $message); - } - - // Do not use strict type checking so that equivalent string and - // \Drupal\Core\Render\Markup objects are detected. - if ($repeat || !in_array($message, $_SESSION['messages'][$type])) { - $_SESSION['messages'][$type][] = $message; - $this->pageCacheKillSwitch->trigger(); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getMessages() { - $messages = isset($_SESSION['messages']) ? $_SESSION['messages'] : []; - foreach ($messages as $type => $messages_by_type) { - $messages[$type] = $messages_by_type; - } - - return $messages; - } - - /** - * {@inheritdoc} - */ - public function getMessagesByType($type) { - $messages = isset($_SESSION['messages']) && isset($_SESSION['messages'][$type]) ? $_SESSION['messages'][$type] : []; - - return $messages; - } - - /** - * {@inheritdoc} - */ - public function deleteMessages() { - unset($_SESSION['messages']); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function deleteMessagesByType($type) { - unset($_SESSION['messages'][$type]); - - return $this; - } - -} diff --git a/core/lib/Drupal/Core/Messenger/StaticMessenger.php b/core/lib/Drupal/Core/Messenger/StaticMessenger.php deleted file mode 100644 index f2e0f51101aa..000000000000 --- a/core/lib/Drupal/Core/Messenger/StaticMessenger.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php - -namespace Drupal\Core\Messenger; - -use Drupal\Component\Render\MarkupInterface; -use Drupal\Core\PageCache\ResponsePolicy\KillSwitch; -use Drupal\Core\Render\Markup; - -/** - * Provides a messenger that stores messages for this request only. - */ -class StaticMessenger implements MessengerInterface { - - /** - * The messages that have been set. - * - * @var array[] - * Keys are either self::TYPE_STATUS, self::TYPE_WARNING, or - * self::TYPE_ERROR. Values are arrays of arrays with the following keys: - * - message (string): the message. - * - safe (bool): whether the message is marked as safe markup. - */ - protected $messages = []; - - /** - * The page caching kill switch. - * - * @var \Drupal\Core\PageCache\ResponsePolicy\KillSwitch - */ - protected $pageCacheKillSwitch; - - /** - * Constructs a new instance. - * - * @param \Drupal\Core\PageCache\ResponsePolicy\KillSwitch $page_cache_kill_switch - * The page caching kill switch. - */ - public function __construct(KillSwitch $page_cache_kill_switch) { - $this->pageCacheKillSwitch = $page_cache_kill_switch; - } - - /** - * {@inheritdoc} - */ - public function addMessage($message, $type = self::TYPE_STATUS, $repeat = FALSE) { - if (!isset($this->messages[$type])) { - $this->messages[$type] = []; - } - - // Convert strings which are safe to the simplest Markup objects. - if (!($message instanceof Markup) && $message instanceof MarkupInterface) { - $message = Markup::create((string) $message); - } - - // Do not use strict type checking so that equivalent string and - // MarkupInterface objects are detected. - if ($repeat || !in_array($message, $this->messages[$type])) { - $this->messages[$type][] = $message; - $this->pageCacheKillSwitch->trigger(); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getMessages() { - $messages = isset($this->messages) ? $this->messages : []; - foreach ($messages as $type => $messages_by_type) { - $messages[$type] = $messages_by_type; - } - - return $messages; - } - - /** - * {@inheritdoc} - */ - public function getMessagesByType($type) { - $messages = isset($this->messages) && isset($this->messages[$type]) ? $this->messages[$type] : []; - - return $messages; - } - - /** - * {@inheritdoc} - */ - public function deleteMessages() { - unset($this->messages); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function deleteMessagesByType($type) { - unset($this->messages[$type]); - - return $this; - } - -} diff --git a/core/modules/serialization/serialization.services.yml b/core/modules/serialization/serialization.services.yml index 8b570c076308..c510ab161906 100644 --- a/core/modules/serialization/serialization.services.yml +++ b/core/modules/serialization/serialization.services.yml @@ -64,13 +64,3 @@ services: class: Drupal\serialization\EntityResolver\TargetIdResolver tags: - { name: entity_resolver} - serialization.exception.default: - class: Drupal\serialization\EventSubscriber\DefaultExceptionSubscriber - tags: - - { name: event_subscriber } - arguments: ['@serializer', '%serializer.formats%'] - serialization.user_route_alter_subscriber: - class: Drupal\serialization\EventSubscriber\UserRouteAlterSubscriber - tags: - - { name: event_subscriber } - arguments: ['@serializer', '%serializer.formats%'] diff --git a/core/modules/serialization/src/EventSubscriber/DefaultExceptionSubscriber.php b/core/modules/serialization/src/EventSubscriber/DefaultExceptionSubscriber.php index ba91836377ec..753d3c10b8bc 100644 --- a/core/modules/serialization/src/EventSubscriber/DefaultExceptionSubscriber.php +++ b/core/modules/serialization/src/EventSubscriber/DefaultExceptionSubscriber.php @@ -115,16 +115,6 @@ public function on422(GetResponseForExceptionEvent $event) { $this->setEventResponse($event, Response::HTTP_UNPROCESSABLE_ENTITY); } - /** - * Handles a 429 error for HTTP. - * - * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event - * The event to process. - */ - public function on429(GetResponseForExceptionEvent $event) { - $this->setEventResponse($event, Response::HTTP_TOO_MANY_REQUESTS); - } - /** * Sets the Response for the exception event. * diff --git a/core/modules/serialization/src/EventSubscriber/UserRouteAlterSubscriber.php b/core/modules/serialization/src/EventSubscriber/UserRouteAlterSubscriber.php deleted file mode 100644 index a8b71c7bbb69..000000000000 --- a/core/modules/serialization/src/EventSubscriber/UserRouteAlterSubscriber.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -namespace Drupal\serialization\EventSubscriber; - -use Drupal\Core\Routing\RouteBuildEvent; -use Drupal\Core\Routing\RoutingEvents; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Serializer\SerializerInterface; - -/** - * Alters user authentication routes to support additional serialization formats. - */ -class UserRouteAlterSubscriber implements EventSubscriberInterface { - - /** - * The serializer. - * - * @var \Symfony\Component\Serializer\Serializer - */ - protected $serializer; - - /** - * The available serialization formats. - * - * @var array - */ - protected $serializerFormats = []; - - /** - * UserRouteAlterSubscriber constructor. - * - * @param \Symfony\Component\Serializer\SerializerInterface $serializer - * The serializer service. - * @param array $serializer_formats - * The available serializer formats. - */ - public function __construct(SerializerInterface $serializer, array $serializer_formats) { - $this->serializer = $serializer; - $this->serializerFormats = $serializer_formats; - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents() { - $events[RoutingEvents::ALTER][] = 'onRoutingAlterAddFormats'; - return $events; - } - - /** - * Adds supported formats to the user authentication HTTP routes. - * - * @param \Drupal\Core\Routing\RouteBuildEvent $event - * The event to process. - */ - public function onRoutingAlterAddFormats(RouteBuildEvent $event) { - $route_names = [ - 'user.login_status.http', - 'user.login.http', - 'user.logout.http', - ]; - $routes = $event->getRouteCollection(); - foreach ($route_names as $route_name) { - if ($route = $routes->get($route_name)) { - $formats = explode('|', $route->getRequirement('_format')); - $formats = array_unique($formats + $this->serializerFormats); - $route->setRequirement('_format', implode('|', $formats)); - } - } - } - -} diff --git a/core/modules/user/src/Controller/UserAuthenticationController.php b/core/modules/user/src/Controller/UserAuthenticationController.php deleted file mode 100644 index 569a1211ac07..000000000000 --- a/core/modules/user/src/Controller/UserAuthenticationController.php +++ /dev/null @@ -1,345 +0,0 @@ -<?php - -namespace Drupal\user\Controller; - -use Drupal\Core\Access\CsrfTokenGenerator; -use Drupal\Core\Controller\ControllerBase; -use Drupal\Core\DependencyInjection\ContainerInjectionInterface; -use Drupal\Core\Flood\FloodInterface; -use Drupal\Core\Routing\RouteProviderInterface; -use Drupal\user\UserAuthInterface; -use Drupal\user\UserInterface; -use Drupal\user\UserStorageInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; -use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; -use Symfony\Component\Serializer\Encoder\JsonEncoder; -use Symfony\Component\Serializer\Serializer; - -/** - * Provides controllers for login, login status and logout via HTTP requests. - */ -class UserAuthenticationController extends ControllerBase implements ContainerInjectionInterface { - - /** - * String sent in responses, to describe the user as being logged in. - * - * @var string - */ - const LOGGED_IN = 1; - - /** - * String sent in responses, to describe the user as being logged out. - * - * @var string - */ - const LOGGED_OUT = 0; - - /** - * The flood controller. - * - * @var \Drupal\Core\Flood\FloodInterface - */ - protected $flood; - - /** - * The user storage. - * - * @var \Drupal\user\UserStorageInterface - */ - protected $userStorage; - - /** - * The CSRF token generator. - * - * @var \Drupal\Core\Access\CsrfTokenGenerator - */ - protected $csrfToken; - - /** - * The user authentication. - * - * @var \Drupal\user\UserAuthInterface - */ - protected $userAuth; - - /** - * The route provider. - * - * @var \Drupal\Core\Routing\RouteProviderInterface - */ - protected $routeProvider; - - /** - * The serializer. - * - * @var \Symfony\Component\Serializer\Serializer - */ - protected $serializer; - - /** - * The available serialization formats. - * - * @var array - */ - protected $serializerFormats = []; - - /** - * Constructs a new UserAuthenticationController object. - * - * @param \Drupal\Core\Flood\FloodInterface $flood - * The flood controller. - * @param \Drupal\user\UserStorageInterface $user_storage - * The user storage. - * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token - * The CSRF token generator. - * @param \Drupal\user\UserAuthInterface $user_auth - * The user authentication. - * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider - * The route provider. - * @param \Symfony\Component\Serializer\Serializer $serializer - * The serializer. - * @param array $serializer_formats - * The available serialization formats. - */ - public function __construct(FloodInterface $flood, UserStorageInterface $user_storage, CsrfTokenGenerator $csrf_token, UserAuthInterface $user_auth, RouteProviderInterface $route_provider, Serializer $serializer, array $serializer_formats) { - $this->flood = $flood; - $this->userStorage = $user_storage; - $this->csrfToken = $csrf_token; - $this->userAuth = $user_auth; - $this->serializer = $serializer; - $this->serializerFormats = $serializer_formats; - $this->routeProvider = $route_provider; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - if ($container->hasParameter('serializer.formats') && $container->has('serializer')) { - $serializer = $container->get('serializer'); - $formats = $container->getParameter('serializer.formats'); - } - else { - $formats = ['json']; - $encoders = [new JsonEncoder()]; - $serializer = new Serializer([], $encoders); - } - - return new static( - $container->get('flood'), - $container->get('entity_type.manager')->getStorage('user'), - $container->get('csrf_token'), - $container->get('user.auth'), - $container->get('router.route_provider'), - $serializer, - $formats - ); - } - - /** - * Logs in a user. - * - * @param \Symfony\Component\HttpFoundation\Request $request - * The request. - * - * @return \Symfony\Component\HttpFoundation\Response - * A response which contains the ID and CSRF token. - */ - public function login(Request $request) { - $format = $this->getRequestFormat($request); - - $content = $request->getContent(); - $credentials = $this->serializer->decode($content, $format); - if (!isset($credentials['name']) && !isset($credentials['pass'])) { - throw new BadRequestHttpException('Missing credentials.'); - } - - if (!isset($credentials['name'])) { - throw new BadRequestHttpException('Missing credentials.name.'); - } - if (!isset($credentials['pass'])) { - throw new BadRequestHttpException('Missing credentials.pass.'); - } - - $this->floodControl($request, $credentials['name']); - - if ($this->userIsBlocked($credentials['name'])) { - throw new BadRequestHttpException('The user has not been activated or is blocked.'); - } - - if ($uid = $this->userAuth->authenticate($credentials['name'], $credentials['pass'])) { - $this->flood->clear('user.http_login', $this->getLoginFloodIdentifier($request, $credentials['name'])); - /** @var \Drupal\user\UserInterface $user */ - $user = $this->userStorage->load($uid); - $this->userLoginFinalize($user); - - // Send basic metadata about the logged in user. - $response_data = []; - if ($user->get('uid')->access('view', $user)) { - $response_data['current_user']['uid'] = $user->id(); - } - if ($user->get('roles')->access('view', $user)) { - $response_data['current_user']['roles'] = $user->getRoles(); - } - if ($user->get('name')->access('view', $user)) { - $response_data['current_user']['name'] = $user->getAccountName(); - } - $response_data['csrf_token'] = $this->csrfToken->get('rest'); - - $logout_route = $this->routeProvider->getRouteByName('user.logout.http'); - // Trim '/' off path to match \Drupal\Core\Access\CsrfAccessCheck. - $logout_path = ltrim($logout_route->getPath(), '/'); - $response_data['logout_token'] = $this->csrfToken->get($logout_path); - - $encoded_response_data = $this->serializer->encode($response_data, $format); - return new Response($encoded_response_data); - } - - $flood_config = $this->config('user.flood'); - if ($identifier = $this->getLoginFloodIdentifier($request, $credentials['name'])) { - $this->flood->register('user.http_login', $flood_config->get('user_window'), $identifier); - } - // Always register an IP-based failed login event. - $this->flood->register('user.failed_login_ip', $flood_config->get('ip_window')); - throw new BadRequestHttpException('Sorry, unrecognized username or password.'); - } - - /** - * Verifies if the user is blocked. - * - * @param string $name - * The username. - * - * @return bool - * TRUE if the user is blocked, otherwise FALSE. - */ - protected function userIsBlocked($name) { - return user_is_blocked($name); - } - - /** - * Finalizes the user login. - * - * @param \Drupal\user\UserInterface $user - * The user. - */ - protected function userLoginFinalize(UserInterface $user) { - user_login_finalize($user); - } - - /** - * Logs out a user. - * - * @return \Drupal\rest\ResourceResponse - * The response object. - */ - public function logout() { - $this->userLogout(); - return new Response(NULL, 204); - } - - /** - * Logs the user out. - */ - protected function userLogout() { - user_logout(); - } - - /** - * Checks whether a user is logged in or not. - * - * @return \Symfony\Component\HttpFoundation\Response - * The response. - */ - public function loginStatus() { - if ($this->currentUser()->isAuthenticated()) { - $response = new Response(self::LOGGED_IN); - } - else { - $response = new Response(self::LOGGED_OUT); - } - $response->headers->set('Content-Type', 'text/plain'); - return $response; - } - - /** - * Gets the format of the current request. - * - * @param \Symfony\Component\HttpFoundation\Request $request - * The current request. - * - * @return string - * The format of the request. - */ - protected function getRequestFormat(Request $request) { - $format = $request->getRequestFormat(); - if (!in_array($format, $this->serializerFormats)) { - throw new BadRequestHttpException("Unrecognized format: $format."); - } - return $format; - } - - /** - * Enforces flood control for the current login request. - * - * @param \Symfony\Component\HttpFoundation\Request $request - * The current request. - * @param string $username - * The user name sent for login credentials. - */ - protected function floodControl(Request $request, $username) { - $flood_config = $this->config('user.flood'); - if (!$this->flood->isAllowed('user.failed_login_ip', $flood_config->get('ip_limit'), $flood_config->get('ip_window'))) { - throw new AccessDeniedHttpException('Access is blocked because of IP based flood prevention.', NULL, Response::HTTP_TOO_MANY_REQUESTS); - } - - if ($identifier = $this->getLoginFloodIdentifier($request, $username)) { - // Don't allow login if the limit for this user has been reached. - // Default is to allow 5 failed attempts every 6 hours. - if (!$this->flood->isAllowed('user.http_login', $flood_config->get('user_limit'), $flood_config->get('user_window'), $identifier)) { - if ($flood_config->get('uid_only')) { - $error_message = sprintf('There have been more than %s failed login attempts for this account. It is temporarily blocked. Try again later or request a new password.', $flood_config->get('user_limit')); - } - else { - $error_message = 'Too many failed login attempts from your IP address. This IP address is temporarily blocked.'; - } - throw new AccessDeniedHttpException($error_message, NULL, Response::HTTP_TOO_MANY_REQUESTS); - } - } - } - - /** - * Gets the login identifier for user login flood control. - * - * @param \Symfony\Component\HttpFoundation\Request $request - * The current request. - * @param string $username - * The username supplied in login credentials. - * - * @return string - * The login identifier or if the user does not exist an empty string. - */ - protected function getLoginFloodIdentifier(Request $request, $username) { - $flood_config = $this->config('user.flood'); - $accounts = $this->userStorage->loadByProperties(['name' => $username, 'status' => 1]); - if ($account = reset($accounts)) { - if ($flood_config->get('uid_only')) { - // Register flood events based on the uid only, so they apply for any - // IP address. This is the most secure option. - $identifier = $account->id(); - } - else { - // The default identifier is a combination of uid and IP address. This - // is less secure but more resistant to denial-of-service attacks that - // could lock out all users with public user names. - $identifier = $account->id() . '-' . $request->getClientIp(); - } - return $identifier; - } - return ''; - } - -} diff --git a/core/modules/user/tests/src/Functional/UserLoginHttpTest.php b/core/modules/user/tests/src/Functional/UserLoginHttpTest.php deleted file mode 100644 index 356544119b66..000000000000 --- a/core/modules/user/tests/src/Functional/UserLoginHttpTest.php +++ /dev/null @@ -1,421 +0,0 @@ -<?php - -namespace Drupal\Tests\user\Functional; - -use Drupal\Core\Flood\DatabaseBackend; -use Drupal\Core\Url; -use Drupal\Tests\BrowserTestBase; -use Drupal\user\Controller\UserAuthenticationController; -use GuzzleHttp\Cookie\CookieJar; -use Psr\Http\Message\ResponseInterface; -use Symfony\Component\Serializer\Encoder\JsonEncoder; -use Symfony\Component\Serializer\Encoder\XmlEncoder; -use Symfony\Component\Serializer\Serializer; - -/** - * Tests login via direct HTTP. - * - * @group user - */ -class UserLoginHttpTest extends BrowserTestBase { - - /** - * The cookie jar. - * - * @var \GuzzleHttp\Cookie\CookieJar - */ - protected $cookies; - - /** - * The serializer. - * - * @var \Symfony\Component\Serializer\Serializer - */ - protected $serializer; - - /** - * {@inheritdoc} - */ - protected function setUp() { - parent::setUp(); - $this->cookies = new CookieJar(); - $encoders = [new JsonEncoder(), new XmlEncoder()]; - $this->serializer = new Serializer([], $encoders); - } - - /** - * Executes a login HTTP request. - * - * @param string $name - * The username. - * @param string $pass - * The user password. - * @param string $format - * The format to use to make the request. - * - * @return \Psr\Http\Message\ResponseInterface The HTTP response. - * The HTTP response. - */ - protected function loginRequest($name, $pass, $format = 'json') { - $user_login_url = Url::fromRoute('user.login.http') - ->setRouteParameter('_format', $format) - ->setAbsolute(); - - $request_body = []; - if (isset($name)) { - $request_body['name'] = $name; - } - if (isset($pass)) { - $request_body['pass'] = $pass; - } - - $result = \Drupal::httpClient()->post($user_login_url->toString(), [ - 'body' => $this->serializer->encode($request_body, $format), - 'headers' => [ - 'Accept' => "application/$format", - ], - 'http_errors' => FALSE, - 'cookies' => $this->cookies, - ]); - return $result; - } - - /** - * Tests user session life cycle. - */ - public function testLogin() { - $client = \Drupal::httpClient(); - foreach ([FALSE, TRUE] as $serialization_enabled_option) { - if ($serialization_enabled_option) { - /** @var \Drupal\Core\Extension\ModuleInstaller $module_installer */ - $module_installer = $this->container->get('module_installer'); - $module_installer->install(['serialization']); - $formats = ['json', 'xml']; - } - else { - // Without the serialization module only JSON is supported. - $formats = ['json']; - } - foreach ($formats as $format) { - // Create new user for each iteration to reset flood. - // Grant the user administer users permissions to they can see the - // 'roles' field. - $account = $this->drupalCreateUser(['administer users']); - $name = $account->getUsername(); - $pass = $account->passRaw; - - $login_status_url = $this->getLoginStatusUrlString($format); - $response = $client->get($login_status_url); - $this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_OUT); - - // Flooded. - $this->config('user.flood') - ->set('user_limit', 3) - ->save(); - - $response = $this->loginRequest($name, 'wrong-pass', $format); - $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format); - - $response = $this->loginRequest($name, 'wrong-pass', $format); - $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format); - - $response = $this->loginRequest($name, 'wrong-pass', $format); - $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format); - - $response = $this->loginRequest($name, 'wrong-pass', $format); - $this->assertHttpResponseWithMessage($response, 403, 'Too many failed login attempts from your IP address. This IP address is temporarily blocked.', $format); - - // After testing the flood control we can increase the limit. - $this->config('user.flood') - ->set('user_limit', 100) - ->save(); - - $response = $this->loginRequest(NULL, NULL, $format); - $this->assertHttpResponseWithMessage($response, 400, 'Missing credentials.', $format); - - $response = $this->loginRequest(NULL, $pass, $format); - $this->assertHttpResponseWithMessage($response, 400, 'Missing credentials.name.', $format); - - $response = $this->loginRequest($name, NULL, $format); - $this->assertHttpResponseWithMessage($response, 400, 'Missing credentials.pass.', $format); - - // Blocked. - $account - ->block() - ->save(); - - $response = $this->loginRequest($name, $pass, $format); - $this->assertHttpResponseWithMessage($response, 400, 'The user has not been activated or is blocked.', $format); - - $account - ->activate() - ->save(); - - $response = $this->loginRequest($name, 'garbage', $format); - $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format); - - $response = $this->loginRequest('garbage', $pass, $format); - $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format); - - $response = $this->loginRequest($name, $pass, $format); - $this->assertEquals(200, $response->getStatusCode()); - $result_data = $this->serializer->decode($response->getBody(), $format); - $this->assertEquals($name, $result_data['current_user']['name']); - $this->assertEquals($account->id(), $result_data['current_user']['uid']); - $this->assertEquals($account->getRoles(), $result_data['current_user']['roles']); - $logout_token = $result_data['logout_token']; - - $response = $client->get($login_status_url, ['cookies' => $this->cookies]); - $this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_IN); - - $response = $this->logoutRequest($format, $logout_token); - $this->assertEquals(204, $response->getStatusCode()); - - $response = $client->get($login_status_url, ['cookies' => $this->cookies]); - $this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_OUT); - - $this->resetFlood(); - } - } - } - - /** - * Gets a value for a given key from the response. - * - * @param \Psr\Http\Message\ResponseInterface $response - * The response object. - * @param string $key - * The key for the value. - * @param string $format - * The encoded format. - * - * @return mixed - * The value for the key. - */ - protected function getResultValue(ResponseInterface $response, $key, $format) { - $decoded = $this->serializer->decode((string) $response->getBody(), $format); - if (is_array($decoded)) { - return $decoded[$key]; - } - else { - return $decoded->{$key}; - } - } - - /** - * Resets all flood entries. - */ - protected function resetFlood() { - $this->container->get('database')->delete(DatabaseBackend::TABLE_NAME)->execute(); - } - - /** - * Tests the global login flood control. - * - * @see \Drupal\basic_auth\Tests\Authentication\BasicAuthTest::testGlobalLoginFloodControl - * @see \Drupal\user\Tests\UserLoginTest::testGlobalLoginFloodControl - */ - public function testGlobalLoginFloodControl() { - $this->config('user.flood') - ->set('ip_limit', 2) - // Set a high per-user limit out so that it is not relevant in the test. - ->set('user_limit', 4000) - ->save(); - - $user = $this->drupalCreateUser([]); - $incorrect_user = clone $user; - $incorrect_user->passRaw .= 'incorrect'; - - // Try 2 failed logins. - for ($i = 0; $i < 2; $i++) { - $response = $this->loginRequest($incorrect_user->getUsername(), $incorrect_user->passRaw); - $this->assertEquals('400', $response->getStatusCode()); - } - - // IP limit has reached to its limit. Even valid user credentials will fail. - $response = $this->loginRequest($user->getUsername(), $user->passRaw); - $this->assertHttpResponseWithMessage($response, '403', 'Access is blocked because of IP based flood prevention.'); - } - - /** - * Checks a response for status code and body. - * - * @param \Psr\Http\Message\ResponseInterface $response - * The response object. - * @param int $expected_code - * The expected status code. - * @param mixed $expected_body - * The expected response body. - */ - protected function assertHttpResponse(ResponseInterface $response, $expected_code, $expected_body) { - $this->assertEquals($expected_code, $response->getStatusCode()); - $this->assertEquals($expected_body, (string) $response->getBody()); - } - - /** - * Checks a response for status code and message. - * - * @param \Psr\Http\Message\ResponseInterface $response - * The response object. - * @param int $expected_code - * The expected status code. - * @param string $expected_message - * The expected message encoded in response. - * @param string $format - * The format that the response is encoded in. - */ - protected function assertHttpResponseWithMessage(ResponseInterface $response, $expected_code, $expected_message, $format = 'json') { - $this->assertEquals($expected_code, $response->getStatusCode()); - $this->assertEquals($expected_message, $this->getResultValue($response, 'message', $format)); - } - - /** - * Test the per-user login flood control. - * - * @see \Drupal\user\Tests\UserLoginTest::testPerUserLoginFloodControl - * @see \Drupal\basic_auth\Tests\Authentication\BasicAuthTest::testPerUserLoginFloodControl - */ - public function testPerUserLoginFloodControl() { - foreach ([TRUE, FALSE] as $uid_only_setting) { - $this->config('user.flood') - // Set a high global limit out so that it is not relevant in the test. - ->set('ip_limit', 4000) - ->set('user_limit', 3) - ->set('uid_only', $uid_only_setting) - ->save(); - - $user1 = $this->drupalCreateUser([]); - $incorrect_user1 = clone $user1; - $incorrect_user1->passRaw .= 'incorrect'; - - $user2 = $this->drupalCreateUser([]); - - // Try 2 failed logins. - for ($i = 0; $i < 2; $i++) { - $response = $this->loginRequest($incorrect_user1->getUsername(), $incorrect_user1->passRaw); - $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.'); - } - - // A successful login will reset the per-user flood control count. - $response = $this->loginRequest($user1->getUsername(), $user1->passRaw); - $result_data = $this->serializer->decode($response->getBody(), 'json'); - $this->logoutRequest('json', $result_data['logout_token']); - - // Try 3 failed logins for user 1, they will not trigger flood control. - for ($i = 0; $i < 3; $i++) { - $response = $this->loginRequest($incorrect_user1->getUsername(), $incorrect_user1->passRaw); - $this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.'); - } - - // Try one successful attempt for user 2, it should not trigger any - // flood control. - $this->drupalLogin($user2); - $this->drupalLogout(); - - // Try one more attempt for user 1, it should be rejected, even if the - // correct password has been used. - $response = $this->loginRequest($user1->getUsername(), $user1->passRaw); - // Depending on the uid_only setting the error message will be different. - if ($uid_only_setting) { - $excepted_message = 'There have been more than 3 failed login attempts for this account. It is temporarily blocked. Try again later or request a new password.'; - } - else { - $excepted_message = 'Too many failed login attempts from your IP address. This IP address is temporarily blocked.'; - } - $this->assertHttpResponseWithMessage($response, 403, $excepted_message); - } - - } - - /** - * Executes a logout HTTP request. - * - * @param string $format - * The format to use to make the request. - * @param string $logout_token - * The csrf token for user logout. - * - * @return \Psr\Http\Message\ResponseInterface The HTTP response. - * The HTTP response. - */ - protected function logoutRequest($format = 'json', $logout_token = '') { - /** @var \GuzzleHttp\Client $client */ - $client = $this->container->get('http_client'); - $user_logout_url = Url::fromRoute('user.logout.http') - ->setRouteParameter('_format', $format) - ->setAbsolute(); - if ($logout_token) { - $user_logout_url->setOption('query', ['token' => $logout_token]); - } - $post_options = [ - 'headers' => [ - 'Accept' => "application/$format", - ], - 'http_errors' => FALSE, - 'cookies' => $this->cookies, - ]; - - $response = $client->post($user_logout_url->toString(), $post_options); - return $response; - } - - /** - * Test csrf protection of User Logout route. - */ - public function testLogoutCsrfProtection() { - $client = \Drupal::httpClient(); - $login_status_url = $this->getLoginStatusUrlString(); - $account = $this->drupalCreateUser(); - $name = $account->getUsername(); - $pass = $account->passRaw; - - $response = $this->loginRequest($name, $pass); - $this->assertEquals(200, $response->getStatusCode()); - $result_data = $this->serializer->decode($response->getBody(), 'json'); - - $logout_token = $result_data['logout_token']; - - // Test third party site posting to current site with logout request. - // This should not logout the current user because it lacks the CSRF - // token. - $response = $this->logoutRequest('json'); - $this->assertEquals(403, $response->getStatusCode()); - - // Ensure still logged in. - $response = $client->get($login_status_url, ['cookies' => $this->cookies]); - $this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_IN); - - // Try with an incorrect token. - $response = $this->logoutRequest('json', 'not-the-correct-token'); - $this->assertEquals(403, $response->getStatusCode()); - - // Ensure still logged in. - $response = $client->get($login_status_url, ['cookies' => $this->cookies]); - $this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_IN); - - // Try a logout request with correct token. - $response = $this->logoutRequest('json', $logout_token); - $this->assertEquals(204, $response->getStatusCode()); - - // Ensure actually logged out. - $response = $client->get($login_status_url, ['cookies' => $this->cookies]); - $this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_OUT); - } - - /** - * Gets the URL string for checking login. - * - * @param string $format - * The format to use to make the request. - * - * @return string - * The URL string. - */ - protected function getLoginStatusUrlString($format = 'json') { - $user_login_status_url = Url::fromRoute('user.login_status.http'); - $user_login_status_url->setRouteParameter('_format', $format); - $user_login_status_url->setAbsolute(); - return $user_login_status_url->toString(); - } - -} diff --git a/core/modules/user/user.routing.yml b/core/modules/user/user.routing.yml index caea9795bcef..6eea7ececfe8 100644 --- a/core/modules/user/user.routing.yml +++ b/core/modules/user/user.routing.yml @@ -129,34 +129,6 @@ user.login: options: _maintenance_access: TRUE -user.login.http: - path: '/user/login' - defaults: - _controller: \Drupal\user\Controller\UserAuthenticationController::login - methods: [POST] - requirements: - _user_is_logged_in: 'FALSE' - _format: 'json' - -user.login_status.http: - path: '/user/login_status' - defaults: - _controller: \Drupal\user\Controller\UserAuthenticationController::loginStatus - methods: [GET] - requirements: - _access: 'TRUE' - _format: 'json' - -user.logout.http: - path: '/user/logout' - defaults: - _controller: \Drupal\user\Controller\UserAuthenticationController::logout - methods: [POST] - requirements: - _user_is_logged_in: 'TRUE' - _format: 'json' - _csrf_token: 'TRUE' - user.cancel_confirm: path: '/user/{user}/cancel/confirm/{timestamp}/{hashed_pass}' defaults: diff --git a/core/tests/Drupal/Tests/Core/Messenger/SessionMessengerTest.php b/core/tests/Drupal/Tests/Core/Messenger/SessionMessengerTest.php deleted file mode 100644 index 2da979c0a20f..000000000000 --- a/core/tests/Drupal/Tests/Core/Messenger/SessionMessengerTest.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php - -namespace Drupal\Tests\Core\Messenger; - -use Drupal\Core\Messenger\SessionMessenger; -use Drupal\Core\PageCache\ResponsePolicy\KillSwitch; -use Drupal\Tests\UnitTestCase; - -/** - * @coversDefaultClass \Drupal\Core\Messenger\SessionMessenger - * @group messenger - */ -class SessionMessengerTest extends UnitTestCase { - - /** - * A copy of any existing session data to restore after the test. - * - * @var array - */ - protected $existingSession; - - /** - * The messenger under test. - * - * @var \Drupal\Core\Messenger\SessionMessenger - */ - protected $messenger; - - /** - * The page caching kill switch. - * - * @var \Drupal\Core\PageCache\ResponsePolicy\KillSwitch|\PHPUnit_Framework_MockObject_MockObject - */ - protected $pageCacheKillSwitch; - - /** - * {@inheritdoc} - */ - public function setUp() { - $this->pageCacheKillSwitch = $this->prophesize(KillSwitch::class); - - $this->existingSession = isset($_SESSION) ? $_SESSION : NULL; - $_SESSION = []; - } - - /** - * {@inheritdoc} - */ - public function tearDown() { - if ($this->existingSession !== NULL) { - $_SESSION = $this->existingSession; - } - else { - unset($_SESSION); - } - } - - /** - * @covers ::addMessage - * @covers ::getMessages - * @covers ::getMessagesByType - * @covers ::deleteMessages - * @covers ::deleteMessagesByType - */ - public function testMessenger() { - $this->pageCacheKillSwitch->trigger()->shouldBeCalled(); - - $this->messenger = new SessionMessenger($this->pageCacheKillSwitch->reveal()); - - $message_a = $this->randomMachineName(); - $type_a = $this->randomMachineName(); - $message_b = $this->randomMachineName(); - $type_b = $this->randomMachineName(); - - // Test that if there are no messages, the default is an empty array. - $this->assertEquals($this->messenger->getMessages(), []); - - // Test that adding a message returns the messenger and that the message can - // be retrieved. - $this->assertEquals($this->messenger->addMessage($message_a, $type_a), $this->messenger); - $this->messenger->addMessage($message_a, $type_a); - $this->messenger->addMessage($message_a, $type_a, TRUE); - $this->messenger->addMessage($message_b, $type_b, TRUE); - $this->assertEquals($this->messenger->getMessages(), [ - $type_a => [$message_a, $message_a], - $type_b => [$message_b], - ]); - - // Test deleting messages of a certain type. - $this->assertEquals($this->messenger->deleteMessagesByType($type_a), $this->messenger); - $this->assertEquals($this->messenger->getMessages(), [ - $type_b => [$message_b], - ]); - - // Test deleting all messages. - $this->assertEquals($this->messenger->deleteMessages(), $this->messenger); - $this->assertEquals($this->messenger->getMessages(), []); - } - -} diff --git a/core/tests/Drupal/Tests/Core/Messenger/StaticMessengerTest.php b/core/tests/Drupal/Tests/Core/Messenger/StaticMessengerTest.php deleted file mode 100644 index d3158954497d..000000000000 --- a/core/tests/Drupal/Tests/Core/Messenger/StaticMessengerTest.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php - -namespace Drupal\Tests\Core\Messenger; - -use Drupal\Core\Messenger\StaticMessenger; -use Drupal\Core\PageCache\ResponsePolicy\KillSwitch; -use Drupal\Tests\RandomGeneratorTrait; - -/** - * @coversDefaultClass \Drupal\Core\Messenger\StaticMessenger - * @group messenger - */ -class StaticMessengerTest extends \PHPUnit_Framework_TestCase { - - use RandomGeneratorTrait; - - /** - * The messenger under test. - * - * @var \Drupal\Core\Messenger\StaticMessenger - */ - protected $messenger; - - /** - * The page caching kill switch. - * - * @var \Drupal\Core\PageCache\ResponsePolicy\KillSwitch|\PHPUnit_Framework_MockObject_MockObject - */ - protected $pageCacheKillSwitch; - - /** - * {@inheritdoc} - */ - public function setUp() { - $this->pageCacheKillSwitch = $this->prophesize(KillSwitch::class); - } - - /** - * @covers ::addMessage - * @covers ::getMessages - * @covers ::getMessagesByType - * @covers ::deleteMessages - * @covers ::deleteMessagesByType - */ - public function testMessenger() { - $message_a = $this->randomMachineName(); - $type_a = $this->randomMachineName(); - $message_b = $this->randomMachineName(); - $type_b = $this->randomMachineName(); - - $this->pageCacheKillSwitch->trigger()->shouldBeCalled(); - - $this->messenger = new StaticMessenger($this->pageCacheKillSwitch->reveal()); - - // Test that if there are no messages, the default is an empty array. - $this->assertEquals($this->messenger->getMessages(), []); - - // Test that adding a message returns the messenger and that the message can - // be retrieved. - $this->assertSame($this->messenger->addMessage($message_a, $type_a), $this->messenger); - $this->messenger->addMessage($message_a, $type_a); - $this->messenger->addMessage($message_a, $type_a, TRUE); - $this->messenger->addMessage($message_b, $type_b, TRUE); - $this->assertEquals([ - $type_a => [$message_a, $message_a], - $type_b => [$message_b], - ], $this->messenger->getMessages()); - - // Test deleting messages of a certain type. - $this->assertEquals($this->messenger->deleteMessagesByType($type_a), $this->messenger); - $this->assertEquals([ - $type_b => [$message_b], - ], $this->messenger->getMessages()); - - // Test deleting all messages. - $this->assertEquals($this->messenger->deleteMessages(), $this->messenger); - $this->assertEquals([], $this->messenger->getMessages()); - } - -} -- GitLab