updated core and modules
This commit is contained in:
@@ -5,8 +5,8 @@ type: module
|
||||
dependencies:
|
||||
- system (>=8.1.0)
|
||||
|
||||
# Information added by Drupal.org packaging script on 2016-06-23
|
||||
version: '8.x-1.0-alpha3+2-dev'
|
||||
# Information added by Drupal.org packaging script on 2016-12-08
|
||||
version: '8.x-1.0-alpha4'
|
||||
core: '8.x'
|
||||
project: 'entity'
|
||||
datestamp: 1466693538
|
||||
datestamp: 1481194986
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
permission_callbacks:
|
||||
- \Drupal\entity\EntityPermissions::buildPermissions
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler as CoreEntityAccessControlHandler;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\user\EntityOwnerInterface;
|
||||
|
||||
/**
|
||||
* Controls access based on the generic entity permissions.
|
||||
*
|
||||
* @see \Drupal\entity\EntityPermissionProvider
|
||||
*/
|
||||
class EntityAccessControlHandler extends CoreEntityAccessControlHandler {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
$account = $this->prepareUser($account);
|
||||
/** @var \Drupal\Core\Access\AccessResult $result */
|
||||
$result = parent::checkAccess($entity, $operation, $account);
|
||||
|
||||
if ($result->isNeutral()) {
|
||||
if ($entity instanceof EntityOwnerInterface) {
|
||||
$result = $this->checkEntityOwnerPermissions($entity, $operation, $account);
|
||||
}
|
||||
else {
|
||||
$result = $this->checkEntityPermissions($entity, $operation, $account);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that access is evaluated again when the entity changes.
|
||||
return $result->addCacheableDependency($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the entity operation and bundle permissions.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity for which to check access.
|
||||
* @param string $operation
|
||||
* The entity operation. Usually one of 'view', 'view label', 'update' or
|
||||
* 'delete'.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The user for which to check access.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The access result.
|
||||
*/
|
||||
protected function checkEntityPermissions(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
return AccessResult::allowedIfHasPermissions($account, [
|
||||
"$operation {$entity->getEntityTypeId()}",
|
||||
"$operation {$entity->bundle()} {$entity->getEntityTypeId()}",
|
||||
], 'OR');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the entity operation and bundle permissions, with owners.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity for which to check access.
|
||||
* @param string $operation
|
||||
* The entity operation. Usually one of 'view', 'view label', 'update' or
|
||||
* 'delete'.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The user for which to check access.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The access result.
|
||||
*/
|
||||
protected function checkEntityOwnerPermissions(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
/** @var \Drupal\Core\Entity\EntityInterface|\Drupal\user\EntityOwnerInterface $entity */
|
||||
if (($account->id() == $entity->getOwnerId())) {
|
||||
$result = AccessResult::allowedIfHasPermissions($account, [
|
||||
"$operation own {$entity->getEntityTypeId()}",
|
||||
"$operation any {$entity->getEntityTypeId()}",
|
||||
"$operation own {$entity->bundle()} {$entity->getEntityTypeId()}",
|
||||
"$operation any {$entity->bundle()} {$entity->getEntityTypeId()}",
|
||||
], 'OR');
|
||||
}
|
||||
else {
|
||||
$result = AccessResult::allowedIfHasPermissions($account, [
|
||||
"$operation any {$entity->getEntityTypeId()}",
|
||||
"$operation any {$entity->bundle()} {$entity->getEntityTypeId()}",
|
||||
], 'OR');
|
||||
}
|
||||
|
||||
return $result->cachePerUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
|
||||
$result = parent::checkCreateAccess($account, $context, $entity_bundle);
|
||||
if ($result->isNeutral()) {
|
||||
$permissions = [
|
||||
'administer ' . $this->entityTypeId,
|
||||
'create ' . $this->entityTypeId,
|
||||
];
|
||||
if ($entity_bundle) {
|
||||
$permissions[] = 'create ' . $entity_bundle . ' ' . $this->entityTypeId;
|
||||
}
|
||||
|
||||
$result = AccessResult::allowedIfHasPermissions($account, $permissions, 'OR');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityHandlerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\user\EntityOwnerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides generic entity permissions.
|
||||
*
|
||||
* Supports both entity_type and bundle granularities.
|
||||
* Supports entity ownership (own/any permissions).
|
||||
*
|
||||
* Intended for content entity types, since config entity types usually rely
|
||||
* on a single "administer" permission.
|
||||
* Example annotation:
|
||||
* @code
|
||||
* handlers = {
|
||||
* "access" = "Drupal\entity\EntityAccessControlHandler",
|
||||
* "permission_provider" = "Drupal\entity\EntityPermissionProvider",
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @see \Drupal\entity\EntityAccessControlHandler
|
||||
* @see \Drupal\entity\EntityPermissions
|
||||
*/
|
||||
class EntityPermissionProvider implements EntityPermissionProviderInterface, EntityHandlerInterface {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* The entity type bundle info.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
|
||||
*/
|
||||
protected $entityTypeBundleInfo;
|
||||
|
||||
/**
|
||||
* Constructs a new EntityPermissionProvider object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
|
||||
* The entity type bundle info.
|
||||
*/
|
||||
public function __construct(EntityTypeBundleInfoInterface $entity_type_bundle_info) {
|
||||
$this->entityTypeBundleInfo = $entity_type_bundle_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
|
||||
return new static(
|
||||
$container->get('entity_type.bundle.info')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildPermissions(EntityTypeInterface $entity_type) {
|
||||
$entity_type_id = $entity_type->id();
|
||||
$has_owner = $entity_type->isSubclassOf(EntityOwnerInterface::class);
|
||||
$singular_label = $entity_type->getSingularLabel();
|
||||
$plural_label = $entity_type->getPluralLabel();
|
||||
|
||||
$permissions = [];
|
||||
$permissions["administer {$entity_type_id}"] = [
|
||||
'title' => $this->t('Administer @type', ['@type' => $plural_label]),
|
||||
'restrict access' => TRUE,
|
||||
];
|
||||
$permissions["access {$entity_type_id} overview"] = [
|
||||
'title' => $this->t('Access the @type overview page', ['@type' => $plural_label]),
|
||||
];
|
||||
// View permissions are the same for both granularities.
|
||||
if ($has_owner) {
|
||||
$permissions["view any {$entity_type_id}"] = [
|
||||
'title' => $this->t('View any @type', [
|
||||
'@type' => $singular_label,
|
||||
]),
|
||||
];
|
||||
$permissions["view own {$entity_type_id}"] = [
|
||||
'title' => $this->t('View own @type', [
|
||||
'@type' => $plural_label,
|
||||
]),
|
||||
];
|
||||
}
|
||||
else {
|
||||
$permissions["view {$entity_type_id}"] = [
|
||||
'title' => $this->t('View @type', [
|
||||
'@type' => $plural_label,
|
||||
]),
|
||||
];
|
||||
}
|
||||
// Generate the other permissions based on granularity.
|
||||
if ($entity_type->getPermissionGranularity() == 'entity_type') {
|
||||
$permissions += $this->buildEntityTypePermissions($entity_type);
|
||||
}
|
||||
else {
|
||||
$permissions += $this->buildBundlePermissions($entity_type);
|
||||
}
|
||||
|
||||
foreach ($permissions as $name => $permission) {
|
||||
// Permissions are grouped by provider on admin/people/permissions.
|
||||
$permissions[$name]['provider'] = $entity_type->getProvider();
|
||||
// TranslatableMarkup objects don't sort properly.
|
||||
$permissions[$name]['title'] = (string) $permission['title'];
|
||||
}
|
||||
|
||||
return $permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds permissions for the entity_type granularity.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type.
|
||||
*
|
||||
* @return array
|
||||
* The permissions.
|
||||
*/
|
||||
protected function buildEntityTypePermissions(EntityTypeInterface $entity_type) {
|
||||
$entity_type_id = $entity_type->id();
|
||||
$has_owner = $entity_type->isSubclassOf(EntityOwnerInterface::class);
|
||||
$singular_label = $entity_type->getSingularLabel();
|
||||
$plural_label = $entity_type->getPluralLabel();
|
||||
|
||||
$permissions = [];
|
||||
$permissions["create {$entity_type_id}"] = [
|
||||
'title' => $this->t('Create @type', [
|
||||
'@type' => $plural_label,
|
||||
]),
|
||||
];
|
||||
if ($has_owner) {
|
||||
$permissions["update any {$entity_type_id}"] = [
|
||||
'title' => $this->t('Update any @type', [
|
||||
'@type' => $singular_label,
|
||||
]),
|
||||
];
|
||||
$permissions["update own {$entity_type_id}"] = [
|
||||
'title' => $this->t('Update own @type', [
|
||||
'@type' => $plural_label,
|
||||
]),
|
||||
];
|
||||
$permissions["delete any {$entity_type_id}"] = [
|
||||
'title' => $this->t('Delete any @type', [
|
||||
'@type' => $singular_label,
|
||||
]),
|
||||
];
|
||||
$permissions["delete own {$entity_type_id}"] = [
|
||||
'title' => $this->t('Delete own @type', [
|
||||
'@type' => $plural_label,
|
||||
]),
|
||||
];
|
||||
}
|
||||
else {
|
||||
$permissions["update {$entity_type_id}"] = [
|
||||
'title' => $this->t('Update @type', [
|
||||
'@type' => $plural_label,
|
||||
]),
|
||||
];
|
||||
$permissions["delete {$entity_type_id}"] = [
|
||||
'title' => $this->t('Delete @type', [
|
||||
'@type' => $plural_label,
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
return $permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds permissions for the bundle granularity.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type.
|
||||
*
|
||||
* @return array
|
||||
* The permissions.
|
||||
*/
|
||||
protected function buildBundlePermissions(EntityTypeInterface $entity_type) {
|
||||
$entity_type_id = $entity_type->id();
|
||||
$bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type_id);
|
||||
$has_owner = $entity_type->isSubclassOf(EntityOwnerInterface::class);
|
||||
$singular_label = $entity_type->getSingularLabel();
|
||||
$plural_label = $entity_type->getPluralLabel();
|
||||
|
||||
$permissions = [];
|
||||
foreach ($bundles as $bundle_name => $bundle_info) {
|
||||
$permissions["create {$bundle_name} {$entity_type_id}"] = [
|
||||
'title' => $this->t('@bundle: Create @type', [
|
||||
'@bundle' => $bundle_info['label'],
|
||||
'@type' => $plural_label,
|
||||
]),
|
||||
];
|
||||
|
||||
if ($has_owner) {
|
||||
$permissions["update any {$bundle_name} {$entity_type_id}"] = [
|
||||
'title' => $this->t('@bundle: Update any @type', [
|
||||
'@bundle' => $bundle_info['label'],
|
||||
'@type' => $singular_label,
|
||||
]),
|
||||
];
|
||||
$permissions["update own {$bundle_name} {$entity_type_id}"] = [
|
||||
'title' => $this->t('@bundle: Update own @type', [
|
||||
'@bundle' => $bundle_info['label'],
|
||||
'@type' => $plural_label,
|
||||
]),
|
||||
];
|
||||
$permissions["delete any {$bundle_name} {$entity_type_id}"] = [
|
||||
'title' => $this->t('@bundle: Delete any @type', [
|
||||
'@bundle' => $bundle_info['label'],
|
||||
'@type' => $singular_label,
|
||||
]),
|
||||
];
|
||||
$permissions["delete own {$bundle_name} {$entity_type_id}"] = [
|
||||
'title' => $this->t('@bundle: Delete own @type', [
|
||||
'@bundle' => $bundle_info['label'],
|
||||
'@type' => $plural_label,
|
||||
]),
|
||||
];
|
||||
}
|
||||
else {
|
||||
$permissions["update {$bundle_name} {$entity_type_id}"] = [
|
||||
'title' => $this->t('@bundle: Update @type', [
|
||||
'@bundle' => $bundle_info['label'],
|
||||
'@type' => $plural_label,
|
||||
]),
|
||||
];
|
||||
$permissions["delete {$bundle_name} {$entity_type_id}"] = [
|
||||
'title' => $this->t('@bundle: Delete @type', [
|
||||
'@bundle' => $bundle_info['label'],
|
||||
'@type' => $plural_label,
|
||||
]),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $permissions;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
|
||||
/**
|
||||
* Allows entity types to provide permissions.
|
||||
*/
|
||||
interface EntityPermissionProviderInterface {
|
||||
|
||||
/**
|
||||
* Builds permissions for the given entity type.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type.
|
||||
*
|
||||
* @return array
|
||||
* The permissions.
|
||||
*/
|
||||
public function buildPermissions(EntityTypeInterface $entity_type);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\entity;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Generates entity permissions via their permission providers.
|
||||
*
|
||||
* @see \Drupal\entity\EntityPermissionProvider
|
||||
*/
|
||||
class EntityPermissions implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Constructs a new EntityPermissions object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
*/
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity_type.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list of permissions for the participating entity types.
|
||||
*
|
||||
* @return array
|
||||
* The permissions.
|
||||
*/
|
||||
public function buildPermissions() {
|
||||
$permissions = [];
|
||||
/** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
|
||||
foreach ($this->entityTypeManager->getDefinitions() as $entity_type) {
|
||||
if ($entity_type->hasHandlerClass('permission_provider')) {
|
||||
$permission_provider_class = $entity_type->getHandlerClass('permission_provider');
|
||||
$permission_provider = $this->entityTypeManager->createHandlerInstance($permission_provider_class, $entity_type);
|
||||
$permissions += $permission_provider->buildPermissions($entity_type);
|
||||
}
|
||||
}
|
||||
|
||||
return $permissions;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -124,7 +124,7 @@ class RevisionableContentEntityForm extends ContentEntityForm {
|
||||
$insert = $this->entity->isNew();
|
||||
$this->entity->save();
|
||||
$context = ['@type' => $this->entity->bundle(), '%info' => $this->entity->label()];
|
||||
$logger = $this->logger($this->entity->id());
|
||||
$logger = $this->logger('content');
|
||||
$bundle_entity = $this->getBundleEntity();
|
||||
$t_args = ['@type' => $bundle_entity ? $bundle_entity->label() : 'None', '%info' => $this->entity->label()];
|
||||
|
||||
|
||||
+3
-3
@@ -2,8 +2,8 @@ name: Entity test
|
||||
type: module
|
||||
# core: 8.x
|
||||
|
||||
# Information added by Drupal.org packaging script on 2016-06-23
|
||||
version: '8.x-1.0-alpha3+2-dev'
|
||||
# Information added by Drupal.org packaging script on 2016-12-08
|
||||
version: '8.x-1.0-alpha4'
|
||||
core: '8.x'
|
||||
project: 'entity'
|
||||
datestamp: 1466693538
|
||||
datestamp: 1481194986
|
||||
|
||||
-4
@@ -1,7 +1,3 @@
|
||||
'administer entity_test_enhanced':
|
||||
title: 'Administer entity_test_enhanced'
|
||||
'restrict access': TRUE
|
||||
|
||||
'view all entity_test_enhanced revisions':
|
||||
title: 'View all entity_test_enhanced revisions'
|
||||
'restrict access': TRUE
|
||||
|
||||
+3
@@ -14,6 +14,8 @@ use Drupal\entity\Revision\RevisionableContentEntityBase;
|
||||
* label = @Translation("Entity test with enhancements"),
|
||||
* handlers = {
|
||||
* "storage" = "\Drupal\Core\Entity\Sql\SqlContentEntityStorage",
|
||||
* "access" = "\Drupal\entity\EntityAccessControlHandler",
|
||||
* "permission_provider" = "\Drupal\entity\EntityPermissionProvider",
|
||||
* "form" = {
|
||||
* "add" = "\Drupal\entity\Form\RevisionableContentEntityForm",
|
||||
* "edit" = "\Drupal\entity\Form\RevisionableContentEntityForm",
|
||||
@@ -33,6 +35,7 @@ use Drupal\entity\Revision\RevisionableContentEntityBase;
|
||||
* translatable = TRUE,
|
||||
* revisionable = TRUE,
|
||||
* admin_permission = "administer entity_test_enhanced",
|
||||
* permission_granularity = "bundle",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "bundle" = "type",
|
||||
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\entity\Unit;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\Context\CacheContextsManager;
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\ContentEntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\entity\EntityAccessControlHandler;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\user\EntityOwnerInterface;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\entity\EntityAccessControlHandler
|
||||
* @group entity
|
||||
*/
|
||||
class EntityAccessControlHandlerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$module_handler = $this->prophesize(ModuleHandlerInterface::class);
|
||||
$module_handler->invokeAll(Argument::any(), Argument::any())->willReturn([]);
|
||||
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class);
|
||||
$cache_contexts_manager->assertValidTokens(Argument::any())->willReturn(TRUE);
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('module_handler', $module_handler->reveal());
|
||||
$container->set('cache_contexts_manager', $cache_contexts_manager->reveal());
|
||||
\Drupal::setContainer($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::checkAccess
|
||||
* @covers ::checkEntityPermissions
|
||||
* @covers ::checkEntityOwnerPermissions
|
||||
* @covers ::checkCreateAccess
|
||||
*
|
||||
* @dataProvider accessProvider
|
||||
*/
|
||||
public function testAccess(EntityInterface $entity, $operation, $account, $allowed) {
|
||||
$handler = new EntityAccessControlHandler($entity->getEntityType());
|
||||
$handler->setStringTranslation($this->getStringTranslationStub());
|
||||
$result = $handler->access($entity, $operation, $account);
|
||||
$this->assertEquals($allowed, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::checkCreateAccess
|
||||
*
|
||||
* @dataProvider createAccessProvider
|
||||
*/
|
||||
public function testCreateAccess(EntityTypeInterface $entity_type, $bundle, $account, $allowed) {
|
||||
$handler = new EntityAccessControlHandler($entity_type);
|
||||
$handler->setStringTranslation($this->getStringTranslationStub());
|
||||
$result = $handler->createAccess($bundle, $account);
|
||||
$this->assertEquals($allowed, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testAccess().
|
||||
*
|
||||
* @return array
|
||||
* A list of testAccess method arguments.
|
||||
*/
|
||||
public function accessProvider() {
|
||||
$data = [];
|
||||
|
||||
$entity_type = $this->prophesize(ContentEntityTypeInterface::class);
|
||||
$entity_type->id()->willReturn('green_entity');
|
||||
$entity_type->getAdminPermission()->willReturn('administer green_entity');
|
||||
|
||||
// User with the admin permission can do anything.
|
||||
$entity = $this->buildMockEntity($entity_type->reveal());
|
||||
$account = $this->prophesize(AccountInterface::class);
|
||||
$account->id()->willReturn(6);
|
||||
$account->hasPermission('administer green_entity')->willReturn(TRUE);
|
||||
$data[] = [$entity->reveal(), 'view', $account->reveal(), TRUE];
|
||||
$data[] = [$entity->reveal(), 'update', $account->reveal(), TRUE];
|
||||
$data[] = [$entity->reveal(), 'delete', $account->reveal(), TRUE];
|
||||
|
||||
// Entity with no owner.
|
||||
$entity = $this->buildMockEntity($entity_type->reveal());
|
||||
// User who has access.
|
||||
$first_account = $this->prophesize(AccountInterface::class);
|
||||
$first_account->id()->willReturn(6);
|
||||
$first_account->hasPermission('view green_entity')->willReturn(TRUE);
|
||||
$first_account->hasPermission(Argument::any())->willReturn(FALSE);
|
||||
// User who doesn't have access.
|
||||
$second_account = $this->prophesize(AccountInterface::class);
|
||||
$second_account->id()->willReturn(7);
|
||||
$second_account->hasPermission('view green_entity')->willReturn(FALSE);
|
||||
$second_account->hasPermission(Argument::any())->willReturn(FALSE);
|
||||
$data[] = [$entity->reveal(), 'view', $first_account->reveal(), TRUE];
|
||||
$data[] = [$entity->reveal(), 'view', $second_account->reveal(), FALSE];
|
||||
|
||||
// Entity with owner.
|
||||
$entity = $this->buildMockEntity($entity_type->reveal(), 6);
|
||||
// Owner.
|
||||
$first_account = $this->prophesize(AccountInterface::class);
|
||||
$first_account->id()->willReturn(6);
|
||||
$first_account->hasPermission('update own green_entity')->willReturn(TRUE);
|
||||
$first_account->hasPermission(Argument::any())->willReturn(FALSE);
|
||||
// Non-owner.
|
||||
$second_account = $this->prophesize(AccountInterface::class);
|
||||
$second_account->id()->willReturn(7);
|
||||
$second_account->hasPermission('update own green_entity')->willReturn(TRUE);
|
||||
$second_account->hasPermission(Argument::any())->willReturn(FALSE);
|
||||
// User who can update any.
|
||||
$third_account = $this->prophesize(AccountInterface::class);
|
||||
$third_account->id()->willReturn(8);
|
||||
$third_account->hasPermission('update any green_entity')->willReturn(TRUE);
|
||||
$third_account->hasPermission(Argument::any())->willReturn(FALSE);
|
||||
$data[] = [$entity->reveal(), 'update', $first_account->reveal(), TRUE];
|
||||
$data[] = [$entity->reveal(), 'update', $second_account->reveal(), FALSE];
|
||||
$data[] = [$entity->reveal(), 'update', $third_account->reveal(), TRUE];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testCreateAccess().
|
||||
*
|
||||
* @return array
|
||||
* A list of testCreateAccess method arguments.
|
||||
*/
|
||||
public function createAccessProvider() {
|
||||
$data = [];
|
||||
|
||||
$entity_type = $this->prophesize(ContentEntityTypeInterface::class);
|
||||
$entity_type->id()->willReturn('green_entity');
|
||||
$entity_type->getAdminPermission()->willReturn('administer green_entity');
|
||||
|
||||
// User with the admin permission.
|
||||
$account = $this->prophesize(AccountInterface::class);
|
||||
$account->id()->willReturn(6);
|
||||
$account->hasPermission('administer green_entity')->willReturn(TRUE);
|
||||
$data[] = [$entity_type->reveal(), NULL, $account->reveal(), TRUE];
|
||||
|
||||
// Ordinary user.
|
||||
$account = $this->prophesize(AccountInterface::class);
|
||||
$account->id()->willReturn(6);
|
||||
$account->hasPermission('create green_entity')->willReturn(TRUE);
|
||||
$account->hasPermission(Argument::any())->willReturn(FALSE);
|
||||
$data[] = [$entity_type->reveal(), NULL, $account->reveal(), TRUE];
|
||||
|
||||
// Ordinary user, entity with a bundle.
|
||||
$account = $this->prophesize(AccountInterface::class);
|
||||
$account->id()->willReturn(6);
|
||||
$account->hasPermission('create first_bundle green_entity')->willReturn(TRUE);
|
||||
$account->hasPermission(Argument::any())->willReturn(FALSE);
|
||||
$data[] = [$entity_type->reveal(), 'first_bundle', $account->reveal(), TRUE];
|
||||
|
||||
// User with no permissions.
|
||||
$account = $this->prophesize(AccountInterface::class);
|
||||
$account->id()->willReturn(6);
|
||||
$account->hasPermission(Argument::any())->willReturn(FALSE);
|
||||
$data[] = [$entity_type->reveal(), NULL, $account->reveal(), FALSE];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a mock entity.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type.
|
||||
* @param string $owner_id
|
||||
* The owner ID.
|
||||
*
|
||||
* @return \Prophecy\Prophecy\ObjectProphecy
|
||||
* The entity mock.
|
||||
*/
|
||||
protected function buildMockEntity(EntityTypeInterface $entity_type, $owner_id = NULL) {
|
||||
$langcode = LanguageInterface::LANGCODE_NOT_SPECIFIED;
|
||||
$entity = $this->prophesize(ContentEntityInterface::class);
|
||||
if ($owner_id) {
|
||||
$entity->willImplement(EntityOwnerInterface::class);
|
||||
$entity->getOwnerId()->willReturn($owner_id);
|
||||
}
|
||||
$entity->bundle()->willReturn($entity_type->id());
|
||||
$entity->isNew()->willReturn(FALSE);
|
||||
$entity->uuid()->willReturn('fake uuid');
|
||||
$entity->language()->willReturn(new Language(['id' => $langcode]));
|
||||
$entity->getEntityTypeId()->willReturn($entity_type->id());
|
||||
$entity->getEntityType()->willReturn($entity_type);
|
||||
$entity->getCacheContexts()->willReturn([]);
|
||||
$entity->getCacheTags()->willReturn([]);
|
||||
$entity->getCacheMaxAge()->willReturn(Cache::PERMANENT);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\entity\Unit;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityTypeInterface;
|
||||
use Drupal\Core\Entity\ContentEntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\entity\EntityPermissionProvider;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\user\EntityOwnerInterface;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\entity\EntityPermissionProvider
|
||||
* @group entity
|
||||
*/
|
||||
class EntityPermissionProviderTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The entity permission provider.
|
||||
*
|
||||
* @var \Drupal\entity\EntityPermissionProviderInterface
|
||||
*/
|
||||
protected $permissionProvider;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$entity_type_bundle_info = $this->prophesize(EntityTypeBundleInfoInterface::class);
|
||||
$entity_type_bundle_info->getBundleInfo('white_entity')->willReturn([
|
||||
'first' => ['label' => 'First'],
|
||||
'second' => ['label' => 'Second'],
|
||||
]);
|
||||
$entity_type_bundle_info->getBundleInfo('black_entity')->willReturn([
|
||||
'third' => ['label' => 'Third'],
|
||||
]);
|
||||
$this->permissionProvider = new EntityPermissionProvider($entity_type_bundle_info->reveal());
|
||||
$this->permissionProvider->setStringTranslation($this->getStringTranslationStub());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::buildPermissions
|
||||
*
|
||||
* @dataProvider entityTypeProvider
|
||||
*/
|
||||
public function testBuildPermissions(EntityTypeInterface $entity_type, array $expected_permissions) {
|
||||
$permissions = $this->permissionProvider->buildPermissions($entity_type);
|
||||
$this->assertEquals(array_keys($expected_permissions), array_keys($permissions));
|
||||
foreach ($permissions as $name => $permission) {
|
||||
$this->assertEquals('entity_module_test', $permission['provider']);
|
||||
$this->assertEquals($expected_permissions[$name], $permission['title']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testBuildPermissions().
|
||||
*
|
||||
* @return array
|
||||
* A list of testBuildPermissions method arguments.
|
||||
*/
|
||||
public function entityTypeProvider() {
|
||||
$data = [];
|
||||
// Content entity type.
|
||||
$entity_type = $this->prophesize(ContentEntityTypeInterface::class);
|
||||
$entity_type->getProvider()->willReturn('entity_module_test');
|
||||
$entity_type->id()->willReturn('green_entity');
|
||||
$entity_type->getSingularLabel()->willReturn('green entity');
|
||||
$entity_type->getPluralLabel()->willReturn('green entities');
|
||||
$entity_type->isSubclassOf(EntityOwnerInterface::class)->willReturn(FALSE);
|
||||
$entity_type->getPermissionGranularity()->willReturn('entity_type');
|
||||
$expected_permissions = [
|
||||
'administer green_entity' => 'Administer green entities',
|
||||
'access green_entity overview' => 'Access the green entities overview page',
|
||||
'view green_entity' => 'View green entities',
|
||||
'create green_entity' => 'Create green entities',
|
||||
'update green_entity' => 'Update green entities',
|
||||
'delete green_entity' => 'Delete green entities',
|
||||
];
|
||||
$data[] = [$entity_type->reveal(), $expected_permissions];
|
||||
|
||||
// Content entity type with owner.
|
||||
$entity_type = $this->prophesize(ContentEntityTypeInterface::class);
|
||||
$entity_type->getProvider()->willReturn('entity_module_test');
|
||||
$entity_type->id()->willReturn('blue_entity');
|
||||
$entity_type->getSingularLabel()->willReturn('blue entity');
|
||||
$entity_type->getPluralLabel()->willReturn('blue entities');
|
||||
$entity_type->isSubclassOf(EntityOwnerInterface::class)->willReturn(TRUE);
|
||||
$entity_type->getPermissionGranularity()->willReturn('entity_type');
|
||||
$expected_permissions = [
|
||||
'administer blue_entity' => 'Administer blue entities',
|
||||
'access blue_entity overview' => 'Access the blue entities overview page',
|
||||
'view any blue_entity' => 'View any blue entity',
|
||||
'view own blue_entity' => 'View own blue entities',
|
||||
'create blue_entity' => 'Create blue entities',
|
||||
'update any blue_entity' => 'Update any blue entity',
|
||||
'update own blue_entity' => 'Update own blue entities',
|
||||
'delete any blue_entity' => 'Delete any blue entity',
|
||||
'delete own blue_entity' => 'Delete own blue entities',
|
||||
];
|
||||
$data[] = [$entity_type->reveal(), $expected_permissions];
|
||||
|
||||
// Content entity type with bundles.
|
||||
$entity_type = $this->prophesize(ContentEntityTypeInterface::class);
|
||||
$entity_type->getProvider()->willReturn('entity_module_test');
|
||||
$entity_type->id()->willReturn('white_entity');
|
||||
$entity_type->getSingularLabel()->willReturn('white entity');
|
||||
$entity_type->getPluralLabel()->willReturn('white entities');
|
||||
$entity_type->isSubclassOf(EntityOwnerInterface::class)->willReturn(FALSE);
|
||||
$entity_type->getPermissionGranularity()->willReturn('bundle');
|
||||
$expected_permissions = [
|
||||
'administer white_entity' => 'Administer white entities',
|
||||
'access white_entity overview' => 'Access the white entities overview page',
|
||||
'view white_entity' => 'View white entities',
|
||||
'create first white_entity' => 'First: Create white entities',
|
||||
'update first white_entity' => 'First: Update white entities',
|
||||
'delete first white_entity' => 'First: Delete white entities',
|
||||
'create second white_entity' => 'Second: Create white entities',
|
||||
'update second white_entity' => 'Second: Update white entities',
|
||||
'delete second white_entity' => 'Second: Delete white entities',
|
||||
];
|
||||
$data[] = [$entity_type->reveal(), $expected_permissions];
|
||||
|
||||
// Content entity type with bundles and owner.
|
||||
$entity_type = $this->prophesize(ContentEntityTypeInterface::class);
|
||||
$entity_type->getProvider()->willReturn('entity_module_test');
|
||||
$entity_type->id()->willReturn('black_entity');
|
||||
$entity_type->getSingularLabel()->willReturn('black entity');
|
||||
$entity_type->getPluralLabel()->willReturn('black entities');
|
||||
$entity_type->isSubclassOf(EntityOwnerInterface::class)->willReturn(TRUE);
|
||||
$entity_type->getPermissionGranularity()->willReturn('bundle');
|
||||
$expected_permissions = [
|
||||
'administer black_entity' => 'Administer black entities',
|
||||
'access black_entity overview' => 'Access the black entities overview page',
|
||||
'view any black_entity' => 'View any black entity',
|
||||
'view own black_entity' => 'View own black entities',
|
||||
'create third black_entity' => 'Third: Create black entities',
|
||||
'update any third black_entity' => 'Third: Update any black entity',
|
||||
'update own third black_entity' => 'Third: Update own black entities',
|
||||
'delete any third black_entity' => 'Third: Delete any black entity',
|
||||
'delete own third black_entity' => 'Third: Delete own black entities',
|
||||
];
|
||||
$data[] = [$entity_type->reveal(), $expected_permissions];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user