4

With D8, I have a node (content type: basic page) that I use as a custom 403 (access denied) page.

I set this as the custom 403 page on: /admin/config/system/site-information. The path is /node/21, and the alias is /error/403.

On the block admin page, I added the user login block to the content region. I added the restriction "show only on certain pages":

  • /error/*
  • /view/*
  • /node/21

I have a view that requires "add content type ABC permission" to access. The path to the view is /view/abc. The anonymous user does NOT have this permission.

So, as an anonymous user, I go to /view/abc and am shown the content of /node/21. BUT, the user login block is not shown.

If I go to the block administration screen and remove the "show only on certain pages" restriction, then I see the block as the anonymous user on /view/abc, but I don't want to show the login block on every single page; I only want to show it on the pages that are 403s.

What is the "path" to use for the user login block to only show it on a custom 403 page?

2

One approach is to add page templates to your theme registry:

function MYMODULE_theme_suggestions_page_alter(array &$suggestions, array $variables) {

  //Allow theming the site error pages
  $route_name = \Drupal::routeMatch()->getRouteName();

  switch ($route_name) {
    case 'system.401':
    // Unauthorized Access.
    $error = 401;
    break;

    case 'system.403':
    // Access Denied.
    $error = 403;
    break;

    case 'system.404':
    // Page Not Found.
    $error = 404;
    break;
  }

  if (isset($error)) {
    $suggestions[] = 'page__' . $error;
  }

}

Then in page--403.html.twig you can render a specific block with Twig. See: How to embed a view in a specific node? and Programatically print blocks in twig

*A reason I like this approach is that the Login block is a Drupal core block, not a custom one. You can just carry around a nice 403 template file and always know it will render out this block. The preprocess function above seems like the least invasive and time consuming (from looking at different approaches), plus it gives the ability to theme these error pages. I think it is ideal to utilize template files for error pages.

0

If you can code, you should go for a ConditionPlugin.

Just like RequestPath*(ConditionPlugin) we built a custom RouteCondition plugin. That allows us to have granularity on each route.

In your case, a simple ConditionPlugin could be the proper starting point.

Here is an example * (www/modules/custom/{your_module}/src/Plugin/Condition/NotFoundCondition.php)

<?php

namespace Drupal\{your_module}\Plugin\Condition;


use Drupal\Core\Condition\ConditionPluginBase;

/**
 * Provides a 'Error Pages 403' condition.
 *
 * @Condition(
 *   id = "error_403_pages",
 *   label = @Translation("Error 403 Pages"),
 * )
 */
class ErrorPages extends ConditionPluginBase {

  /**
   * @return bool
   */
  public function evaluate() {
      //  Retrieve the current route
      $route_name = \Drupal::service('current_route_match')->getRouteName();

      // Does we have a match
      return strpos( $route_name, 'system.403') === 0 * $this->isNegated();

    // EDIT: the negate concept might be a bit overwelming at first.
    // Maybe you don't need it right now

  }

  public function summary() {
    if (!empty($this->configuration['negate'])) {
      return $this->t('Do not return true on 403 pages');
    }
    return $this->t('Return true on 403 pages');

  }
}

After a cache rebuild you should be able to place the login block on 403 page using structure>block layout

  • What is the FormStateInterface doing there? It's unused, innit? And where's the login block??? – leymannx Jan 15 at 14:01
  • FormStateInterface was an artifact. I edited the post. – SwingingTom Jan 15 at 14:12
  • 3
    Whereas a custom condition plugin is a good idea, your example won't work, if a custom node is used as error page. In this case, the most reliable way is to check the exception attribute from the request for being an instance of AccessDeniedHttpException. – Mario Steinitz Jan 15 at 14:27
  • @MarioSteinitz You are right. I didn't have this in mind. – SwingingTom Jan 15 at 14:37
  • 2
    @MarioSteinitz, exactly, this is how the patch and the module in the linked question implements the condition. You can get the exception type also with getStatusCode() on the exception object. The patch doesn't care, its condition is for all exceptions, but the module does. See the plugin code of the module cgit.drupalcode.org/block_in_page_not_found/tree/src/Plugin/… – 4k4 Jan 15 at 16:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.