Commit 8d98311f authored by Greg Knaddison's avatar Greg Knaddison Committed by Léo Prada
Browse files

Issue #3201471 by greggles, lkacenja, Nixou: Show a message when redirecting authenticated users

parent 5883fa88
Loading
Loading
Loading
Loading
+3 −0
Changes for config/install/r4032login.settings.yml: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -2,6 +2,9 @@ display_denied_message: true
access_denied_message: 'Access denied. You must log in to view this page.'
access_denied_message_type: 'error'
redirect_authenticated_users_to: ''
display_auth_denied_message: true
access_denied_auth_message: "Access denied. Check with your site administrator if you need assistance."
access_denied_auth_message_type: 'error'
user_login_path: '/user/login'
default_redirect_code: 307
destination_parameter_override: ''
+9 −0
Changes for config/schema/r4032login.schema.yml: 9 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -14,6 +14,15 @@ r4032login.settings:
    redirect_authenticated_users_to:
      type: label
      label: 'Redirect authenticated users to'
    display_auth_denied_message:
      type: boolean
      label: 'Display access denied message on authenticated landing page'
    access_denied_auth_message:
      type: label
      label: "Authenticated user 'access denied' message"
    access_denied_auth_message_type:
      type: string
      label: "Authenticated user 'access denied' message type"
    user_login_path:
      type: path
      label: '/user/login'
+72 −28
Changes for r4032login.module: 72 added lines, 28 removed lines.
Original line number Diff line number Diff line
@@ -24,28 +24,42 @@ function r4032login_form_system_site_information_settings_alter(&$form, FormStat
  $form['error_page']['r4032login'] = [
    '#type' => 'details',
    '#title' => t('Redirect 403 to User Login'),
    '#description' => t('Redirect anonymous users from 403 Access Denied pages to the /user/login page.'),
    '#description' => t('Redirect users from 403 Access Denied pages to another page.'),
    '#open' => TRUE,
  ];
  $form['error_page']['r4032login']['r4032login_redirect_to_destination'] = [
  $form['error_page']['r4032login']['anonymous'] = [
    '#type' => 'details',
    '#title' => t('Behavior for anonymous users'),
    '#open' => TRUE,
  ];
  $form['error_page']['r4032login']['anonymous']['r4032login_user_login_path'] = [
    '#type' => 'textfield',
    '#title' => t('Redirect anonymous users to'),
    '#description' => t('If anonymous user tries to access a page they can not, redirect them to the given page. Include the leading slash, i.e.: /user/login.'),
    '#default_value' => $config->get('user_login_path'),
  ];
  $form['error_page']['r4032login']['anonymous']['r4032login_redirect_to_destination'] = [
    '#type' => 'checkbox',
    '#weight' => 4,
    '#title' => t('Redirect user to the page they tried to access after login'),
    '#title' => t('Redirect anonymous users to the page they tried to access after login'),
    '#default_value' => $config->get('redirect_to_destination'),
  ];
  $form['error_page']['r4032login']['r4032login_display_denied_message'] = [
  $form['error_page']['r4032login']['anonymous']['r4032login_destination_parameter_override'] = [
    '#type' => 'textfield',
    '#title' => t("Destination parameter override"),
    '#description' => t("The parameter to use when setting the return destination once login has succeeded. By default Drupal uses 'destination', but overriding this may be necessary if using an external login system such as CAS, Shibboleth or OAuth."),
    '#default_value' => $config->get('destination_parameter_override'),
  ];
  $form['error_page']['r4032login']['anonymous']['r4032login_display_denied_message'] = [
    '#type' => 'checkbox',
    '#weight' => 5,
    '#title' => t('Display access denied message on login page'),
    '#description' => t('Displays an access denied message on the user login page.'),
    '#default_value' => $config->get('display_denied_message'),
  ];
  $form['error_page']['r4032login']['r4032login_access_denied_message'] = [
  $form['error_page']['r4032login']['anonymous']['r4032login_access_denied_message'] = [
    '#type' => 'textarea',
    '#rows' => 1,
    '#weight' => 6,
    '#title' => t("User login 'access denied' message"),
    '#description' => t('The message text displayed to users who are denied access to the page.'),
    '#description' => t('The message text displayed to anonymous users who are denied access to the page.'),
    '#default_value' => $config->get('access_denied_message'),
    '#states' => [
      'invisible' => [
@@ -55,7 +69,7 @@ function r4032login_form_system_site_information_settings_alter(&$form, FormStat
      ],
    ],
  ];
  $form['error_page']['r4032login']['r4032login_access_denied_message_type'] = [
  $form['error_page']['r4032login']['anonymous']['r4032login_access_denied_message_type'] = [
    '#type' => 'select',
    '#title' => t("User login 'access denied' message type"),
    '#description' => t('The message type displayed to users who are denied access to the page.'),
@@ -65,7 +79,6 @@ function r4032login_form_system_site_information_settings_alter(&$form, FormStat
      'warning' => t('Warning'),
      'status' => t('Status'),
    ],
    '#weight' => 7,
    '#states' => [
      'invisible' => [
        'input[name="r4032login_display_denied_message"]' => [
@@ -74,23 +87,59 @@ function r4032login_form_system_site_information_settings_alter(&$form, FormStat
      ],
    ],
  ];
  $form['error_page']['r4032login']['r4032login_redirect_authenticated_users_to'] = [
  $form['error_page']['r4032login']['authenticated'] = [
    '#type' => 'details',
    '#title' => t('Behavior for authenticated users'),
    '#open' => TRUE,
  ];
  $form['error_page']['r4032login']['authenticated']['r4032login_redirect_authenticated_users_to'] = [
    '#type' => 'textfield',
    '#weight' => 8,
    '#title' => t("Redirect authenticated users to"),
    '#description' => t('If an authenticated user tries to access a page they can not, redirect them to the given page. Use <front> for the front page, leave blank for a default access denied page.'),
    '#default_value' => $config->get('redirect_authenticated_users_to'),
  ];
  $form['error_page']['r4032login']['r4032login_user_login_path'] = [
    '#type' => 'textfield',
    '#weight' => 9,
    '#title' => t("Path to user login form"),
    '#description' => t('The path to the user login form. Include the leading slash, i.e.: /user/login.'),
    '#default_value' => $config->get('user_login_path'),

  $form['error_page']['r4032login']['authenticated']['r4032login_display_auth_denied_message'] = [
    '#type' => 'checkbox',
    '#title' => t('Display access denied message on authenticated landing page'),
    '#default_value' => $config->get('display_auth_denied_message'),
  ];
  $form['error_page']['r4032login']['authenticated']['r4032login_access_denied_auth_message'] = [
    '#type' => 'textarea',
    '#rows' => 1,
    '#title' => t("Authenticated user 'access denied' message"),
    '#description' => t('The message text displayed to authenticated users who are denied access to the page.'),
    '#default_value' => $config->get('access_denied_auth_message'),
    '#states' => [
      'invisible' => [
        'input[name="r4032login_display_auth_denied_message"]' => [
          'checked' => FALSE,
        ],
      ],
    ],
  ];
  $form['error_page']['r4032login']['authenticated']['r4032login_access_denied_auth_message_type'] = [
    '#type' => 'select',
    '#title' => t("Authenticated user 'access denied' message type"),
    '#description' => t('The message type displayed to authenticated users who are denied access to the page.'),
    '#default_value' => $config->get('access_denied_auth_message_type'),
    '#options' => [
      'error' => t('Error'),
      'warning' => t('Warning'),
      'status' => t('Status'),
    ],
    '#weight' => 11,
    '#states' => [
      'invisible' => [
        'input[name="r4032login_display_auth_denied_message"]' => [
          'checked' => FALSE,
        ],
      ],
    ],
  ];

  $form['error_page']['r4032login']['r4032login_default_redirect_code'] = [
    '#type' => 'select',
    '#weight' => 10,
    '#title' => t("HTTP redirect code"),
    '#description' => t('The redirect code to send by default. 301 and 302 responses may be cached by browsers and proxies, so 307 is normally the correct choice.'),
    '#options' => [
@@ -100,19 +149,11 @@ function r4032login_form_system_site_information_settings_alter(&$form, FormStat
    ],
    '#default_value' => $config->get('default_redirect_code'),
  ];
  $form['error_page']['r4032login']['r4032login_destination_parameter_override'] = [
    '#type' => 'textfield',
    '#weight' => 11,
    '#title' => t("Destination parameter override"),
    '#description' => t("The parameter to use when setting the return destination once login has succeeded. By default Drupal uses 'destination', but overriding this may be necessary if using an external login system such as CAS, Shibboleth or OAuth."),
    '#default_value' => $config->get('destination_parameter_override'),
  ];
  $form['error_page']['r4032login']['matching_paths'] = [
    '#type' => 'details',
    '#title' => t('Skip redirect for matching pages'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    '#weight' => 12,
  ];
  $form['error_page']['r4032login']['matching_paths']['r4032login_match_noredirect_pages'] = [
    '#type' => 'textarea',
@@ -183,6 +224,9 @@ function r4032login_form_system_site_information_settings_form_submit($form, For
    ->set('access_denied_message', $form_state->getValue('r4032login_access_denied_message'))
    ->set('access_denied_message_type', $form_state->getValue('r4032login_access_denied_message_type'))
    ->set('redirect_authenticated_users_to', $form_state->getValue('r4032login_redirect_authenticated_users_to'))
    ->set('display_auth_denied_message', $form_state->getValue('r4032login_display_auth_denied_message'))
    ->set('access_denied_auth_message', $form_state->getValue('r4032login_access_denied_auth_message'))
    ->set('access_denied_auth_message_type', $form_state->getValue('r4032login_access_denied_auth_message_type'))
    ->set('user_login_path', $form_state->getValue('r4032login_user_login_path'))
    ->set('default_redirect_code', $form_state->getValue('r4032login_default_redirect_code'))
    ->set('destination_parameter_override', $form_state->getValue('r4032login_destination_parameter_override'))
+12 −0
Changes for src/EventSubscriber/R4032LoginSubscriber.php: 12 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -178,6 +178,18 @@ class R4032LoginSubscriber extends HttpExceptionSubscriberBase {
          $messageType = $config->get('access_denied_message_type');
          $this->messenger->addMessage(Markup::create(Xss::filterAdmin($message)), $messageType);
        }
        if ($this->currentUser->isAuthenticated()) {
          // If user is authenticated, remove destination to prevent looping.
          if (!empty($options['query']) && !empty($options['query']['destination'])) {
            unset($options['query']);
          }
          // Show custom access denied message for authenticated users if set.
          if ($config->get('display_auth_denied_message')) {
            $message = $config->get('access_denied_auth_message');
            $messageType = $config->get('access_denied_auth_message_type');
            $this->messenger->addMessage(Markup::create(Xss::filterAdmin($message)), $messageType);
          }
        }

        if ($redirectPath === '<front>') {
          $url = Url::fromRoute('<front>', [], $options)->toString();
+106 −0
Changes for tests/src/Functional/AuthenticatedRedirectCustomMessageTest.php: 106 added lines, 0 removed lines.
Original line number Diff line number Diff line
<?php

namespace Drupal\Tests\r4032login\Functional;

use Drupal\Tests\BrowserTestBase;

/**
 * Test authenticated redirection includes a custom message.
 *
 * @group r4032login
 */
class AuthenticatedRedirectCustomMessageTest extends BrowserTestBase {

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

  /**
   * {@inheritdoc}
   */
  protected static $modules = ['r4032login'];

  /**
   * A regular user.
   *
   * @var \Drupal\user\UserInterface
   */
  protected $webUser;

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();

    $this->webUser = $this->drupalCreateUser();
  }

  /**
   * Test message override behavior or redirection of authenticated users.
   *
   * @param string $message
   *   The message to set in config and to look for after redirecting.
   * @param string $message_type
   *   The type of message to show.
   * @param string $selector
   *   The selector to look for the message within.
   *
   * @throws \Behat\Mink\Exception\ExpectationException
   *
   * @dataProvider baseRedirectMessageDataProvider
   */
  public function testAuthenticatedRedirectMessage($message, $message_type, $selector) {
    $config = $this->config('r4032login.settings');
    $config->set('access_denied_auth_message', $message);
    $config->set('access_denied_auth_message_type', $message_type);
    $config->set('redirect_authenticated_users_to', '/');
    $config->save();

    $this->drupalLogin($this->webUser);

    $this->drupalGet('admin/config');
    $this->assertSession()->elementContains('css', $selector, $message);
  }

  /**
   * Data provider for testAuthenticatedRedirectMessage.
   */
  public function baseRedirectMessageDataProvider() {
    return [
      [
        'You are not supposed to be here.',
        'error',
        'div[aria-label="Error message"]',
      ],
      [
        'You are not supposed to be <p>here</p>.',
        'warning',
        'div[aria-label="Warning message"]',
      ],
      [
        'You are not supposed to be here.',
        'status',
        'div[aria-label="Status message"]',
      ],
    ];
  }

  /**
   * Test authenticated message will not appear if disabled.
   *
   * @throws \Behat\Mink\Exception\ExpectationException
   */
  public function testDisabledAuthenticatedRedirectMessage() {
    $config = $this->config('r4032login.settings');
    $config->set('display_auth_denied_message', FALSE);
    $config->save();

    $this->drupalLogin($this->webUser);

    $this->drupalGet('admin/config');
    $this->assertSession()->elementNotExists('css', 'div[aria-label="Error message"]');
  }

}
Loading