Drupal - How can I restrict user access to view nodes based on field value?

You could use a programmatically solution using hook_node_access(), in this example the field_YOURFIELD is a checkbox.

/**
 * Implements hook_node_access().
 */
function MYMODULE_node_access(\Drupal\node\NodeInterface $node, $op, \Drupal\Core\Session\AccountInterface $account) {
  $access = new \Drupal\Core\Access\AccessResultNeutral();
  if ($node->hasField('field_YOURFIELD')) {
    $field = $node->get('field_YOURFIELD')->getString();
    if (empty($field) && $account->id() != $node->getOwnerId()) {
      $access = new \Drupal\Core\Access\AccessResultForbidden();
    }
  }
  $access->addCacheableDependency($field);
  $access->addCacheableDependency($node);
  return $access;
}

There are a few options.

If it's really just that checkbox and won't get more complicated over time and writing code is an option, then you can write a custom views filter plugin that only adds a condition if the user is not a member.

Such a plugin would do something like this in the query method and extend from the one that is used by default, and then you use hook_views_data_alter() to use your plugin on your field instead of that one, or add your own views data definition.

/**
 * {@inheritdoc}
 */
public function query() {
  // Only add the condition if the current user is not authenticated.
  if (\Drupal::currentUser()->isAnonymous()) {
    parent::query();
  }
}

The other option is to rely on a node access module like https://www.drupal.org/project/content_access. That has a development release for Drupal 8, I'm not sure how usable it is already. There might also be alternative modules that do something, or you can implement one yourself. Drupal core has a fairly simple node_access_test test module that makes nodes private based on a "private" field, you could base yours on that.


After further research I opted for the following approach.

  • Install Taxonomy Access Control Lite
  • Create a new vocabulary in taxonomy - e.g. 'Access control'
  • Create a new term in this vocabulary - e.g. 'Member only'
  • Configure Taxonomy Access Control Lite to make content tagged with this term viewable to the roles you want (e.g. authenticated users)
  • Add a taxonomy field with this vocabulary to each content type that you want to restrict access to

After following these steps I have a simple select field called 'Access control' which can be set to ' - None - ' or 'Member only'. The content will be displayed publicly or only to members depending on the option chosen.

Notes

  1. I looked at another module that works in a similar way: Permissions by Term. This looks like a good alternative.
  2. I opted to display the 'Access control' field as a select list as I only needed one selection. It would be easy enough to use tick boxes instead if you allowed multiple selections for this field.

Tags:

Users

8