web-dev-qa-db-ja.com

付与システムの参照ノードに基づいてアクセスチェックを実装するにはどうすればよいですか?

別のスレッドの提案に従って ここ Drupalの許可システムでhook_node_accessを使用して開発したアクセス制限(およびこれまでのところうまく機能している)を書き直そうとしています(つまり、hook_node_access_recordshook_node_grantsを使用しています)。私はそれを2つの理由でしたいと思います:

  1. ユーザー数が増えると、現在のアクセスチェックがパフォーマンスのボトルネックになるのではないかと心配しています。
  2. アクセスチェックの結果をビューのフィルターとして使用する必要があります。

これが、現在のアクセスチェックの一部を省略したものです。

function mymodule_node_access(\Drupal\node\NodeInterface $node, $op, \Drupal\Core\Session\AccountInterface $account){
  $type = $node->bundle();
  $user = $account->getAccount();
  $uid = $user->id();

  // only handle the lesson content type
  if ($type === 'lesson') {

    // ...

    // check the user's access to the referring courses
    $courseaccess = FALSE;
    if ($node->hasField('reverse_entity_reference')) {
      $parentcourses = $node->get('reverse_entity_reference')->getValue();
      foreach ($parentcourses as $course) {
        $coursenode = \Drupal\node\Entity\Node::load($course['target_id']);
        // perform access checks for the referring course
        $courseaccess = $courseaccess || ...
      }
    }

    // ...

    // return the result
    if ($courseaccess) {
      return AccessResult::allowed();
    } else {
      return AccessResult::forbidden();
    }
  }

  // ...

}

本質的に、現在のユーザーが参照しているノード(courses)のいずれかにアクセスできるかどうかをチェックする必要があることに注意してください。表示されたノード(lessons:これは、ユーザーがlessonにアクセスできるかどうかを決定します。そのために逆エンティティ参照を使用しています。

それを見ると(私は提案を受け入れることができます)、これに取り組むには基本的に2つの方法があります。残念ながら、これまでのところ、関連する問題を解決できていません。だから、私の理解では、私は...

  1. フルアクセスロジックを(多かれ少なかれ)hook_node_grantsに入れます:つまり、私はhook_node_grantsで現在表示されているノード(lesson)にアクセスできる必要があるため、ユーザーが参照ノードのいずれかにアクセスできるかどうかを確認するための逆参照。それは可能ですか? $node変数はありません...
  2. フルアクセスロジックを(多かれ少なかれ)hook_node_access_recordsに入れます:その場合、ノードがいつでもフックが呼び出される(したがってlessonが更新される)だけであることが問題です保存されます。したがって、レッスンが別のコースに含まれるとすぐに、アクセス制限は古くなります。

この時点でどのように進めるかわかりません。助成金制度でこれを書き換えることは可能ですか?他のアイデアは?

1
Marcus C.

要件の完全なリストがなく、Q&Aが長時間のディスカッションに適さない場合、明確にイエスと言うことは不可能です。

助成金システムは、階層のあらゆる種類のアイデアを中心に設計されていません。書き換えは可能ですか?付与システムが提供するものに関して既存のロジックをリファクタリングできるかどうかによって異なります。

あなたは質問をジレンマとして組み立てましたが、グラントシステムを使用するには両方のフックが本当に必要です。

  • _hook_node_grants_は、_$user_に対応するrealm/gid許可と、彼らがアクセスできる利用可能なレッスンnidを割り当てる必要があります。
  • _hook_node_access_records_は、レッスンに対して起動する必要があります_$node_

だからできるなら:

  • realm/gid付与キーをマップして、ユーザーがアクセスできるコースに一致させます(例_mymodule_course_realm_/_123_ where _123_マップするいくつかのグループ識別子)コースへのアクセス権を持つユーザーのグループへのレッスンnidアクセス権)
  • トリガーlessonコースの更新時にイベントを保存します(たとえば、_hook_node_update_、_hook_node_insert_などを使用して更新コースを探し、レッスンノードでダミー保存を行う)。これにより、_hook_node_access_records_は、関係が変更されたlessonノードに対して起動できます。 (または、NodeGrantDatabaseStorage::write()を介して直接許可を挿入するカスタムロジックを構築します)

おそらく、グラントシステムが提供するフックをリファクタリングすることができます。

1
Shawn Conn