Change record status: 
Project: 
Introduced in branch: 
8.x-1.x
Introduced in version: 
8.x-1.0-rc1
Description: 

The module now ships with an entity query access API, which alters entity queries and views to only list the entities that the user has access to.
That means that an entity query or a view might be restricted to only published entities, or only entities of specific bundles, or belonging to a specific user ("view own").

The query_access handler generates conditions which are then applied to the queries. The default handlers are permission-based, checking the permissions provided by EntityPermissionProvider and UncacheableEntityPermissionProvider.

Annotation examples:

 *   handlers = {
 *     "access" = "\Drupal\entity\EntityAccessControlHandler",
 *     "query_access" = "\Drupal\entity\QueryAccess\QueryAccessHandler",
 *     "permission_provider" = "\Drupal\entity\EntityPermissionProvider",
 *   handlers = {
 *     "access" = "\Drupal\entity\UncacheableEntityAccessControlHandler",
 *     "query_access" = "\Drupal\entity\QueryAccess\UncacheableQueryAccessHandler",
 *     "permission_provider" = "\Drupal\entity\UncacheableEntityPermissionProvider",

Modules can use the QueryAccessEvent ("entity.query_access.$entity_type_id") to alter the generated access conditions before they are applied to a query, in order to add additional filtering based on a group, store, or some other factor. See the QueryAccessSubscriber in tests/entity_module_test for an example.

Impacts: 
Module developers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done

Comments

ransomweaver’s picture

I often have trouble understanding the usage from the test code. Fortunately there is a good practical example in the commerce_cart submodule of Drupal Commerce:

1) there is a service in commerce_cart.services.yml:

commerce_cart.query_access_subscriber:
    class: Drupal\commerce_cart\EventSubscriber\QueryAccessSubscriber
    arguments: ['@commerce_cart.cart_provider', '@commerce_cart.cart_session']
    tags:
      - { name: event_subscriber, priority: 100 }

2) the subscriber in the class noted above a) checks if user already has permission from the Permissions provider and returns if they do and b) assembles the carts related to the user and grants access to those for the user in the query:

/**
   * Modifies the access conditions for cart orders.
   *
   * @param \Drupal\entity\QueryAccess\QueryAccessEvent $event
   *   The event.
   */
  public function onQueryAccess(QueryAccessEvent $event) {
    if ($event->getOperation() != 'view') {
      return;
    }

    $conditions = $event->getConditions();
    // The user already has full access due to a "administer commerce_order"
    // or "view commerce_order" permission.
    if (!$conditions->count() && !$conditions->isAlwaysFalse()) {
      return;
    }

    $account = $event->getAccount();
    // Any user can view their own active carts, regardless of any permissions.
    $cart_ids = $this->cartProvider->getCartIds($account);
    if ($account->isAnonymous()) {
      $completed_cart_ids = $this->cartSession->getCartIds(CartSessionInterface::COMPLETED);
      $cart_ids = array_merge($cart_ids, $completed_cart_ids);
    }

    if (!empty($cart_ids)) {
      $conditions->addCondition('order_id', $cart_ids);
      $conditions->alwaysFalse(FALSE);
    }
  }
mxh’s picture

It should be noted that subqueries are currently not supported by the Query Access API. Also see #3259313: Let Query Access API support subqueries

Anybody’s picture

Looks like this is a helpful blog article on this topic:
https://gorannikolovski.com/blog/query-level-filtering-custom-entities-d...

http://www.DROWL.de || Professionelle Drupal Lösungen aus Ostwestfalen-Lippe (OWL)
http://www.webks.de || webks: websolutions kept simple - Webbasierte Lösungen die einfach überzeugen!
http://www.drupal-theming.com || Individuelle Responsive Themes