0

I have scoured the internet trying to find information on how to achieve this functionality to no avail. I am hoping I can get an answer here.

I have a content type called 'Server' on my website. One of the fields on 'Server' is an 'Access Role' field, which is an entity reference of user roles.

When a new piece of content is made, the author selects one (or multiple roles) that have access to this piece of content (The author can't be granted the 'manage roles' permission, so they can't use the standard 'permissions' options available when creating content).

I have a view setup (that is a REST EXPORT of type key_auth. When a user accesses the endpoint using their auth key, the view should return a list of server content that matches ONLY if one of the users roles is in the access roles field for the piece of content. I can't seem to find out how to achieve this using views and filters.

As an example;

Server 1 Access Roles: Developer, Testing

Server 2 Access Roles: Administrator

The user accessing the endpoint does not have the administrator role, but does have the Testing role. When the user accesses the endpoint, only 'Server 1' should return for them, since that's the only server that matches one of their roles. If more servers matched, those servers would be displayed, too.

I have the access roles setup, and the view setup to connect the api key to the correct user, but can't figure out how to set the filter up to match user roles to one of the possible access roles on the server content.

Is there somebody that could offer me some assistance?

1 Answer 1

0

EDIT: I think this is actually wrong: Views doesn't evaluate hook_node_access() for performance reasons. How to filter a view according to nodes permissions

It's going to be difficult for Views to model the relationships needed for this correctly, because Roles are configuration entities in Drupal 8 (as opposed to content entities).

You may be going about this the wrong way, though. Views already respects entity access control, preventing entities from showing in results if the current user doesn't have permission to access those entities. You haven't made those access control rules explicit to Drupal yet, which is why they don't get automatically filtered out in Views. But you could implement hook_node_access() to formally describe those access permission rules to Drupal.

Here's the API documentation example: https://api.drupal.org/api/drupal/core!modules!node!node.api.php/function/hook_node_access/8.8.x

Your implementation would look something like this:

<?php

function MYMODULE_node_access(\Drupal\node\NodeInterface $node, $op, \Drupal\Core\Session\AccountInterface $account) {
  if ($op == 'view' && $node->hasField('field_roles')) {
    $node_roles = array_column($node->field_roles->getValue(), 'target_id');
    $user_roles = $account->getRoles();
    if (array_intersect($node_roles, $user_roles)) {
      return \Drupal\Core\Access\AccessResult::allowed();
    }
    else {
      return \Drupal\Core\Access\AccessResult::forbidden();
    }
  }
  return \Drupal\Core\Access\AccessResult::neutral();
}
5
  • From my understanding, this would be on a content type basis, not a single piece of content basis. I need it to be single piece of content basis as the server content type itself is viewable by everyone, but individual nodes/entities in that content type are only visible by people with the correct roles as provided on the piece of content.
    – Ex0r
    Commented May 14, 2020 at 17:42
  • The ultimate goal, is for an author to create a new piece of 'server' content, specify what roles can access that piece of content, and move on.
    – Ex0r
    Commented May 14, 2020 at 17:42
  • @Ex0r: hook_node_access() actually is evaluated separately for each single piece of content. I've updated the answer with an implementation example to illustrate.
    – Les Lim
    Commented May 14, 2020 at 19:05
  • Wait, turns out that Views doesn't evaluate hook_node_access(). Edited the answer to link to a relevant topic - you would want to implement hook_node_access_records() and hook_node_grants() instead. I might re-answer this later.
    – Les Lim
    Commented May 14, 2020 at 19:29
  • Oy vey. Who makes these design decisions? Since when did a simple query to compare a value to a value become writing a novel?
    – Ex0r
    Commented May 15, 2020 at 12:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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