Access Rules

Last updated on
20 April 2024

Overview:

Access rules combine three elements

  1. The field on the entity and/or user. 
  2. An Access rule plugin - This performs the logic of comparing values and controlling access. 
  3. An access rule data definition - This exposes your access rule in the "Add access rule" modal. 

Access rules were highly influenced by views plugins!

Access Rule Data Definition

In many cases you can create your own access rule by simply defining a data definition. In fact, it is recommended that you try this method first before writing your own plugin.

Define your access rule data definition with hook_access_policy_data

function my_module_access_policy_data() {
  $data = [];
  $data['node']['is_own'] = [
    'label' => t('Authored by current user.'),
    'description' => t('Grant access if the node is authored by the current user'),
    'plugin_id' => 'is_own',
    'entity_type' => 'node',
    'field' => 'uid',
  ];
}

For more more details about hook_access_policy_data see access_policy.api.php 

Access Rule Plugin

The definition depends on the is_own access rule plugin. Create a new plugin in src/Plugin/access_policy/AccessRule

**
 * @AccessRule(
 *   id = "is_own",
 *   handlers = {
 *     "query_alter" = "\Drupal\my_module\AccessRuleQueryHandler\IsOwn"
 *   }
 * )
 */
class IsOwn extends AccessRuleBase {

  public function isApplicable(EntityInterface $entity) {
    if ($entity instanceof EntityOwnerInterface) {
      return TRUE;
    }

    return FALSE;
  }


  public function accessRuleForm(array $form, FormStateInterface $form_state) {
    return $form;
  }


  public function validate(EntityInterface $entity, AccountInterface $account) {
    if ($entity->getOwnerId() == $account->id()) {
      return TRUE;
    }

    return FALSE;
  }

  public function getCacheContexts() {
    return ['user'];
  }

}

query_alter handlers: 

Access is handled in two places: 

  • On each entity operation such as view, edit, delete etc. 
  • On listing pages like the content page. 

For each context Drupal handles access differently. With hook_entity_access and hook_query_TAG_alter respectively. The query_alter handler is a class that is called during hook_query_TAG_alter and allows your plugin to alter the query. If this handler is omitted then your plugin will not restrict query access. 

Create a new access rule query handler in src/AccessRuleQueryHandler

class IsOwn extends AccessRuleQueryHandlerBase {

  public function query() {
    $this->ensureMyTable();
    $entity_type = $this->getEntityType();
    $user_field = $this->getTableAlias() . '.' . $entity_type->getKey('owner');

    $this->query->condition($user_field, $this->currentUser->id());
  }

  public function ensureMyTable() {
    $base_field_placeholder = $this->query->getBaseTable() . '.' . $this->query->getBaseField();

    $entity_type = $this->getEntityType();
    $id = $entity_type->getKey('id');
    $this->query->join($this->tableAlias, $this->tableAlias, $this->tableAlias . "." . $id . " = " . $base_field_placeholder);
  }

  private function getEntityType() {
    $entity_type_id = $this->definition->getEntityType();
    return $this->entityTypeManager->getDefinition($entity_type_id);
  }

}

Help improve this page

Page status: No known problems

You can: