I have a website where I use the book module to structure my pages. I made a custom module to forbid access to a node based on a boolean field in the book parent.
Simplified: When this field is set to true in the book parent, access for all child nodes is forbidden.
When this field is set to false the specific child node that is set as frontpage is accessible via its own path for example book.com/page-1 works. But the front page book.com (showing page-1) still shows a log in page and is not accissible? Emptying all cache solves the probleem but I don't want to empty all cache when this value changes.
I tried using cache meta data to solve it but it doesn't work yet.
$access_result = AccessResult::forbidden() ->cachePerPermissions() ->cachePerUser() ->addCacheableDependency($node) ->addCacheContexts(['route.name', 'url.path']); // Add cache dependencies for parent entities if ($book-parent) { $access_result->addCacheableDependency($book-parent); } if ($book-level-2) { $access_result->addCacheableDependency($book-level-2); } return $access_result; I also tried invalidating cache for all child nodes with level 2:
foreach ($nids as $nid) { $cache_tags_to_invalidate[] = 'node:' . $nid; } // Invalidate cache tags for all affected nodes if (!empty($cache_tags_to_invalidate)) { Cache::invalidateTags($cache_tags_to_invalidate); } None of these did solve my problem. How to do this right so that the access is restored also for the frontpage?
The full code:
function private_content_node_access(NodeInterface $node, $op, AccountInterface $account) { if (!LoadValues::isAdmin() && $node->bundle() !== 'column' && $node->bundle() !== 'page' && $node->bundle() !== 'view') { //get book and book editor/viewers $book = LoadValues::loadParentBook($node); $book_editors = array_column($book->field_user->getValue(), 'target_id'); $book_viewers = array_column($book->field_share->getValue(), 'target_id'); $allowedUsers = array_merge($book_editors, $book_viewers); //get book and book editor/viewers if ($node->bundle() !== 'reader') { $issue = LoadValues::loadParentIssue($node); $issue_viewers = array_column($issue->field_share->getValue(), 'target_id'); $allowedUsers = array_merge($allowedUsers, $issue_viewers); } //add owners of book (reader_administrator) and current node $allowedUsers[] = $book->getOwnerId(); $allowedUsers[] = $node->getOwnerId(); $private_book = 0; if ($book !== null) { //get private state from book $private_book = $book->field_private->get(0)->value; } $private_issue = 0; if (isset($issue) && count($issue->field_private) > 0) { //get private state from issue $private_issue = $issue->field_private->get(0)->value; } /* @ -- Book / Issue Privacy */ if ($private_book == 1 || $private_issue == 1) { if ($op == 'view') { $currentUser = User::load($account->id()); if ((!$node->isPublished() && $currentUser->hasRole('reading_group'))) { //excluded nodes for reading group members that are not published return AccessResult::forbidden(); } else { if (in_array($account->id(), $allowedUsers)) { //make private content accessible for the co-editors of the node return AccessResult::allowed() ->cachePerPermissions() ->cachePerUser() ->addCacheableDependency($node); } else { return AccessResult::forbidden(); } } } return AccessResult::neutral(); } } }