web-dev-qa-db-ja.com

ユーザー(管理者/編集者を除く)がコンテンツタイプの正規ページを表示できないようにする方法

特定のコンテンツタイプについて、ほとんどのユーザーがランディングページまたは他のノードページに読み込まれたときにコンテンツタイプ(ノードバンドル)を表示できるようにしたいが、ルートエンティティにアクセスできないようにする場合コンテンツタイプの.node.canonicalは、明示的な権限(管理者ロールと編集者ロールに付与される)がない限り、Drupal 8?

例として、サイトに「動画」コンテンツタイプがあり、関連動画ブロックなどのブロックに読み込まれたときに、誰もがそれを表示できるようにしたいが、ユーザーがその動画にアクセスしようとした場合、正規ページの場合、404を取得します。ただし、ページを表示する権限を持つロールがない場合に限ります。

これは、ブロック内でのみアクセスを許可するコンテンツまたはメディアエンティティの特定のバンドルの場合ですが、ユーザーに適切な権限がない場合は、正規ページが404である必要があります。

これをDrupal 8に設定するための最良の戦略は何ですか?

2
oknate

Drupal 7では、Rulesでこれを実行できると思います。Rulesモジュールは、技術的にDrupal 8で利用できますが、方法を理解できませんでしたそれを使用するので、条件に基づいて手動でリダイレクトするカスタムモジュールを接続する方法を示します。


基本的な考え方は、カスタムリダイレクトを行うには、EventSubscriberサービスを登録し、REQUEST KernelEventにサブスクライブし、その後、リクエストオブジェクト全体にアクセスできるようにする必要があるということです。

私の会社の場合、「リダイレクト」というカスタムモジュールを作成したので、この例で使用します。

まず、redirect.services.ymlファイルを作成します。

services:
  redirect.subscriber:
    class: Drupal\redirect\EventSubscriber\RedirectSubscriber
    tags:
      - { name: event_subscriber}

次に、上記で参照されたクラス(Drupal\redirect\EventSubscriber\RedirectSubscribersrc/EventSubscriber/RedirectSubscriber.php

<?php

namespace Drupal\redirect\EventSubscriber;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Drupal\node\Entity\Node;

class RedirectSubscriber implements EventSubscriberInterface {

  public function redirect(GetResponseEvent $event) {
    $request = $event->getRequest();
    $baseUrl = $request->getBaseUrl();
    $attr = $request->attributes;
    $roles = \Drupal::currentUser()->getRoles();

    if ($attr !== null) {
      $node = $attr->get('node');
      if ($node !== null && $node instanceof Node) {
        $type = $node->get('type')->getString();
        if ($type == 'seel_lesson_plan' && !in_array('administrator', $roles)) {
          $event->setResponse(
            new RedirectResponse("$baseUrl/url-to-404-page")
          );
        }
      }
    }
  }

  static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = ['redirect'];
    return $events;
  }

}

これがどのように機能するかをよりよく理解するには、 イベントサブスクライバーの登録の説明公式イベントAPIページ 、および this other Drupal SEの質問 コンテンツページのリダイレクトについて。

4

リンカーンの答えを90%にしたので、正解としてマークしました。しかし、ここにリダイレクトの代わりに404をスローする私のバージョンがあります。

これをmymodule.services.ymlファイルに追加します。

services:
  mymodule.canonical_404_subscriber:
    class: Drupal\mymodule\EventSubscriber\KernalEventSubscriber
    tags:
      - { name: event_subscriber}

/modules/custom/mymodule/src/EventSubscriber/KernalEventSubscriber.php

こちらがクラスです。

/**
 * Class KernalEventSubscriber
 *
 * Restrict access to the canonical pages for certain entities
 * and node bundles.
 */
class KernalEventSubscriber implements EventSubscriberInterface {

  public function checkAccess(GetResponseEvent $event) {

    // Routes to block, regardless of bundle, if
    // user lacks the appropriate role.
    $blocked_routes = [
      'entity.custom_entity1.canonical',
      'entity.media.canonical',
      'entity.custom_entity2.canonical'
    ];

    $allowed_roles = [
      'administrator'
    ];

    $current_route = \Drupal::routeMatch()->getRouteName();

    $current_user_roles = \Drupal::currentUser()->getRoles();

    if (in_array($current_route, $blocked_routes)) {
      if (empty(array_intersect($allowed_roles, $current_user_roles))) {
        throw new NotFoundHttpException();
      }
    }

    // Node bundles to block, if
    // user lacks the appropriate role.
    $node_bundles = [
      'photo_gallery',
      'video'
    ];

    if ($current_route == 'entity.node.canonical') {
      $node = \Drupal::routeMatch()->getParameter('node');
      if (in_array($node->bundle(), $node_bundles) && empty(array_intersect($allowed_roles, $current_user_roles))) {
        throw new NotFoundHttpException();
      }
    }

  }

  static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = ['checkAccess'];
    return $events;
  }

}
1
oknate