Issue #2843756 by vaplas, Wim Leers, brentschuddinck, jamesdesq: EntityResource: Provide comprehensive test coverage for FieldStorageConfig entity
parent
e31a0430c1
commit
a6b84bfbf2
|
|
@ -18,6 +18,7 @@ use Drupal\field\FieldStorageConfigInterface;
|
|||
* id = "field_storage_config",
|
||||
* label = @Translation("Field storage"),
|
||||
* handlers = {
|
||||
* "access" = "Drupal\field\FieldStorageConfigAccessControlHandler",
|
||||
* "storage" = "Drupal\field\FieldStorageConfigStorage"
|
||||
* },
|
||||
* config_prefix = "storage",
|
||||
|
|
|
|||
|
|
@ -2,13 +2,12 @@
|
|||
|
||||
namespace Drupal\field;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Defines the access control handler for the field entity type.
|
||||
* Defines the access control handler for the field config entity type.
|
||||
*
|
||||
* @see \Drupal\field\Entity\FieldConfig
|
||||
*/
|
||||
|
|
@ -18,16 +17,16 @@ class FieldConfigAccessControlHandler extends EntityAccessControlHandler {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
if ($operation == 'delete') {
|
||||
$field_storage_entity = $entity->getFieldStorageDefinition();
|
||||
if ($field_storage_entity->isLocked()) {
|
||||
return AccessResult::forbidden()->addCacheableDependency($field_storage_entity);
|
||||
}
|
||||
else {
|
||||
return AccessResult::allowedIfHasPermission($account, 'administer ' . $entity->getTargetEntityTypeId() . ' fields')->addCacheableDependency($field_storage_entity);
|
||||
}
|
||||
}
|
||||
return AccessResult::allowedIfHasPermission($account, 'administer ' . $entity->getTargetEntityTypeId() . ' fields');
|
||||
// Delegate access control to the underlying field storage config entity:
|
||||
// the field config entity merely handles configuration for a particular
|
||||
// bundle of an entity type, the bulk of the logic and configuration is with
|
||||
// the field storage config entity. Therefore, if an operation is allowed on
|
||||
// a certain field storage config entity, it should also be allowed for all
|
||||
// associated field config entities.
|
||||
// @see \Drupal\Core\Field\FieldDefinitionInterface
|
||||
/** \Drupal\field\FieldConfigInterface $entity */
|
||||
$field_storage_entity = $entity->getFieldStorageDefinition();
|
||||
return $field_storage_entity->access($operation, $account, TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\field;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Defines the access control handler for the field storage config entity type.
|
||||
*
|
||||
* @see \Drupal\field\Entity\FieldStorageConfig
|
||||
*/
|
||||
class FieldStorageConfigAccessControlHandler extends EntityAccessControlHandler {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
/** \Drupal\field\FieldStorageConfigInterface $entity */
|
||||
if ($operation === 'delete') {
|
||||
if ($entity->isLocked()) {
|
||||
return AccessResult::forbidden()->addCacheableDependency($entity);
|
||||
}
|
||||
else {
|
||||
return AccessResult::allowedIfHasPermission($account, 'administer ' . $entity->getTargetEntityTypeId() . ' fields')->addCacheableDependency($entity);
|
||||
}
|
||||
}
|
||||
return AccessResult::allowedIfHasPermission($account, 'administer ' . $entity->getTargetEntityTypeId() . ' fields');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\field\Unit;
|
||||
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\FieldConfigAccessControlHandler;
|
||||
|
||||
/**
|
||||
* Tests the field config access controller.
|
||||
*
|
||||
* @group field
|
||||
*
|
||||
* @coversDefaultClass \Drupal\field\FieldConfigAccessControlHandler
|
||||
*/
|
||||
class FieldConfigAccessControlHandlerTest extends FieldStorageConfigAccessControlHandlerTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->entity = new FieldConfig([
|
||||
'field_name' => $this->fieldStorage->getName(),
|
||||
'entity_type' => 'node',
|
||||
'fieldStorage' => $this->fieldStorage,
|
||||
'bundle' => 'test_bundle',
|
||||
'field_type' => 'test_field',
|
||||
], 'node');
|
||||
|
||||
$this->accessControlHandler = new FieldConfigAccessControlHandler($this->entity->getEntityType());
|
||||
$this->accessControlHandler->setModuleHandler($this->moduleHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures field config access is working properly.
|
||||
*/
|
||||
public function testAccess() {
|
||||
$this->assertAllowOperations([], $this->anon);
|
||||
$this->assertAllowOperations(['view', 'update', 'delete'], $this->member);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\field\Unit;
|
||||
|
||||
use Drupal\Component\Uuid\UuidInterface;
|
||||
use Drupal\Core\Cache\Context\CacheContextsManager;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityTypeInterface;
|
||||
use Drupal\Core\DependencyInjection\Container;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\field\FieldStorageConfigAccessControlHandler;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests the field storage config access controller.
|
||||
*
|
||||
* @group field
|
||||
*
|
||||
* @coversDefaultClass \Drupal\field\FieldStorageConfigAccessControlHandler
|
||||
*/
|
||||
class FieldStorageConfigAccessControlHandlerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The field storage config access controller to test.
|
||||
*
|
||||
* @var \Drupal\field\FieldStorageConfigAccessControlHandler
|
||||
*/
|
||||
protected $accessControlHandler;
|
||||
|
||||
/**
|
||||
* The mock module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The mock account without field storage config access.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $anon;
|
||||
|
||||
/**
|
||||
* The mock account with field storage config access.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $member;
|
||||
|
||||
/**
|
||||
* The mocked test field storage config.
|
||||
*
|
||||
* @var \Drupal\field\FieldStorageConfigInterface
|
||||
*/
|
||||
protected $fieldStorage;
|
||||
|
||||
/**
|
||||
* The main entity used for testing.
|
||||
*
|
||||
* @var \Drupal\Core\Config\Entity\ConfigEntityInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->anon = $this->getMock(AccountInterface::class);
|
||||
$this->anon
|
||||
->expects($this->any())
|
||||
->method('hasPermission')
|
||||
->will($this->returnValue(FALSE));
|
||||
$this->anon
|
||||
->expects($this->any())
|
||||
->method('id')
|
||||
->will($this->returnValue(0));
|
||||
|
||||
$this->member = $this->getMock(AccountInterface::class);
|
||||
$this->member
|
||||
->expects($this->any())
|
||||
->method('hasPermission')
|
||||
->will($this->returnValueMap([
|
||||
['administer node fields', TRUE],
|
||||
]));
|
||||
$this->member
|
||||
->expects($this->any())
|
||||
->method('id')
|
||||
->will($this->returnValue(2));
|
||||
|
||||
$storageType = $this->getMock(ConfigEntityTypeInterface::class);
|
||||
$storageType
|
||||
->expects($this->any())
|
||||
->method('getProvider')
|
||||
->will($this->returnValue('field'));
|
||||
$storageType
|
||||
->expects($this->any())
|
||||
->method('getConfigPrefix')
|
||||
->will($this->returnValue('field.storage'));
|
||||
|
||||
$entityType = $this->getMock(ConfigEntityTypeInterface::class);
|
||||
$entityType
|
||||
->expects($this->any())
|
||||
->method('getProvider')
|
||||
->will($this->returnValue('node'));
|
||||
$entityType
|
||||
->expects($this->any())
|
||||
->method('getConfigPrefix')
|
||||
->willReturn('node');
|
||||
|
||||
$this->moduleHandler = $this->getMock(ModuleHandlerInterface::class);
|
||||
$this->moduleHandler
|
||||
->expects($this->any())
|
||||
->method('getImplementations')
|
||||
->will($this->returnValue([]));
|
||||
$this->moduleHandler
|
||||
->expects($this->any())
|
||||
->method('invokeAll')
|
||||
->will($this->returnValue([]));
|
||||
|
||||
$storage_access_control_handler = new FieldStorageConfigAccessControlHandler($storageType);
|
||||
$storage_access_control_handler->setModuleHandler($this->moduleHandler);
|
||||
|
||||
$entityManager = $this->getMock(EntityManagerInterface::class);
|
||||
$entityManager
|
||||
->expects($this->any())
|
||||
->method('getDefinition')
|
||||
->willReturnMap([
|
||||
['field_storage_config', TRUE, $storageType],
|
||||
['node', TRUE, $entityType],
|
||||
]);
|
||||
$entityManager
|
||||
->expects($this->any())
|
||||
->method('getStorage')
|
||||
->willReturnMap([
|
||||
['field_storage_config', $this->getMock(EntityStorageInterface::class)],
|
||||
]);
|
||||
$entityManager
|
||||
->expects($this->any())
|
||||
->method('getAccessControlHandler')
|
||||
->willReturnMap([
|
||||
['field_storage_config', $storage_access_control_handler],
|
||||
]);
|
||||
|
||||
$container = new Container();
|
||||
$container->set('entity.manager', $entityManager);
|
||||
$container->set('uuid', $this->getMock(UuidInterface::class));
|
||||
$container->set('cache_contexts_manager', $this->prophesize(CacheContextsManager::class));
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
$this->fieldStorage = new FieldStorageConfig([
|
||||
'field_name' => 'test_field',
|
||||
'entity_type' => 'node',
|
||||
'type' => 'boolean',
|
||||
'id' => 'node.test_field',
|
||||
'uuid' => '6f2f259a-f3c7-42ea-bdd5-111ad1f85ed1',
|
||||
]);
|
||||
|
||||
$this->entity = $this->fieldStorage;
|
||||
$this->accessControlHandler = $storage_access_control_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert method to verify the access by operations.
|
||||
*
|
||||
* @param array $allow_operations
|
||||
* A list of allowed operations.
|
||||
* @param \Drupal\Core\Session\AccountInterface $user
|
||||
* The account to use for get access.
|
||||
*/
|
||||
public function assertAllowOperations(array $allow_operations, AccountInterface $user) {
|
||||
foreach (['view', 'update', 'delete'] as $operation) {
|
||||
$expected = in_array($operation, $allow_operations);
|
||||
$actual = $this->accessControlHandler->access($this->entity, $operation, $user);
|
||||
$this->assertSame($expected, $actual, "Access problem with '$operation' operation.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures field storage config access is working properly.
|
||||
*/
|
||||
public function testAccess() {
|
||||
$this->assertAllowOperations([], $this->anon);
|
||||
$this->assertAllowOperations(['view', 'update', 'delete'], $this->member);
|
||||
|
||||
$this->fieldStorage->setLocked(TRUE)->save();
|
||||
// Unfortunately, EntityAccessControlHandler has a static cache, which we
|
||||
// therefore must reset manually.
|
||||
$this->accessControlHandler->resetCache();
|
||||
|
||||
$this->assertAllowOperations([], $this->anon);
|
||||
$this->assertAllowOperations(['view', 'update'], $this->member);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\FieldStorageConfig;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\FieldStorageConfig\FieldStorageConfigResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class FieldStorageConfigHalJsonAnonTest extends FieldStorageConfigResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\FieldStorageConfig;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\FieldStorageConfig\FieldStorageConfigResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class FieldStorageConfigHalJsonBasicAuthTest extends FieldStorageConfigResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal', 'basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\hal\Functional\EntityResource\FieldStorageConfig;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\FieldStorageConfig\FieldStorageConfigResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class FieldStorageConfigHalJsonCookieTest extends FieldStorageConfigResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\FieldStorageConfig;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class FieldStorageConfigJsonAnonTest extends FieldStorageConfigResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\FieldStorageConfig;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class FieldStorageConfigJsonBasicAuthTest extends FieldStorageConfigResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\FieldStorageConfig;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class FieldStorageConfigJsonCookieTest extends FieldStorageConfigResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\FieldStorageConfig;
|
||||
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
|
||||
abstract class FieldStorageConfigResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['node'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'field_storage_config';
|
||||
|
||||
/**
|
||||
* @var \Drupal\field\FieldConfigStorage
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
$this->grantPermissionsToTestedRole(['administer node fields']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => 'true_llama',
|
||||
'entity_type' => 'node',
|
||||
'type' => 'boolean',
|
||||
]);
|
||||
$field_storage->save();
|
||||
return $field_storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'cardinality' => 1,
|
||||
'custom_storage' => FALSE,
|
||||
'dependencies' => [
|
||||
'module' => ['node'],
|
||||
],
|
||||
'entity_type' => 'node',
|
||||
'field_name' => 'true_llama',
|
||||
'id' => 'node.true_llama',
|
||||
'indexes' => [],
|
||||
'langcode' => 'en',
|
||||
'locked' => FALSE,
|
||||
'module' => 'core',
|
||||
'persist_with_no_fields' => FALSE,
|
||||
'settings' => [],
|
||||
'status' => TRUE,
|
||||
'translatable' => TRUE,
|
||||
'type' => 'boolean',
|
||||
'uuid' => $this->entity->uuid(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
// @todo Update in https://www.drupal.org/node/2300677.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedUnauthorizedAccessMessage($method) {
|
||||
if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) {
|
||||
return parent::getExpectedUnauthorizedAccessMessage($method);
|
||||
}
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
return "The 'administer node fields' permission is required.";
|
||||
|
||||
default:
|
||||
return parent::getExpectedUnauthorizedAccessMessage($method);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedCacheContexts() {
|
||||
return [
|
||||
'user.permissions',
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue