summaryrefslogtreecommitdiffstatshomepage
path: root/core/modules/jsonapi
diff options
context:
space:
mode:
Diffstat (limited to 'core/modules/jsonapi')
-rw-r--r--core/modules/jsonapi/jsonapi.api.php17
-rw-r--r--core/modules/jsonapi/jsonapi.module16
-rw-r--r--core/modules/jsonapi/src/Access/TemporaryQueryGuard.php31
-rw-r--r--core/modules/jsonapi/src/Hook/JsonapiHooks.php59
-rw-r--r--core/modules/jsonapi/src/JsonApiFilter.php77
5 files changed, 148 insertions, 52 deletions
diff --git a/core/modules/jsonapi/jsonapi.api.php b/core/modules/jsonapi/jsonapi.api.php
index 5b2f2002d25c..ca8c5ae993fb 100644
--- a/core/modules/jsonapi/jsonapi.api.php
+++ b/core/modules/jsonapi/jsonapi.api.php
@@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Access\AccessResult;
+use Drupal\jsonapi\JsonApiFilter;
/**
* @defgroup jsonapi_architecture JSON:API Architecture
@@ -263,10 +264,10 @@ use Drupal\Core\Access\AccessResult;
* 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
+ * - JsonApiFilter::AMONG_ALL: all entities of the given type.
+ * - JsonApiFilter::AMONG_PUBLISHED: all published entities of the given type.
+ * - JsonApiFilter::AMONG_ENABLED: all enabled entities of the given type.
+ * - JsonApiFilter::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.
@@ -278,7 +279,7 @@ function hook_jsonapi_entity_filter_access(EntityTypeInterface $entity_type, Acc
// 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),
+ JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, $admin_permission),
]);
}
}
@@ -305,9 +306,9 @@ function hook_jsonapi_entity_filter_access(EntityTypeInterface $entity_type, Acc
*/
function hook_jsonapi_ENTITY_TYPE_filter_access(EntityTypeInterface $entity_type, AccountInterface $account): array {
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'),
+ JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'administer llamas'),
+ JsonApiFilter::AMONG_PUBLISHED => AccessResult::allowedIfHasPermission($account, 'view all published llamas'),
+ JsonApiFilter::AMONG_OWN => AccessResult::allowedIfHasPermissions($account, ['view own published llamas', 'view own unpublished llamas'], 'AND'),
]);
}
diff --git a/core/modules/jsonapi/jsonapi.module b/core/modules/jsonapi/jsonapi.module
index 69414af650b9..c512575305a4 100644
--- a/core/modules/jsonapi/jsonapi.module
+++ b/core/modules/jsonapi/jsonapi.module
@@ -11,6 +11,10 @@
* regardless of whether they are published or enabled, and regardless of
* their owner.
*
+ * @deprecated in drupal:11.3.0 and is removed from drupal:13.0.0. Use
+ * \Drupal\jsonapi\JsonApiFilter::AMONG_ALL instead.
+ *
+ * @see https://www.drupal.org/node/3495601
* @see hook_jsonapi_entity_filter_access()
* @see hook_jsonapi_ENTITY_TYPE_filter_access()
*/
@@ -25,6 +29,10 @@ const JSONAPI_FILTER_AMONG_ALL = 'filter_among_all';
* This is used when an entity type has a "published" entity key and there's a
* query condition for the value of that equaling 1.
*
+ * @deprecated in drupal:11.3.0 and is removed from drupal:13.0.0. Use
+ * \Drupal\jsonapi\JsonApiFilter::AMONG_PUBLISHED instead.
+ *
+ * @see https://www.drupal.org/node/3495601
* @see hook_jsonapi_entity_filter_access()
* @see hook_jsonapi_ENTITY_TYPE_filter_access()
*/
@@ -42,6 +50,10 @@ const JSONAPI_FILTER_AMONG_PUBLISHED = 'filter_among_published';
* For the User entity type, which does not have a "status" entity key, the
* "status" field is used.
*
+ * @deprecated in drupal:11.3.0 and is removed from drupal:13.0.0. Use
+ * \Drupal\jsonapi\JsonApiFilter::AMONG_ENABLED instead.
+ *
+ * @see https://www.drupal.org/node/3495601
* @see hook_jsonapi_entity_filter_access()
* @see hook_jsonapi_ENTITY_TYPE_filter_access()
*/
@@ -64,6 +76,10 @@ const JSONAPI_FILTER_AMONG_ENABLED = 'filter_among_enabled';
* - The entity type has an "owner" entity key.
* - There's a filter/query condition for the value equal to the user's ID.
*
+ * @deprecated in drupal:11.3.0 and is removed from drupal:13.0.0. Use
+ * \Drupal\jsonapi\JsonApiFilter::AMONG_OWN instead.
+ *
+ * @see https://www.drupal.org/node/3495601
* @see hook_jsonapi_entity_filter_access()
* @see hook_jsonapi_ENTITY_TYPE_filter_access()
*/
diff --git a/core/modules/jsonapi/src/Access/TemporaryQueryGuard.php b/core/modules/jsonapi/src/Access/TemporaryQueryGuard.php
index d59dca4ec03a..2888fbbec77c 100644
--- a/core/modules/jsonapi/src/Access/TemporaryQueryGuard.php
+++ b/core/modules/jsonapi/src/Access/TemporaryQueryGuard.php
@@ -12,6 +12,7 @@ use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TypedData\DataReferenceDefinitionInterface;
+use Drupal\jsonapi\JsonApiFilter;
use Drupal\jsonapi\Query\EntityCondition;
use Drupal\jsonapi\Query\EntityConditionGroup;
use Drupal\jsonapi\Query\Filter;
@@ -323,12 +324,12 @@ class TemporaryQueryGuard {
}
/**
- * Gets an access condition for the allowed JSONAPI_FILTER_AMONG_* subsets.
+ * Gets an access condition for the allowed JsonApiFilter::AMONG_* subsets.
*
- * If access is allowed for the JSONAPI_FILTER_AMONG_ALL subset, then no
+ * If access is allowed for the JsonApiFilter::AMONG_ALL subset, then no
* conditions are returned. Otherwise, if access is allowed for
- * JSONAPI_FILTER_AMONG_PUBLISHED, JSONAPI_FILTER_AMONG_ENABLED, or
- * JSONAPI_FILTER_AMONG_OWN, then a condition group is returned for the union
+ * JsonApiFilter::AMONG_PUBLISHED, JsonApiFilter::AMONG_ENABLED, or
+ * JsonApiFilter::AMONG_OWN, then a condition group is returned for the union
* of allowed subsets. If no subsets are allowed, then static::alwaysFalse()
* is returned.
*
@@ -344,12 +345,12 @@ class TemporaryQueryGuard {
* secure an entity query.
*/
protected static function getAccessConditionForKnownSubsets(EntityTypeInterface $entity_type, AccountInterface $account, CacheableMetadata $cacheability) {
- // Get the combined access results for each JSONAPI_FILTER_AMONG_* subset.
+ // Get the combined access results for each JsonApiFilter::AMONG_* subset.
$access_results = static::getAccessResultsFromEntityFilterHook($entity_type, $account);
// No conditions are needed if access is allowed for all entities.
- $cacheability->addCacheableDependency($access_results[JSONAPI_FILTER_AMONG_ALL]);
- if ($access_results[JSONAPI_FILTER_AMONG_ALL]->isAllowed()) {
+ $cacheability->addCacheableDependency($access_results[JsonApiFilter::AMONG_ALL]);
+ if ($access_results[JsonApiFilter::AMONG_ALL]->isAllowed()) {
return NULL;
}
@@ -363,7 +364,7 @@ class TemporaryQueryGuard {
// The "published" subset.
$published_field_name = $entity_type->getKey('published');
if ($published_field_name) {
- $access_result = $access_results[JSONAPI_FILTER_AMONG_PUBLISHED];
+ $access_result = $access_results[JsonApiFilter::AMONG_PUBLISHED];
$cacheability->addCacheableDependency($access_result);
if ($access_result->isAllowed()) {
$conditions[] = new EntityCondition($published_field_name, 1);
@@ -375,7 +376,7 @@ class TemporaryQueryGuard {
// @todo Remove ternary when the 'status' key is added to the User entity type.
$status_field_name = $entity_type->id() === 'user' ? 'status' : $entity_type->getKey('status');
if ($status_field_name) {
- $access_result = $access_results[JSONAPI_FILTER_AMONG_ENABLED];
+ $access_result = $access_results[JsonApiFilter::AMONG_ENABLED];
$cacheability->addCacheableDependency($access_result);
if ($access_result->isAllowed()) {
$conditions[] = new EntityCondition($status_field_name, 1);
@@ -387,7 +388,7 @@ class TemporaryQueryGuard {
// @todo Remove ternary when the 'uid' key is added to the User entity type.
$owner_field_name = $entity_type->id() === 'user' ? 'uid' : $entity_type->getKey('owner');
if ($owner_field_name) {
- $access_result = $access_results[JSONAPI_FILTER_AMONG_OWN];
+ $access_result = $access_results[JsonApiFilter::AMONG_OWN];
$cacheability->addCacheableDependency($access_result);
if ($access_result->isAllowed()) {
$cacheability->addCacheContexts(['user']);
@@ -415,7 +416,7 @@ class TemporaryQueryGuard {
}
/**
- * Gets the combined access result for each JSONAPI_FILTER_AMONG_* subset.
+ * Gets the combined access result for each JsonApiFilter::AMONG_* subset.
*
* This invokes hook_jsonapi_entity_filter_access() and
* hook_jsonapi_ENTITY_TYPE_filter_access() and combines the results from all
@@ -433,10 +434,10 @@ class TemporaryQueryGuard {
protected static function getAccessResultsFromEntityFilterHook(EntityTypeInterface $entity_type, AccountInterface $account) {
/** @var \Drupal\Core\Access\AccessResultInterface[] $combined_access_results */
$combined_access_results = [
- JSONAPI_FILTER_AMONG_ALL => AccessResult::neutral(),
- JSONAPI_FILTER_AMONG_PUBLISHED => AccessResult::neutral(),
- JSONAPI_FILTER_AMONG_ENABLED => AccessResult::neutral(),
- JSONAPI_FILTER_AMONG_OWN => AccessResult::neutral(),
+ JsonApiFilter::AMONG_ALL => AccessResult::neutral(),
+ JsonApiFilter::AMONG_PUBLISHED => AccessResult::neutral(),
+ JsonApiFilter::AMONG_ENABLED => AccessResult::neutral(),
+ JsonApiFilter::AMONG_OWN => AccessResult::neutral(),
];
// Invoke hook_jsonapi_entity_filter_access() and
diff --git a/core/modules/jsonapi/src/Hook/JsonapiHooks.php b/core/modules/jsonapi/src/Hook/JsonapiHooks.php
index 7db5b77b0e80..d5f6d2540fcd 100644
--- a/core/modules/jsonapi/src/Hook/JsonapiHooks.php
+++ b/core/modules/jsonapi/src/Hook/JsonapiHooks.php
@@ -7,6 +7,7 @@ use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\jsonapi\JsonApiFilter;
use Drupal\jsonapi\Routing\Routes;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Hook\Attribute\Hook;
@@ -107,7 +108,7 @@ class JsonapiHooks {
// AccessResult::forbidden() from its implementation of this hook.
if ($admin_permission = $entity_type->getAdminPermission()) {
return [
- JSONAPI_FILTER_AMONG_ALL => AccessResult::allowedIfHasPermission($account, $admin_permission),
+ JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, $admin_permission),
];
}
return [];
@@ -122,8 +123,8 @@ class JsonapiHooks {
// \Drupal\jsonapi\Access\TemporaryQueryGuard adds the condition for
// (isReusable()), so this does not have to.
return [
- JSONAPI_FILTER_AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'access block library'),
- JSONAPI_FILTER_AMONG_PUBLISHED => AccessResult::allowed(),
+ JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'access block library'),
+ JsonApiFilter::AMONG_PUBLISHED => AccessResult::allowed(),
];
}
@@ -136,8 +137,8 @@ class JsonapiHooks {
// \Drupal\jsonapi\Access\TemporaryQueryGuard adds the condition for
// (access to the commented entity), so this does not have to.
return [
- JSONAPI_FILTER_AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'administer comments'),
- JSONAPI_FILTER_AMONG_PUBLISHED => AccessResult::allowedIfHasPermission($account, 'access comments'),
+ JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'administer comments'),
+ JsonApiFilter::AMONG_PUBLISHED => AccessResult::allowedIfHasPermission($account, 'access comments'),
];
}
@@ -148,7 +149,7 @@ class JsonapiHooks {
public function jsonapiEntityTestFilterAccess(EntityTypeInterface $entity_type, AccountInterface $account): array {
// @see \Drupal\entity_test\EntityTestAccessControlHandler::checkAccess()
return [
- JSONAPI_FILTER_AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'view test entity'),
+ JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'view test entity'),
];
}
@@ -161,7 +162,7 @@ class JsonapiHooks {
// \Drupal\jsonapi\Access\TemporaryQueryGuard adds the condition for
// (public OR owner), so this does not have to.
return [
- JSONAPI_FILTER_AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'access content'),
+ JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'access content'),
];
}
@@ -172,7 +173,7 @@ class JsonapiHooks {
public function jsonapiMediaFilterAccess(EntityTypeInterface $entity_type, AccountInterface $account): array {
// @see \Drupal\media\MediaAccessControlHandler::checkAccess()
return [
- JSONAPI_FILTER_AMONG_PUBLISHED => AccessResult::allowedIfHasPermission($account, 'view media'),
+ JsonApiFilter::AMONG_PUBLISHED => AccessResult::allowedIfHasPermission($account, 'view media'),
];
}
@@ -184,30 +185,30 @@ class JsonapiHooks {
// @see \Drupal\node\NodeAccessControlHandler::access()
if ($account->hasPermission('bypass node access')) {
return [
- JSONAPI_FILTER_AMONG_ALL => AccessResult::allowed()->cachePerPermissions(),
+ JsonApiFilter::AMONG_ALL => AccessResult::allowed()->cachePerPermissions(),
];
}
if (!$account->hasPermission('access content')) {
$forbidden = AccessResult::forbidden("The 'access content' permission is required.")->cachePerPermissions();
return [
- JSONAPI_FILTER_AMONG_ALL => $forbidden,
- JSONAPI_FILTER_AMONG_OWN => $forbidden,
- JSONAPI_FILTER_AMONG_PUBLISHED => $forbidden,
+ JsonApiFilter::AMONG_ALL => $forbidden,
+ JsonApiFilter::AMONG_OWN => $forbidden,
+ JsonApiFilter::AMONG_PUBLISHED => $forbidden,
// For legacy reasons, the Node entity type has a "status" key, so
// forbid this subset as well, even though it has no semantic meaning.
- JSONAPI_FILTER_AMONG_ENABLED => $forbidden,
+ JsonApiFilter::AMONG_ENABLED => $forbidden,
];
}
return [
- // @see \Drupal\node\NodeAccessControlHandler::checkAccess()
- JSONAPI_FILTER_AMONG_OWN => AccessResult::allowedIfHasPermission($account, 'view own unpublished content'),
- // @see \Drupal\node\NodeGrantDatabaseStorage::access()
- // Note that:
- // - This is just for the default grant. Other node access conditions
- // are added via the 'node_access' query tag.
- // - Permissions were checked earlier in this function, so we must
- // vary the cache by them.
- JSONAPI_FILTER_AMONG_PUBLISHED => AccessResult::allowed()->cachePerPermissions(),
+ // @see \Drupal\node\NodeAccessControlHandler::checkAccess()
+ JsonApiFilter::AMONG_OWN => AccessResult::allowedIfHasPermission($account, 'view own unpublished content'),
+ // @see \Drupal\node\NodeGrantDatabaseStorage::access()
+ // Note that:
+ // - This is just for the default grant. Other node access conditions
+ // are added via the 'node_access' query tag.
+ // - Permissions were checked earlier in this function, so we must
+ // vary the cache by them.
+ JsonApiFilter::AMONG_PUBLISHED => AccessResult::allowed()->cachePerPermissions(),
];
}
@@ -221,7 +222,7 @@ class JsonapiHooks {
// "shortcut_set = $shortcut_set_storage->getDisplayedToUser($current_user)"
// so this does not have to.
return [
- JSONAPI_FILTER_AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'administer shortcuts')->orIf(AccessResult::allowedIfHasPermissions($account, [
+ JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'administer shortcuts')->orIf(AccessResult::allowedIfHasPermissions($account, [
'access shortcuts',
'customize shortcut links',
])),
@@ -235,8 +236,8 @@ class JsonapiHooks {
public function jsonapiTaxonomyTermFilterAccess(EntityTypeInterface $entity_type, AccountInterface $account): array {
// @see \Drupal\taxonomy\TermAccessControlHandler::checkAccess()
return [
- JSONAPI_FILTER_AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'administer taxonomy'),
- JSONAPI_FILTER_AMONG_PUBLISHED => AccessResult::allowedIfHasPermission($account, 'access content'),
+ JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'administer taxonomy'),
+ JsonApiFilter::AMONG_PUBLISHED => AccessResult::allowedIfHasPermission($account, 'access content'),
];
}
@@ -249,8 +250,8 @@ class JsonapiHooks {
// \Drupal\jsonapi\Access\TemporaryQueryGuard adds the condition for
// (!isAnonymous()), so this does not have to.
return [
- JSONAPI_FILTER_AMONG_OWN => AccessResult::allowed(),
- JSONAPI_FILTER_AMONG_ENABLED => AccessResult::allowedIfHasPermission($account, 'access user profiles'),
+ JsonApiFilter::AMONG_OWN => AccessResult::allowed(),
+ JsonApiFilter::AMONG_ENABLED => AccessResult::allowedIfHasPermission($account, 'access user profiles'),
];
}
@@ -261,8 +262,8 @@ class JsonapiHooks {
public function jsonapiWorkspaceFilterAccess(EntityTypeInterface $entity_type, AccountInterface $account): array {
// @see \Drupal\workspaces\WorkspaceAccessControlHandler::checkAccess()
return [
- JSONAPI_FILTER_AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'view any workspace'),
- JSONAPI_FILTER_AMONG_OWN => AccessResult::allowedIfHasPermission($account, 'view own workspace'),
+ JsonApiFilter::AMONG_ALL => AccessResult::allowedIfHasPermission($account, 'view any workspace'),
+ JsonApiFilter::AMONG_OWN => AccessResult::allowedIfHasPermission($account, 'view own workspace'),
];
}
diff --git a/core/modules/jsonapi/src/JsonApiFilter.php b/core/modules/jsonapi/src/JsonApiFilter.php
new file mode 100644
index 000000000000..c9ac90be7af7
--- /dev/null
+++ b/core/modules/jsonapi/src/JsonApiFilter.php
@@ -0,0 +1,77 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\jsonapi;
+
+/**
+ * JsonApi filter options.
+ */
+final class JsonApiFilter {
+
+ /**
+ * Array key for denoting type-based filtering access.
+ *
+ * Array key for denoting access to filter among all entities of a given type,
+ * regardless of whether they are published or enabled, and regardless of
+ * their owner.
+ *
+ * @see hook_jsonapi_entity_filter_access()
+ * @see hook_jsonapi_ENTITY_TYPE_filter_access()
+ */
+ const AMONG_ALL = 'filter_among_all';
+
+ /**
+ * Array key for denoting type-based published-only filtering access.
+ *
+ * Array key for denoting access to filter among all published entities of a
+ * given type, regardless of their owner.
+ *
+ * This is used when an entity type has a "published" entity key and there's a
+ * query condition for the value of that equaling 1.
+ *
+ * @see hook_jsonapi_entity_filter_access()
+ * @see hook_jsonapi_ENTITY_TYPE_filter_access()
+ */
+ const AMONG_PUBLISHED = 'filter_among_published';
+
+ /**
+ * Array key for denoting type-based enabled-only filtering access.
+ *
+ * Array key for denoting access to filter among all enabled entities of a
+ * given type, regardless of their owner.
+ *
+ * This is used when an entity type has a "status" entity key and there's a
+ * query condition for the value of that equaling 1.
+ *
+ * For the User entity type, which does not have a "status" entity key, the
+ * "status" field is used.
+ *
+ * @see hook_jsonapi_entity_filter_access()
+ * @see hook_jsonapi_ENTITY_TYPE_filter_access()
+ */
+ const AMONG_ENABLED = 'filter_among_enabled';
+
+ /**
+ * Array key for denoting type-based owned-only filtering access.
+ *
+ * Array key for denoting access to filter among all entities of a given type,
+ * regardless of whether they are published or enabled, so long as they are
+ * owned by the user for whom access is being checked.
+ *
+ * When filtering among User entities, this is used when access is being
+ * checked for an authenticated user and there's a query condition
+ * limiting the result set to just that user's entity object.
+ *
+ * When filtering among entities of another type, this is used when all of the
+ * following conditions are met:
+ * - Access is being checked for an authenticated user.
+ * - The entity type has an "owner" entity key.
+ * - There's a filter/query condition for the value equal to the user's ID.
+ *
+ * @see hook_jsonapi_entity_filter_access()
+ * @see hook_jsonapi_ENTITY_TYPE_filter_access()
+ */
+ const AMONG_OWN = 'filter_among_own';
+
+}