class AccessControl in Group 2.0.x
Provides access control for group relation plugins.
Hierarchy
- class \Drupal\group\Plugin\Group\RelationHandlerDefault\AccessControl implements AccessControlInterface uses AccessControlTrait
Expanded class hierarchy of AccessControl
1 file declares its use of AccessControl
- AccessControlTest.php in tests/
src/ Unit/ AccessControlTest.php
1 string reference to 'AccessControl'
1 service uses AccessControl
File
- src/
Plugin/ Group/ RelationHandlerDefault/ AccessControl.php, line 21
Namespace
Drupal\group\Plugin\Group\RelationHandlerDefaultView source
class AccessControl implements AccessControlInterface {
use AccessControlTrait;
/**
* Constructs a new AccessControl.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\group\Plugin\Group\Relation\GroupRelationManagerInterface $groupRelationManager
* The group relation manager.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, GroupRelationManagerInterface $groupRelationManager) {
$this->entityTypeManager = $entity_type_manager;
$this->groupRelationManager = $groupRelationManager;
}
/**
* {@inheritdoc}
*/
public function relationAccess(GroupContentInterface $group_content, $operation, AccountInterface $account, $return_as_object = FALSE) {
$result = AccessResult::neutral();
// Check if the account is the owner.
$is_owner = $group_content
->getOwnerId() === $account
->id();
// Add in the admin permission and filter out the unsupported permissions.
$permissions = [
$this->permissionProvider
->getAdminPermission(),
];
$permissions[] = $this->permissionProvider
->getPermission($operation, 'relation', 'any');
$own_permission = $this->permissionProvider
->getPermission($operation, 'relation', 'own');
if ($is_owner) {
$permissions[] = $own_permission;
}
$permissions = array_filter($permissions);
// If we still have permissions left, check for access.
if (!empty($permissions)) {
$result = GroupAccessResult::allowedIfHasGroupPermissions($group_content
->getGroup(), $account, $permissions, 'OR');
}
// If there was an owner permission to check, the result needs to vary per
// user. We also need to add the relation as a dependency because if its
// owner changes, someone might suddenly gain or lose access.
if ($own_permission) {
// @todo Not necessary if admin, could boost performance here.
$result
->cachePerUser()
->addCacheableDependency($group_content);
}
return $return_as_object ? $result : $result
->isAllowed();
}
/**
* {@inheritdoc}
*/
public function relationCreateAccess(GroupInterface $group, AccountInterface $account, $return_as_object = FALSE) {
$permission = $this->permissionProvider
->getPermission('create', 'relation');
return $this
->combinedPermissionCheck($group, $account, $permission, $return_as_object);
}
/**
* {@inheritdoc}
*/
public function entityAccess(EntityInterface $entity, $operation, AccountInterface $account, $return_as_object = FALSE) {
/** @var \Drupal\group\Entity\Storage\GroupContentStorageInterface $storage */
$storage = $this
->entityTypeManager()
->getStorage('group_content');
$group_contents = $storage
->loadByEntity($entity);
// Filter out the content that does not use this plugin.
foreach ($group_contents as $id => $group_content) {
// @todo Shows the need for a plugin ID base field.
$plugin_id = $group_content
->getRelationPlugin()
->getPluginId();
if ($plugin_id !== $this->pluginId) {
unset($group_contents[$id]);
}
}
// If this plugin is not being used by the entity, we have nothing to say.
if (empty($group_contents)) {
return AccessResult::neutral();
}
// We only check unpublished vs published for "view" right now. If we ever
// start supporting other operations, we need to remove the "view" check.
$check_published = $operation === 'view' && $entity
->getEntityType()
->entityClassImplements(EntityPublishedInterface::class);
// Check if the account is the owner and an owner permission is supported.
$is_owner = FALSE;
if ($entity
->getEntityType()
->entityClassImplements(EntityOwnerInterface::class)) {
$is_owner = $entity
->getOwnerId() === $account
->id();
}
// Add in the admin permission and filter out the unsupported permissions.
$permissions = [
$this->permissionProvider
->getAdminPermission(),
];
if (!$check_published || $entity
->isPublished()) {
$permissions[] = $this->permissionProvider
->getPermission($operation, 'entity', 'any');
$own_permission = $this->permissionProvider
->getPermission($operation, 'entity', 'own');
if ($is_owner) {
$permissions[] = $own_permission;
}
}
elseif ($check_published && !$entity
->isPublished()) {
$permissions[] = $this->permissionProvider
->getPermission("{$operation} unpublished", 'entity', 'any');
$own_permission = $this->permissionProvider
->getPermission("{$operation} unpublished", 'entity', 'own');
if ($is_owner) {
$permissions[] = $own_permission;
}
}
$permissions = array_filter($permissions);
foreach ($group_contents as $group_content) {
$result = GroupAccessResult::allowedIfHasGroupPermissions($group_content
->getGroup(), $account, $permissions, 'OR');
if ($result
->isAllowed()) {
break;
}
}
// If we did not allow access, we need to explicitly forbid access to avoid
// other modules from granting access where Group promised the entity would
// be inaccessible.
if (!$result
->isAllowed()) {
$result = AccessResult::forbidden()
->addCacheContexts([
'user.group_permissions',
]);
}
// If there was an owner permission to check, the result needs to vary per
// user. We also need to add the entity as a dependency because if its owner
// changes, someone might suddenly gain or lose access.
if (!empty($own_permission)) {
// @todo Not necessary if admin, could boost performance here.
$result
->cachePerUser();
}
// If we needed to check for the owner permission or published access, we
// need to add the entity as a dependency because the owner or publication
// status might change.
if (!empty($own_permission) || $check_published) {
// @todo Not necessary if admin, could boost performance here.
$result
->addCacheableDependency($entity);
}
return $return_as_object ? $result : $result
->isAllowed();
}
/**
* {@inheritdoc}
*/
public function entityCreateAccess(GroupInterface $group, AccountInterface $account, $return_as_object = FALSE) {
// You cannot create target entities if the plugin does not support it.
if (empty($this->definition['entity_access'])) {
return $return_as_object ? AccessResult::neutral() : FALSE;
}
$permission = $this->permissionProvider
->getPermission('create', 'entity');
return $this
->combinedPermissionCheck($group, $account, $permission, $return_as_object);
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
AccessControl:: |
public | function |
Checks access to an operation on the entity. Overrides AccessControlTrait:: |
|
AccessControl:: |
public | function |
Checks access to create an entity. Overrides AccessControlTrait:: |
|
AccessControl:: |
public | function |
Checks access to an operation on the relation. Overrides AccessControlTrait:: |
|
AccessControl:: |
public | function |
Checks access to create a relation. Overrides AccessControlTrait:: |
|
AccessControl:: |
public | function | Constructs a new AccessControl. | |
AccessControlTrait:: |
protected | property | The plugin's permission provider. | |
AccessControlTrait:: |
protected | function | Checks the provided permission alongside the admin permission. | |
AccessControlTrait:: |
public | function | ||
RelationHandlerTrait:: |
protected | property | The plugin definition. | |
RelationHandlerTrait:: |
protected | property | The entity type manager. | |
RelationHandlerTrait:: |
protected | property | The group relation manager. | |
RelationHandlerTrait:: |
protected | property | The parent relation handler in the decorator chain. | |
RelationHandlerTrait:: |
protected | property | The plugin ID as read from the definition. | |
RelationHandlerTrait:: |
protected | function | Gets the entity type manager service. | |
RelationHandlerTrait:: |
protected | function | Gets the group relation manager service. | |
RelationHandlerTrait:: |
public | function | Aliased as: traitInit |