Commit 1208ddd9 authored by catch's avatar catch

Issue #2428703 by Wim Leers: Add a 'user.permissions' cache context (was:...

Issue #2428703 by Wim Leers: Add a 'user.permissions' cache context (was: "Should cache contexts be able to associate a cache tag?")
parent c7fd064c
......@@ -74,6 +74,11 @@ services:
arguments: ['@current_user']
tags:
- { name: cache.context}
cache_context.user.permissions:
class: Drupal\Core\Cache\AccountPermissionsCacheContext
arguments: ['@current_user', '@user_permissions_hash_generator']
tags:
- { name: cache.context}
cache_context.user.roles:
class: Drupal\Core\Cache\UserRolesCacheContext
arguments: ['@current_user']
......@@ -1190,6 +1195,9 @@ services:
account_switcher:
class: Drupal\Core\Session\AccountSwitcher
arguments: ['@current_user', '@session_handler.write_safe']
user_permissions_hash_generator:
class: Drupal\Core\Session\PermissionsHashGenerator
arguments: ['@private_key', '@cache.default']
current_user:
class: Drupal\Core\Session\AccountProxy
session_configuration:
......
......@@ -132,7 +132,7 @@ public static function forbiddenIf($condition) {
/**
* Creates an allowed access result if the permission is present, neutral otherwise.
*
* Convenience method, checks the permission and calls ::cachePerRole().
* Checks the permission and adds a 'user.permissions' cache context.
*
* @param \Drupal\Core\Session\AccountInterface $account
* The account for which to check a permission.
......@@ -144,13 +144,13 @@ public static function forbiddenIf($condition) {
* isNeutral() will be TRUE.
*/
public static function allowedIfHasPermission(AccountInterface $account, $permission) {
return static::allowedIf($account->hasPermission($permission))->cachePerRole();
return static::allowedIf($account->hasPermission($permission))->addCacheContexts(['user.permissions']);
}
/**
* Creates an allowed access result if the permissions are present, neutral otherwise.
*
* Convenience method, checks the permissions and calls ::cachePerRole().
* Checks the permission and adds a 'user.permissions' cache contexts.
*
* @param \Drupal\Core\Session\AccountInterface $account
* The account for which to check permissions.
......@@ -185,7 +185,7 @@ public static function allowedIfHasPermissions(AccountInterface $account, array
}
}
return static::allowedIf($access)->cachePerRole();
return static::allowedIf($access)->addCacheContexts(empty($permissions) ? [] : ['user.permissions']);
}
/**
......@@ -334,12 +334,12 @@ public function setCacheMaxAge($max_age) {
}
/**
* Convenience method, adds the "user.roles" cache context.
* Convenience method, adds the "user.permissions" cache context.
*
* @return $this
*/
public function cachePerRole() {
$this->addCacheContexts(array('user.roles'));
public function cachePerPermissions() {
$this->addCacheContexts(array('user.permissions'));
return $this;
}
......
<?php
/**
* @file
* Contains \Drupal\Core\Cache\UserRolesCacheContext.
*/
namespace Drupal\Core\Cache;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Session\PermissionsHashGeneratorInterface;
/**
* Defines the AccountPermissionsCacheContext service, for "per permission" caching.
*/
class AccountPermissionsCacheContext extends UserCacheContext implements CacheContextInterface{
/**
* The permissions hash generator.
*
* @var \Drupal\user\PermissionsHashInterface
*/
protected $permissionsHashGenerator;
/**
* Constructs a new UserCacheContext service.
*
* @param \Drupal\Core\Session\AccountInterface $user
* The current user.
* @param \Drupal\user\PermissionsHashInterface $permissions_hash_generator
* The permissions hash generator.
*/
public function __construct(AccountInterface $user, PermissionsHashGeneratorInterface $permissions_hash_generator) {
$this->user = $user;
$this->permissionsHashGenerator = $permissions_hash_generator;
}
/**
* {@inheritdoc}
*/
public static function getLabel() {
return t("Account's permissions");
}
/**
* {@inheritdoc}
*/
public function getContext() {
return 'ph.' . $this->permissionsHashGenerator->generate($this->user);
}
}
......@@ -2,21 +2,21 @@
/**
* @file
* Contains \Drupal\user\PermissionsHash.
* Contains \Drupal\Core\Session\PermissionsHashGenerator.
*/
namespace Drupal\user;
namespace Drupal\Core\Session;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\PrivateKey;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Site\Settings;
use Drupal\user\Entity\Role;
/**
* Generates and caches the permissions hash for a user.
*/
class PermissionsHash implements PermissionsHashInterface {
class PermissionsHashGenerator implements PermissionsHashGeneratorInterface {
/**
* The private key service.
......@@ -33,7 +33,7 @@ class PermissionsHash implements PermissionsHashInterface {
protected $cache;
/**
* Constructs a PermissionsHash object.
* Constructs a PermissionsHashGenerator object.
*
* @param \Drupal\Core\PrivateKey $private_key
* The private key service.
......@@ -69,7 +69,7 @@ public function generate(AccountInterface $account) {
/**
* Generates a hash that uniquely identifies the user's permissions.
*
* @param \Drupal\user\Entity\Role[] $roles
* @param string[] $roles
* The user's roles.
*
* @return string
......
......@@ -2,17 +2,15 @@
/**
* @file
* Contains Drupal\user\PermissionsHashInterface.
* Contains Drupal\Core\Session\PermissionsHashGeneratorInterface.
*/
namespace Drupal\user;
use Drupal\Core\Session\AccountInterface;
namespace Drupal\Core\Session;
/**
* Defines the user permissions hash interface.
* Defines the user permissions hash generator interface.
*/
interface PermissionsHashInterface {
interface PermissionsHashGeneratorInterface {
/**
* Generates a hash that uniquely identifies a user's permissions.
......
......@@ -28,21 +28,21 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A
/** @var \Drupal\Core\Entity\EntityInterface|\Drupal\user\EntityOwnerInterface $entity */
if ($account->hasPermission('administer comments')) {
$access = AccessResult::allowed()->cachePerRole();
$access = AccessResult::allowed()->cachePerPermissions();
return ($operation != 'view') ? $access : $access->andIf($entity->getCommentedEntity()->access($operation, $account, TRUE));
}
switch ($operation) {
case 'view':
return AccessResult::allowedIf($account->hasPermission('access comments') && $entity->isPublished())->cachePerRole()->cacheUntilEntityChanges($entity)
return AccessResult::allowedIf($account->hasPermission('access comments') && $entity->isPublished())->cachePerPermissions()->cacheUntilEntityChanges($entity)
->andIf($entity->getCommentedEntity()->access($operation, $account, TRUE));
case 'update':
return AccessResult::allowedIf($account->id() && $account->id() == $entity->getOwnerId() && $entity->isPublished() && $account->hasPermission('edit own comments'))->cachePerRole()->cachePerUser()->cacheUntilEntityChanges($entity);
return AccessResult::allowedIf($account->id() && $account->id() == $entity->getOwnerId() && $entity->isPublished() && $account->hasPermission('edit own comments'))->cachePerPermissions()->cachePerUser()->cacheUntilEntityChanges($entity);
default:
// No opinion.
return AccessResult::neutral()->cachePerRole();
return AccessResult::neutral()->cachePerPermissions();
}
}
......@@ -103,7 +103,7 @@ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_
$anonymous_contact = $commented_entity->get($entity->getFieldName())->getFieldDefinition()->getSetting('anonymous');
$admin_access = AccessResult::allowedIfHasPermission($account, 'administer comments');
$anonymous_access = AccessResult::allowedIf($entity->isNew() && $account->isAnonymous() && $anonymous_contact != COMMENT_ANONYMOUS_MAYNOT_CONTACT && $account->hasPermission('post comments'))
->cachePerRole()
->cachePerPermissions()
->cacheUntilEntityChanges($entity)
->cacheUntilEntityChanges($field_definition->getConfig($commented_entity->bundle()))
->cacheUntilEntityChanges($commented_entity);
......@@ -117,9 +117,9 @@ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_
// "access comments" permission and for the comment to be published. The
// mail field is hidden from non-admins.
$admin_access = AccessResult::allowedIf($account->hasPermission('administer comments') && $field_definition->getName() != 'hostname')
->cachePerRole();
->cachePerPermissions();
$anonymous_access = AccessResult::allowedIf($account->hasPermission('access comments') && (!$entity || $entity->isPublished()) && !in_array($field_definition->getName(), array('mail', 'hostname'), TRUE))
->cachePerRole();
->cachePerPermissions();
if ($entity) {
$anonymous_access->cacheUntilEntityChanges($entity);
}
......
......@@ -77,7 +77,7 @@ public function access(Route $route, AccountInterface $account) {
$mapper->hasTranslatable() &&
$source_language_access;
return AccessResult::allowedIf($access)->cachePerRole();
return AccessResult::allowedIf($access)->cachePerPermissions();
}
}
......@@ -71,7 +71,7 @@ public function access(UserInterface $user, AccountInterface $account) {
}
// User administrators should always have access to personal contact forms.
$access = AccessResult::neutral()->cachePerRole();
$access = AccessResult::neutral()->cachePerPermissions();
$permission_access = AccessResult::allowedIfHasPermission($account, 'administer users');
if ($permission_access->isAllowed()) {
return $access->orIf($permission_access);
......
......@@ -25,12 +25,12 @@ class ContactFormAccessControlHandler extends EntityAccessControlHandler {
public function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
if ($operation == 'view') {
// Do not allow access personal form via site-wide route.
return AccessResult::allowedIf($account->hasPermission('access site-wide contact form') && $entity->id() !== 'personal')->cachePerRole();
return AccessResult::allowedIf($account->hasPermission('access site-wide contact form') && $entity->id() !== 'personal')->cachePerPermissions();
}
elseif ($operation == 'delete' || $operation == 'update') {
// Do not allow the 'personal' form to be deleted, as it's used for
// the personal contact form.
return AccessResult::allowedIf($account->hasPermission('administer contact forms') && $entity->id() !== 'personal')->cachePerRole();
return AccessResult::allowedIf($account->hasPermission('administer contact forms') && $entity->id() !== 'personal')->cachePerPermissions();
}
return parent::checkAccess($entity, $operation, $langcode, $account);
......
......@@ -234,7 +234,7 @@ function content_translation_translate_access(EntityInterface $entity) {
$account = \Drupal::currentUser();
$condition = $entity instanceof ContentEntityInterface && !$entity->getUntranslated()->language()->isLocked() && \Drupal::languageManager()->isMultilingual() && $entity->isTranslatable() &&
($account->hasPermission('create content translations') || $account->hasPermission('update content translations') || $account->hasPermission('delete content translations'));
return AccessResult::allowedIf($condition)->cachePerRole()->cacheUntilEntityChanges($entity);
return AccessResult::allowedIf($condition)->cachePerPermissions()->cacheUntilEntityChanges($entity);
}
/**
......
......@@ -75,7 +75,7 @@ public function access(Route $route, RouteMatchInterface $route_match, AccountIn
if ($entity = $route_match->getParameter($entity_type_id)) {
if ($account->hasPermission('translate any entity')) {
return AccessResult::allowed()->cachePerRole();
return AccessResult::allowed()->cachePerPermissions();
}
$operation = $route->getRequirement('_access_content_translation_manage');
......@@ -95,7 +95,7 @@ public function access(Route $route, RouteMatchInterface $route_match, AccountIn
&& isset($languages[$source_language->getId()])
&& isset($languages[$target_language->getId()])
&& !isset($translations[$target_language->getId()]));
return AccessResult::allowedIf($is_new_translation)->cachePerRole()->cacheUntilEntityChanges($entity)
return AccessResult::allowedIf($is_new_translation)->cachePerPermissions()->cacheUntilEntityChanges($entity)
->andIf($handler->getTranslationAccess($entity, $operation));
case 'update':
......@@ -104,7 +104,7 @@ public function access(Route $route, RouteMatchInterface $route_match, AccountIn
$has_translation = isset($languages[$language->getId()])
&& $language->getId() != $entity->getUntranslated()->language()->getId()
&& isset($translations[$language->getId()]);
return AccessResult::allowedIf($has_translation)->cachePerRole()->cacheUntilEntityChanges($entity)
return AccessResult::allowedIf($has_translation)->cachePerPermissions()->cacheUntilEntityChanges($entity)
->andIf($handler->getTranslationAccess($entity, $operation));
}
}
......
......@@ -66,7 +66,7 @@ public function access(RouteMatchInterface $route_match, AccountInterface $accou
// Check "translate any entity" permission.
if ($account->hasPermission('translate any entity')) {
return AccessResult::allowed()->cachePerRole()->inheritCacheability($access);
return AccessResult::allowed()->cachePerPermissions()->inheritCacheability($access);
}
// Check per entity permission.
......
......@@ -208,7 +208,7 @@ public function getTranslationAccess(EntityInterface $entity, $op) {
if (!$current_user->hasPermission('translate any entity') && $permission_granularity = $entity_type->getPermissionGranularity()) {
$translate_permission = $current_user->hasPermission($permission_granularity == 'bundle' ? "translate {$entity->bundle()} {$entity->getEntityTypeId()}" : "translate {$entity->getEntityTypeId()}");
}
return AccessResult::allowedIf($translate_permission && $current_user->hasPermission("$op content translations"))->cachePerRole();
return AccessResult::allowedIf($translate_permission && $current_user->hasPermission("$op content translations"))->cachePerPermissions();
}
/**
......
......@@ -48,7 +48,7 @@ function field_test_entity_field_access($operation, FieldDefinitionInterface $fi
// Only grant view access to test_view_field fields when the user has
// 'view test_view_field content' permission.
if ($field_definition->getName() == 'test_view_field' && $operation == 'view') {
return AccessResult::forbiddenIf(!$account->hasPermission('view test_view_field content'))->cachePerRole();
return AccessResult::forbiddenIf(!$account->hasPermission('view test_view_field content'))->cachePerPermissions();
}
return AccessResult::allowed();
......
......@@ -124,7 +124,7 @@ function testFormatPermissions() {
// which they were granted access.
$fallback_format = entity_load('filter_format', filter_fallback_format());
$this->assertTrue($this->allowedFormat->access('use', $this->webUser), 'A regular user has access to use a text format they were granted access to.');
$this->assertEqual(AccessResult::allowed()->cachePerRole(), $this->allowedFormat->access('use', $this->webUser, TRUE), 'A regular user has access to use a text format they were granted access to.');
$this->assertEqual(AccessResult::allowed()->addCacheContexts(['user.permissions']), $this->allowedFormat->access('use', $this->webUser, TRUE), 'A regular user has access to use a text format they were granted access to.');
$this->assertFalse($this->disallowedFormat->access('use', $this->webUser), 'A regular user does not have access to use a text format they were not granted access to.');
$this->assertEqual(AccessResult::neutral(), $this->disallowedFormat->access('use', $this->webUser, TRUE)); //, 'A regular user does not have access to use a text format they were not granted access to.');
$this->assertTrue($fallback_format->access('use', $this->webUser), 'A regular user has access to use the fallback format.');
......
......@@ -59,11 +59,11 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A
case 'update':
if (!$account->hasPermission('administer menu')) {
return AccessResult::neutral()->cachePerRole();
return AccessResult::neutral()->cachePerPermissions();
}
else {
// If there is a URL, this is an external link so always accessible.
$access = AccessResult::allowed()->cachePerRole()->cacheUntilEntityChanges($entity);
$access = AccessResult::allowed()->cachePerPermissions()->cacheUntilEntityChanges($entity);
/** @var \Drupal\menu_link_content\MenuLinkContentInterface $entity */
// We allow access, but only if the link is accessible as well.
if (($url_object = $entity->getUrlObject()) && $url_object->isRouted()) {
......@@ -74,7 +74,7 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A
}
case 'delete':
return AccessResult::allowedIf(!$entity->isNew() && $account->hasPermission('administer menu'))->cachePerRole()->cacheUntilEntityChanges($entity);
return AccessResult::allowedIf(!$entity->isNew() && $account->hasPermission('administer menu'))->cachePerPermissions()->cacheUntilEntityChanges($entity);
}
}
......
......@@ -336,18 +336,18 @@ function hook_node_access(\Drupal\node\NodeInterface $node, $op, \Drupal\Core\Se
case 'update':
if ($account->hasPermission('edit any ' . $type . ' content', $account)) {
return AccessResult::allowed()->cachePerRole();
return AccessResult::allowed()->cachePerPermissions();
}
else {
return AccessResult::allowedIf($account->hasPermission('edit own ' . $type . ' content', $account) && ($account->id() == $node->getOwnerId()))->cachePerRole()->cachePerUser()->cacheUntilEntityChanges($node);
return AccessResult::allowedIf($account->hasPermission('edit own ' . $type . ' content', $account) && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->cacheUntilEntityChanges($node);
}
case 'delete':
if ($account->hasPermission('delete any ' . $type . ' content', $account)) {
return AccessResult::allowed()->cachePerRole();
return AccessResult::allowed()->cachePerPermissions();
}
else {
return AccessResult::allowedIf($account->hasPermission('delete own ' . $type . ' content', $account) && ($account->id() == $node->getOwnerId()))->cachePerRole()->cachePerUser()->cacheUntilEntityChanges($node);
return AccessResult::allowedIf($account->hasPermission('delete own ' . $type . ' content', $account) && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->cacheUntilEntityChanges($node);
}
default:
......
......@@ -946,18 +946,18 @@ function node_node_access(NodeInterface $node, $op, $account) {
case 'update':
if ($account->hasPermission('edit any ' . $type . ' content', $account)) {
return AccessResult::allowed()->cachePerRole();
return AccessResult::allowed()->cachePerPermissions();
}
else {
return AccessResult::allowedIf($account->hasPermission('edit own ' . $type . ' content', $account) && ($account->id() == $node->getOwnerId()))->cachePerRole()->cachePerUser()->cacheUntilEntityChanges($node);
return AccessResult::allowedIf($account->hasPermission('edit own ' . $type . ' content', $account) && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->cacheUntilEntityChanges($node);
}
case 'delete':
if ($account->hasPermission('delete any ' . $type . ' content', $account)) {
return AccessResult::allowed()->cachePerRole();
return AccessResult::allowed()->cachePerPermissions();
}
else {
return AccessResult::allowedIf($account->hasPermission('delete own ' . $type . ' content', $account) && ($account->id() == $node->getOwnerId()))->cachePerRole()->cachePerUser()->cacheUntilEntityChanges($node);
return AccessResult::allowedIf($account->hasPermission('delete own ' . $type . ' content', $account) && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->cacheUntilEntityChanges($node);
}
default:
......
......@@ -51,7 +51,7 @@ public function access(AccountInterface $account, NodeTypeInterface $node_type =
$access_control_handler = $this->entityManager->getAccessControlHandler('node');
// If checking whether a node of a particular type may be created.
if ($account->hasPermission('administer content types')) {
return AccessResult::allowed()->cachePerRole();
return AccessResult::allowed()->cachePerPermissions();
}
if ($node_type) {
return $access_control_handler->createAccess($node_type->id(), $account, [], TRUE);
......
......@@ -77,7 +77,7 @@ public function access(Route $route, AccountInterface $account, $node_revision =
$node = $this->nodeStorage->loadRevision($node_revision);
}
$operation = $route->getRequirement('_access_node_revision');
return AccessResult::allowedIf($node && $this->checkAccess($node, $account, $operation))->cachePerRole();
return AccessResult::allowedIf($node && $this->checkAccess($node, $account, $operation))->cachePerPermissions();
}
/**
......
......@@ -63,14 +63,14 @@ public function access(EntityInterface $entity, $operation, $langcode = Language
$account = $this->prepareUser($account);
if ($account->hasPermission('bypass node access')) {
$result = AccessResult::allowed()->cachePerRole();
$result = AccessResult::allowed()->cachePerPermissions();
return $return_as_object ? $result : $result->isAllowed();
}
if (!$account->hasPermission('access content')) {
$result = AccessResult::forbidden()->cachePerRole();
$result = AccessResult::forbidden()->cachePerPermissions();
return $return_as_object ? $result : $result->isAllowed();
}
$result = parent::access($entity, $operation, $langcode, $account, TRUE)->cachePerRole();
$result = parent::access($entity, $operation, $langcode, $account, TRUE)->cachePerPermissions();
return $return_as_object ? $result : $result->isAllowed();
}
......@@ -81,15 +81,15 @@ public function createAccess($entity_bundle = NULL, AccountInterface $account =
$account = $this->prepareUser($account);
if ($account->hasPermission('bypass node access')) {
$result = AccessResult::allowed()->cachePerRole();
$result = AccessResult::allowed()->cachePerPermissions();
return $return_as_object ? $result : $result->isAllowed();
}
if (!$account->hasPermission('access content')) {
$result = AccessResult::forbidden()->cachePerRole();
$result = AccessResult::forbidden()->cachePerPermissions();
return $return_as_object ? $result : $result->isAllowed();
}
$result = parent::createAccess($entity_bundle, $account, $context, TRUE)->cachePerRole();
$result = parent::createAccess($entity_bundle, $account, $context, TRUE)->cachePerPermissions();
return $return_as_object ? $result : $result->isAllowed();
}
......@@ -106,7 +106,7 @@ protected function checkAccess(EntityInterface $node, $operation, $langcode, Acc
// Check if authors can view their own unpublished nodes.
if ($operation === 'view' && !$status && $account->hasPermission('view own unpublished content') && $account->isAuthenticated() && $account->id() == $uid) {
return AccessResult::allowed()->cachePerRole()->cachePerUser()->cacheUntilEntityChanges($node);
return AccessResult::allowed()->cachePerPermissions()->cachePerUser()->cacheUntilEntityChanges($node);
}
// If no module specified either ALLOW or KILL, we fall back to the
......@@ -130,7 +130,7 @@ protected function checkAccess(EntityInterface $node, $operation, $langcode, Acc
* {@inheritdoc}
*/
protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
return AccessResult::allowedIf($account->hasPermission('create ' . $entity_bundle . ' content'))->cachePerRole();
return AccessResult::allowedIf($account->hasPermission('create ' . $entity_bundle . ' content'))->cachePerPermissions();
}
/**
......@@ -154,9 +154,9 @@ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_
// administrative permissions or if the new revision option is enabled.
if ($operation == 'edit' && $field_definition->getName() == 'revision_log') {
if ($account->hasPermission('administer nodes')) {
return AccessResult::allowed()->cachePerRole();
return AccessResult::allowed()->cachePerPermissions();
}
return AccessResult::allowedIf($items->getEntity()->type->entity->isNewRevision())->cachePerRole();
return AccessResult::allowedIf($items->getEntity()->type->entity->isNewRevision())->cachePerPermissions();
}
return parent::checkFieldAccess($operation, $field_definition, $account, $items);
}
......
......@@ -23,7 +23,7 @@ public function defaultAccess($operation = 'view', AccountInterface $account = N
if ($operation == 'view') {
return AccessResult::allowed();
}
return AccessResult::allowedIfHasPermissions($account, ['create url aliases', 'administer url aliases'], 'OR')->cachePerRole();
return AccessResult::allowedIfHasPermissions($account, ['create url aliases', 'administer url aliases'], 'OR')->cachePerPermissions();
}
}
......@@ -44,12 +44,12 @@ public function providerTestAccess() {
$editable_entity = $this->createMockEntity();
$editable_entity->expects($this->any())
->method('access')
->will($this->returnValue(AccessResult::allowed()->cachePerRole()));
->will($this->returnValue(AccessResult::allowed()->cachePerPermissions()));
$non_editable_entity = $this->createMockEntity();
$non_editable_entity->expects($this->any())
->method('access')
->will($this->returnValue(AccessResult::neutral()->cachePerRole()));
->will($this->returnValue(AccessResult::neutral()->cachePerPermissions()));
$field_storage_with_access = $this->getMockBuilder('Drupal\field\Entity\FieldStorageConfig')
->disableOriginalConstructor()
......@@ -65,10 +65,10 @@ public function providerTestAccess() {
->will($this->returnValue(AccessResult::neutral()));
$data = array();
$data[] = array($editable_entity, $field_storage_with_access, AccessResult::allowed()->cachePerRole());
$data[] = array($non_editable_entity, $field_storage_with_access, AccessResult::neutral()->cachePerRole());
$data[] = array($editable_entity, $field_storage_without_access, AccessResult::neutral()->cachePerRole());
$data[] = array($non_editable_entity, $field_storage_without_access, AccessResult::neutral()->cachePerRole());
$data[] = array($editable_entity, $field_storage_with_access, AccessResult::allowed()->cachePerPermissions());
$data[] = array($non_editable_entity, $field_storage_with_access, AccessResult::neutral()->cachePerPermissions());
$data[] = array($editable_entity, $field_storage_without_access, AccessResult::neutral()->cachePerPermissions());
$data[] = array($non_editable_entity, $field_storage_without_access, AccessResult::neutral()->cachePerPermissions());
return $data;
}
......
......@@ -59,13 +59,13 @@ function shortcut_set_edit_access(ShortcutSetInterface $shortcut_set = NULL) {
// Shortcut administrators can edit any set.
if ($account->hasPermission('administer shortcuts')) {
return AccessResult::allowed()->cachePerRole();
return AccessResult::allowed()->cachePerPermissions();
}
// Sufficiently-privileged users can edit their currently displayed shortcut
// set, but not other sets. They must also be able to access shortcuts.
$may_edit_current_shortcut_set = $account->hasPermission('customize shortcut links') && (!isset($shortcut_set) || $shortcut_set == shortcut_current_displayed_set()) && $account->hasPermission('access shortcuts');
return AccessResult::allowedIf($may_edit_current_shortcut_set)->cachePerRole();
return AccessResult::allowedIf($may_edit_current_shortcut_set)->cachePerPermissions();
}
/**
......@@ -84,30 +84,30 @@ function shortcut_set_switch_access($account = NULL) {
if ($user->hasPermission('administer shortcuts')) {
// Administrators can switch anyone's shortcut set.
return AccessResult::allowed()->cachePerRole();
return AccessResult::allowed()->cachePerPermissions();
}
if (!$user->hasPermission('access shortcuts')) {
// The user has no permission to use shortcuts.
return AccessResult::neutral()->cachePerRole();
return AccessResult::neutral()->cachePerPermissions();
}
if (!$user->hasPermission('switch shortcut sets')) {
// The user has no permission to switch anyone's shortcut set.
return AccessResult::neutral()->cachePerRole();
return AccessResult::neutral()->cachePerPermissions();
}
// Users with the 'switch shortcut sets' permission can switch their own
// shortcuts sets.
if (!isset($account)) {
return AccessResult::allowed()->cachePerRole();
return AccessResult::allowed()->cachePerPermissions();
}
else if ($user->id() == $account->id()) {
return AccessResult::allowed()->cachePerRole()->cachePerUser();
return AccessResult::allowed()->cachePerPermissions()->cachePerUser();
}
// No opinion.
return AccessResult::neutral()->cachePerRole();
return AccessResult::neutral()->cachePerPermissions();
}
/**
......
......@@ -26,15 +26,15 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A
switch ($operation) {
case 'update':
if ($account->hasPermission('administer shortcuts')) {
return AccessResult::allowed()->cachePerRole();
return AccessResult::allowed()->cachePerPermissions();
}
if (!$account->hasPermission('access shortcuts')) {
return AccessResult::neutral()->cachePerRole();
return AccessResult::neutral()->cachePerPermissions();
}
return AccessResult::allowedIf($account->hasPermission('customize shortcut links') && $entity == shortcut_current_displayed_set($account))->cachePerRole()->cacheUntilEntityChanges($entity);
return AccessResult::allowedIf($account->hasPermission('customize shortcut links') && $entity == shortcut_current_displayed_set($account))->cachePerPermissions()->cacheUntilEntityChanges($entity);
case 'delete':
return AccessResult::allowedIf($account->hasPermission('administer shortcuts') && $entity->id() != 'default')->cachePerRole();
return AccessResult::allowedIf($account->hasPermission('administer shortcuts') && $entity->id() != 'default')->cachePerPermissions();
default:
// No opinion.
......
......@@ -33,10 +33,10 @@ public function access(AccountInterface $account) {
}
if ($account->hasPermission('administer software updates')) {
return AccessResult::allowed()->cachePerRole();
return AccessResult::allowed()->cachePerPermissions();
}
else {
return AccessResult::forbidden()->cachePerRole();
return AccessResult::forbidden()->cachePerPermissions();
}
}
}
......@@ -53,7 +53,7 @@ public function subtreesJsonp() {
* The access result.
*/
public function checkSubTreeAccess($hash, $langcode) {
return AccessResult::allowedIf($this->currentUser()->hasPermission('access toolbar') && $hash == _toolbar_get_subtrees_hash($langcode))->cachePerRole();
return AccessResult::allowedIf($this->currentUser()->hasPermission('access toolbar') && $hash == _toolbar_get_subtrees_hash($langcode))->cachePerPermissions();
}
}
......@@ -31,7 +31,7 @@ class LoginStatusCheck implements AccessInterface {
public function access(AccountInterface $account, Route $route) {
$required_status = filter_var($route->getRequirement('_user_is_logged_in'), FILTER_VALIDATE_BOOLEAN);
$actual_status = $account->isAuthenticated();
return AccessResult::allowedIf($required_status === $actual_status)->cachePerRole();
return AccessResult::allowedIf($required_status === $actual_status)->addCacheContexts(['user.roles:authenticated']);
}
}
......@@ -31,6 +31,11 @@ class PermissionAccessCheck implements AccessInterface {
*/