access('view')` is how entity access is checked. * This call invokes the corresponding hooks. However, these access checks * require an `$entity` object. This means that they cannot be called prior to * executing a database query. * * In order to safely enable filtering across a relationship, modules * responsible for entity access must do two things: * - Implement this hook (or hook_jsonapi_ENTITY_TYPE_filter_access()) and * return an array of AccessResults keyed by the named entity subsets below. * - If the AccessResult::allowed() returned by the above hook does not provide * enough granularity (for example, if access depends on a bundle field value * of the entity being queried), then hook_query_TAG_alter() must be * implemented using the 'entity_access' or 'ENTITY_TYPE_access' query tag. * See node_query_node_access_alter() for an example. * * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type * The entity type of the entity to be filtered upon. * @param \Drupal\Core\Session\AccountInterface $account * The account for which to check access. * * @return \Drupal\Core\Access\AccessResultInterface[] * An array keyed by a constant which identifies a subset of entities. For * each subset, the value is one of the following access results: * - AccessResult::allowed() if all entities within the subset (potentially * narrowed by hook_query_TAG_alter() implementations) are viewable. * - AccessResult::forbidden() if any entity within the subset is not * viewable. * - AccessResult::neutral() if the implementation has no opinion. * The supported subsets for which an access result may be returned are: * - JSONAPI_FILTER_AMONG_ALL: all entities of the given type. * - JSONAPI_FILTER_AMONG_PUBLISHED: all published entities of the given type. * - JSONAPI_FILTER_AMONG_ENABLED: all enabled entities of the given type. * - JSONAPI_FILTER_AMONG_OWN: all entities of the given type owned by the * user for whom access is being checked. * See the documentation of the above constants for more information about * each subset. * * @see hook_jsonapi_ENTITY_TYPE_filter_access() */ function hook_jsonapi_entity_filter_access(\Drupal\Core\Entity\EntityTypeInterface $entity_type, \Drupal\Core\Session\AccountInterface $account) { // For every entity type that has an admin permission, allow access to filter // by all entities of that type to users with that permission. if ($admin_permission = $entity_type->getAdminPermission()) { return ([ JSONAPI_FILTER_AMONG_ALL => AccessResult::allowedIfHasPermission($account, $admin_permission), ]); } } /** * Controls access to filtering by entity data via JSON:API. * * This is the entity-type-specific variant of * hook_jsonapi_entity_filter_access(). For implementations with logic that is * specific to a single entity type, it is recommended to implement this hook * rather than the generic hook_jsonapi_entity_filter_access() hook, which is * called for every entity type. * * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type * The entity type of the entities to be filtered upon. * @param \Drupal\Core\Session\AccountInterface $account * The account for which to check access. * * @return \Drupal\Core\Access\AccessResultInterface[] * The array of access results, keyed by subset. See * hook_jsonapi_entity_filter_access() for details. * * @see hook_jsonapi_entity_filter_access() */ function hook_jsonapi_ENTITY_TYPE_filter_access(\Drupal\Core\Entity\EntityTypeInterface $entity_type, \Drupal\Core\Session\AccountInterface $account) { return ([ JSONAPI_FILTER_AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'administer llamas'), JSONAPI_FILTER_AMONG_PUBLISHED => AccessResult::allowedIfHasPermission($account, 'view all published llamas'), JSONAPI_FILTER_AMONG_OWN => AccessResult::allowedIfHasPermissions($account, ['view own published llamas', 'view own unpublished llamas'], 'AND'), ]); } /** * Restricts filtering access to the given field. * * Some fields may contain sensitive information. In these cases, modules are * supposed to implement hook_entity_field_access(). However, this hook receives * an optional `$items` argument and often must return AccessResult::neutral() * when `$items === NULL`. This is because access may or may not be allowed * based on the field items or based on the entity on which the field is * attached (if the user is the entity owner, for example). * * Since JSON:API must check field access prior to having a field item list * instance available (access must be checked before a database query is made), * it is not sufficiently secure to check field 'view' access alone. * * This hook exists so that modules which cannot return * AccessResult::forbidden() from hook_entity_field_access() can still secure * JSON:API requests where necessary. * * If a corresponding implementation of hook_entity_field_access() *can* be * forbidden for one or more values of the `$items` argument, this hook *MUST* * return AccessResult::forbidden(). * * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition * The field definition of the field to be filtered upon. * @param \Drupal\Core\Session\AccountInterface $account * The account for which to check access. * * @return \Drupal\Core\Access\AccessResultInterface * The access result. */ function hook_jsonapi_entity_field_filter_access(\Drupal\Core\Field\FieldDefinitionInterface $field_definition, \Drupal\Core\Session\AccountInterface $account) { if ($field_definition->getTargetEntityTypeId() === 'node' && $field_definition->getName() === 'field_sensitive_data') { $has_sufficient_access = FALSE; foreach (['administer nodes', 'view all sensitive field data'] as $permission) { $has_sufficient_access = $has_sufficient_access ?: $account->hasPermission($permission); } return AccessResult::forbiddenIf(!$has_sufficient_access)->cachePerPermissions(); } return AccessResult::neutral(); } /** * @} End of "addtogroup hooks". */