Issue #2721595 by Wim Leers, dawehner: Simplify REST configuration
parent
df1fe18178
commit
3a13f94634
|
@ -7,25 +7,14 @@ dependencies:
|
|||
- node
|
||||
id: entity.node
|
||||
plugin_id: 'entity:node'
|
||||
granularity: method
|
||||
granularity: resource
|
||||
configuration:
|
||||
GET:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
POST:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
PATCH:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
DELETE:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
methods:
|
||||
- GET
|
||||
- POST
|
||||
- PATCH
|
||||
- DELETE
|
||||
formats:
|
||||
- hal_json
|
||||
authentication:
|
||||
- basic_auth
|
||||
|
|
|
@ -8,7 +8,6 @@ rest.settings:
|
|||
label: 'Domain of the relation'
|
||||
|
||||
# Method-level granularity of REST resource configuration.
|
||||
# @todo Add resource-level granularity in https://www.drupal.org/node/2721595.
|
||||
rest_resource.method:
|
||||
type: mapping
|
||||
mapping:
|
||||
|
@ -25,6 +24,29 @@ rest_resource.method:
|
|||
type: rest_request
|
||||
label: 'DELETE method settings'
|
||||
|
||||
# Resource-level granularity of REST resource configuration.
|
||||
rest_resource.resource:
|
||||
type: mapping
|
||||
mapping:
|
||||
methods:
|
||||
type: sequence
|
||||
label: 'Supported methods'
|
||||
sequence:
|
||||
type: string
|
||||
label: 'HTTP method'
|
||||
formats:
|
||||
type: sequence
|
||||
label: 'Supported formats'
|
||||
sequence:
|
||||
type: string
|
||||
label: 'Format'
|
||||
authentication:
|
||||
type: sequence
|
||||
label: 'Supported authentication providers'
|
||||
sequence:
|
||||
type: string
|
||||
label: 'Authentication provider'
|
||||
|
||||
rest_request:
|
||||
type: mapping
|
||||
mapping:
|
||||
|
|
|
@ -30,6 +30,8 @@ function rest_requirements($phase) {
|
|||
|
||||
/**
|
||||
* Install the REST config entity type and fix old settings-based config.
|
||||
*
|
||||
* @see rest_post_update_create_rest_resource_config_entities()
|
||||
*/
|
||||
function rest_update_8201() {
|
||||
\Drupal::entityDefinitionUpdateManager()->installEntityType(\Drupal::entityTypeManager()->getDefinition('rest_resource_config'));
|
||||
|
|
|
@ -16,11 +16,8 @@ use Drupal\rest\RestResourceConfigInterface;
|
|||
/**
|
||||
* Create REST resource configuration entities.
|
||||
*
|
||||
* @todo https://www.drupal.org/node/2721595 Automatically upgrade those REST
|
||||
* resource config entities that have the same formats/auth mechanisms for all
|
||||
* methods to "granular: resource".
|
||||
*
|
||||
* @see rest_update_8201()
|
||||
* @see https://www.drupal.org/node/2308745
|
||||
*/
|
||||
function rest_post_update_create_rest_resource_config_entities() {
|
||||
$resources = \Drupal::state()->get('rest_update_8201_resources', []);
|
||||
|
@ -34,6 +31,43 @@ function rest_post_update_create_rest_resource_config_entities() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplify method-granularity REST resource config to resource-granularity.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2721595
|
||||
*/
|
||||
function rest_post_update_resource_granularity() {
|
||||
/** @var \Drupal\rest\RestResourceConfigInterface[] $resource_config_entities */
|
||||
$resource_config_entities = RestResourceConfig::loadMultiple();
|
||||
|
||||
foreach ($resource_config_entities as $resource_config_entity) {
|
||||
if ($resource_config_entity->get('granularity') === RestResourceConfigInterface::METHOD_GRANULARITY) {
|
||||
$configuration = $resource_config_entity->get('configuration');
|
||||
|
||||
$format_and_auth_configuration = [];
|
||||
foreach (array_keys($configuration) as $method) {
|
||||
$format_and_auth_configuration['format'][$method] = implode(',', $configuration[$method]['supported_formats']);
|
||||
$format_and_auth_configuration['auth'][$method] = implode(',', $configuration[$method]['supported_auth']);
|
||||
}
|
||||
|
||||
// If each method has the same formats and the same authentication
|
||||
// providers configured, convert it to 'granularity: resource', which has
|
||||
// a simpler/less verbose configuration.
|
||||
if (count(array_unique($format_and_auth_configuration['format'])) === 1 && count(array_unique($format_and_auth_configuration['auth'])) === 1) {
|
||||
$first_method = array_keys($configuration)[0];
|
||||
$resource_config_entity->set('configuration', [
|
||||
'methods' => array_keys($configuration),
|
||||
'formats' => $configuration[$first_method]['supported_formats'],
|
||||
'authentication' => $configuration[$first_method]['supported_auth']
|
||||
]);
|
||||
$resource_config_entity->set('granularity', RestResourceConfigInterface::RESOURCE_GRANULARITY);
|
||||
$resource_config_entity->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup updates-8.1.x-to-8.2.x".
|
||||
*/
|
||||
|
|
|
@ -61,31 +61,25 @@ class ConfigDependencies implements ContainerInjectionInterface {
|
|||
*/
|
||||
public function calculateDependencies(RestResourceConfigInterface $rest_config) {
|
||||
$granularity = $rest_config->get('granularity');
|
||||
if ($granularity === RestResourceConfigInterface::METHOD_GRANULARITY) {
|
||||
return $this->calculateDependenciesForMethodGranularity($rest_config);
|
||||
}
|
||||
else {
|
||||
throw new \InvalidArgumentException("A different granularity then 'method' is not supported yet.");
|
||||
// @todo Add resource-level granularity support in https://www.drupal.org/node/2721595.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates dependencies of a specific rest resource configuration.
|
||||
*
|
||||
* @param \Drupal\rest\RestResourceConfigInterface $rest_config
|
||||
* The rest configuration.
|
||||
*
|
||||
* @return string[][]
|
||||
* Dependencies keyed by dependency type.
|
||||
*
|
||||
* @see \Drupal\Core\Config\Entity\ConfigEntityInterface::calculateDependencies()
|
||||
*/
|
||||
protected function calculateDependenciesForMethodGranularity(RestResourceConfigInterface $rest_config) {
|
||||
// Dependency calculation is the same for either granularity, the most
|
||||
// notable difference is that for the 'resource' granularity, the same
|
||||
// authentication providers and formats are supported for every method.
|
||||
switch ($granularity) {
|
||||
case RestResourceConfigInterface::METHOD_GRANULARITY:
|
||||
$methods = $rest_config->getMethods();
|
||||
break;
|
||||
case RestResourceConfigInterface::RESOURCE_GRANULARITY:
|
||||
$methods = array_slice($rest_config->getMethods(), 0, 1);
|
||||
break;
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid granularity specified.');
|
||||
}
|
||||
|
||||
// The dependency lists for authentication providers and formats
|
||||
// generated on container build.
|
||||
$dependencies = [];
|
||||
foreach (array_keys($rest_config->get('configuration')) as $request_method) {
|
||||
foreach ($methods as $request_method) {
|
||||
// Add dependencies based on the supported authentication providers.
|
||||
foreach ($rest_config->getAuthenticationProviders($request_method) as $auth) {
|
||||
if (isset($this->authProviders[$auth])) {
|
||||
|
@ -102,6 +96,10 @@ class ConfigDependencies implements ContainerInjectionInterface {
|
|||
}
|
||||
}
|
||||
|
||||
if (isset($dependencies['module'])) {
|
||||
sort($dependencies['module']);
|
||||
}
|
||||
|
||||
return $dependencies;
|
||||
}
|
||||
|
||||
|
@ -121,12 +119,13 @@ class ConfigDependencies implements ContainerInjectionInterface {
|
|||
*/
|
||||
public function onDependencyRemoval(RestResourceConfigInterface $rest_config, array $dependencies) {
|
||||
$granularity = $rest_config->get('granularity');
|
||||
if ($granularity === RestResourceConfigInterface::METHOD_GRANULARITY) {
|
||||
return $this->onDependencyRemovalForMethodGranularity($rest_config, $dependencies);
|
||||
}
|
||||
else {
|
||||
throw new \InvalidArgumentException("A different granularity then 'method' is not supported yet.");
|
||||
// @todo Add resource-level granularity support in https://www.drupal.org/node/2721595.
|
||||
switch ($granularity) {
|
||||
case RestResourceConfigInterface::METHOD_GRANULARITY:
|
||||
return $this->onDependencyRemovalForMethodGranularity($rest_config, $dependencies);
|
||||
case RestResourceConfigInterface::RESOURCE_GRANULARITY:
|
||||
return $this->onDependencyRemovalForResourceGranularity($rest_config, $dependencies);
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid granularity specified.');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,7 +182,71 @@ class ConfigDependencies implements ContainerInjectionInterface {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!empty($configuration_before != $configuration)) {
|
||||
if ($configuration_before != $configuration && !empty($configuration)) {
|
||||
$rest_config->set('configuration', $configuration);
|
||||
// Only mark the dependencies problems as fixed if there is any
|
||||
// configuration left.
|
||||
$changed = TRUE;
|
||||
}
|
||||
}
|
||||
// If the dependency problems are not marked as fixed at this point they
|
||||
// should be related to the resource plugin and the config entity should
|
||||
// be deleted.
|
||||
return $changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs the entity that entities it depends on will be deleted.
|
||||
*
|
||||
* @param \Drupal\rest\RestResourceConfigInterface $rest_config
|
||||
* The rest configuration.
|
||||
* @param array $dependencies
|
||||
* An array of dependencies that will be deleted keyed by dependency type.
|
||||
* Dependency types are, for example, entity, module and theme.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the entity has been changed as a result, FALSE if not.
|
||||
*/
|
||||
public function onDependencyRemovalForResourceGranularity(RestResourceConfigInterface $rest_config, array $dependencies) {
|
||||
$changed = FALSE;
|
||||
// Only module-related dependencies can be fixed. All other types of
|
||||
// dependencies cannot, because they were not generated based on supported
|
||||
// authentication providers or formats.
|
||||
if (isset($dependencies['module'])) {
|
||||
// Try to fix dependencies.
|
||||
$removed_auth = array_keys(array_intersect($this->authProviders, $dependencies['module']));
|
||||
$removed_formats = array_keys(array_intersect($this->formatProviders, $dependencies['module']));
|
||||
$configuration_before = $configuration = $rest_config->get('configuration');
|
||||
if (!empty($removed_auth) || !empty($removed_formats)) {
|
||||
// Try to fix dependency problems by removing affected
|
||||
// authentication providers and formats.
|
||||
foreach ($removed_formats as $format) {
|
||||
if (in_array($format, $rest_config->getFormats('GET'))) {
|
||||
$configuration['formats'] = array_diff($configuration['formats'], $removed_formats);
|
||||
}
|
||||
}
|
||||
foreach ($removed_auth as $auth) {
|
||||
if (in_array($auth, $rest_config->getAuthenticationProviders('GET'))) {
|
||||
$configuration['authentication'] = array_diff($configuration['authentication'], $removed_auth);
|
||||
}
|
||||
}
|
||||
if (empty($configuration['authentication'])) {
|
||||
// Remove the key if there are no more authentication providers
|
||||
// supported.
|
||||
unset($configuration['authentication']);
|
||||
}
|
||||
if (empty($configuration['formats'])) {
|
||||
// Remove the key if there are no more formats supported.
|
||||
unset($configuration['formats']);
|
||||
}
|
||||
if (empty($configuration['authentication']) || empty($configuration['formats'])) {
|
||||
// If there no longer are any supported authentication providers or
|
||||
// formats, this REST resource can no longer function, and so we
|
||||
// cannot fix this config entity to keep it working.
|
||||
$configuration = [];
|
||||
}
|
||||
}
|
||||
if ($configuration_before != $configuration && !empty($configuration)) {
|
||||
$rest_config->set('configuration', $configuration);
|
||||
// Only mark the dependencies problems as fixed if there is any
|
||||
// configuration left.
|
||||
|
|
|
@ -45,7 +45,9 @@ class RestResourceConfig extends ConfigEntityBase implements RestResourceConfigI
|
|||
/**
|
||||
* The REST resource configuration granularity.
|
||||
*
|
||||
* @todo Currently only 'method', but https://www.drupal.org/node/2721595 will add 'resource'
|
||||
* Currently either:
|
||||
* - \Drupal\rest\RestResourceConfigInterface::METHOD_GRANULARITY
|
||||
* - \Drupal\rest\RestResourceConfigInterface::RESOURCE_GRANULARITY
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
@ -112,12 +114,13 @@ class RestResourceConfig extends ConfigEntityBase implements RestResourceConfigI
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMethods() {
|
||||
if ($this->granularity === RestResourceConfigInterface::METHOD_GRANULARITY) {
|
||||
return $this->getMethodsForMethodGranularity();
|
||||
}
|
||||
else {
|
||||
throw new \InvalidArgumentException("A different granularity then 'method' is not supported yet.");
|
||||
// @todo Add resource-level granularity support in https://www.drupal.org/node/2721595.
|
||||
switch ($this->granularity) {
|
||||
case RestResourceConfigInterface::METHOD_GRANULARITY:
|
||||
return $this->getMethodsForMethodGranularity();
|
||||
case RestResourceConfigInterface::RESOURCE_GRANULARITY:
|
||||
return $this->configuration['methods'];
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid granularity specified.');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,12 +139,13 @@ class RestResourceConfig extends ConfigEntityBase implements RestResourceConfigI
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAuthenticationProviders($method) {
|
||||
if ($this->granularity === RestResourceConfigInterface::METHOD_GRANULARITY) {
|
||||
return $this->getAuthenticationProvidersForMethodGranularity($method);
|
||||
}
|
||||
else {
|
||||
throw new \InvalidArgumentException("A different granularity then 'method' is not supported yet.");
|
||||
// @todo Add resource-level granularity support in https://www.drupal.org/node/2721595.
|
||||
switch ($this->granularity) {
|
||||
case RestResourceConfigInterface::METHOD_GRANULARITY:
|
||||
return $this->getAuthenticationProvidersForMethodGranularity($method);
|
||||
case RestResourceConfigInterface::RESOURCE_GRANULARITY:
|
||||
return $this->configuration['authentication'];
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid granularity specified.');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,12 +170,13 @@ class RestResourceConfig extends ConfigEntityBase implements RestResourceConfigI
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormats($method) {
|
||||
if ($this->granularity === RestResourceConfigInterface::METHOD_GRANULARITY) {
|
||||
return $this->getFormatsForMethodGranularity($method);
|
||||
}
|
||||
else {
|
||||
throw new \InvalidArgumentException("A different granularity then 'method' is not supported yet.");
|
||||
// @todo Add resource-level granularity support in https://www.drupal.org/node/2721595.
|
||||
switch ($this->granularity) {
|
||||
case RestResourceConfigInterface::METHOD_GRANULARITY:
|
||||
return $this->getFormatsForMethodGranularity($method);
|
||||
case RestResourceConfigInterface::RESOURCE_GRANULARITY:
|
||||
return $this->configuration['formats'];
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid granularity specified.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,11 @@ interface RestResourceConfigInterface extends ConfigEntityInterface, EntityWithP
|
|||
*/
|
||||
const METHOD_GRANULARITY = 'method';
|
||||
|
||||
/**
|
||||
* Granularity value for per-resource configuration.
|
||||
*/
|
||||
const RESOURCE_GRANULARITY = 'resource';
|
||||
|
||||
/**
|
||||
* Retrieves the REST resource plugin.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\rest\Tests\Update;
|
||||
|
||||
use Drupal\system\Tests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests method-granularity REST config is simplified to resource-granularity.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2721595
|
||||
* @see rest_post_update_resource_granularity()
|
||||
*
|
||||
* @group rest
|
||||
*/
|
||||
class ResourceGranularityUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['rest', 'serialization'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
|
||||
__DIR__ . '/../../../../rest/tests/fixtures/update/drupal-8.rest-rest_post_update_resource_granularity.php',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rest_post_update_simplify_resource_granularity().
|
||||
*/
|
||||
public function testMethodGranularityConvertedToResourceGranularity() {
|
||||
/** @var \Drupal\Core\Entity\EntityStorageInterface $resource_config_storage */
|
||||
$resource_config_storage = $this->container->get('entity_type.manager')->getStorage('rest_resource_config');
|
||||
|
||||
// Make sure we have the expected values before the update.
|
||||
$resource_config_entities = $resource_config_storage->loadMultiple();
|
||||
$this->assertIdentical(['entity.comment', 'entity.node', 'entity.user'], array_keys($resource_config_entities));
|
||||
$this->assertIdentical('method', $resource_config_entities['entity.node']->get('granularity'));
|
||||
$this->assertIdentical('method', $resource_config_entities['entity.comment']->get('granularity'));
|
||||
$this->assertIdentical('method', $resource_config_entities['entity.user']->get('granularity'));
|
||||
|
||||
// Read the existing 'entity:comment' and 'entity:user' resource
|
||||
// configuration so we can verify it after the update.
|
||||
$comment_resource_configuration = $resource_config_entities['entity.comment']->get('configuration');
|
||||
$user_resource_configuration = $resource_config_entities['entity.user']->get('configuration');
|
||||
|
||||
$this->runUpdates();
|
||||
|
||||
// Make sure we have the expected values after the update.
|
||||
$resource_config_entities = $resource_config_storage->loadMultiple();
|
||||
$this->assertIdentical(['entity.comment', 'entity.node', 'entity.user'], array_keys($resource_config_entities));
|
||||
// 'entity:node' should be updated.
|
||||
$this->assertIdentical('resource', $resource_config_entities['entity.node']->get('granularity'));
|
||||
$this->assertidentical($resource_config_entities['entity.node']->get('configuration'), [
|
||||
'methods' => ['GET', 'POST', 'PATCH', 'DELETE'],
|
||||
'formats' => ['hal_json'],
|
||||
'authentication' => ['basic_auth'],
|
||||
]);
|
||||
// 'entity:comment' should be unchanged.
|
||||
$this->assertIdentical('method', $resource_config_entities['entity.comment']->get('granularity'));
|
||||
$this->assertIdentical($comment_resource_configuration, $resource_config_entities['entity.comment']->get('configuration'));
|
||||
// 'entity:user' should be unchanged.
|
||||
$this->assertIdentical('method', $resource_config_entities['entity.user']->get('granularity'));
|
||||
$this->assertIdentical($user_resource_configuration, $resource_config_entities['entity.user']->get('configuration'));
|
||||
}
|
||||
|
||||
}
|
|
@ -9,6 +9,8 @@ use Drupal\system\Tests\Update\UpdatePathTestBase;
|
|||
* Tests that rest.settings is converted to rest_resource_config entities.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2308745
|
||||
* @see rest_update_8201()
|
||||
* @see rest_post_update_create_rest_resource_config_entities()
|
||||
*
|
||||
* @group rest
|
||||
*/
|
||||
|
@ -43,10 +45,6 @@ class RestConfigurationEntitiesUpdateTest extends UpdatePathTestBase {
|
|||
$resource_config_entities = $resource_config_storage->loadMultiple();
|
||||
$this->assertIdentical([], array_keys($resource_config_entities));
|
||||
|
||||
// Read the existing 'entity:node' resource configuration so we can verify
|
||||
// it after the update.
|
||||
$node_configuration = $rest_settings->getRawData()['resources']['entity:node'];
|
||||
|
||||
$this->runUpdates();
|
||||
|
||||
// Make sure we have the expected values after the update.
|
||||
|
@ -55,8 +53,12 @@ class RestConfigurationEntitiesUpdateTest extends UpdatePathTestBase {
|
|||
$resource_config_entities = $resource_config_storage->loadMultiple();
|
||||
$this->assertIdentical(['entity.node'], array_keys($resource_config_entities));
|
||||
$node_resource_config_entity = $resource_config_entities['entity.node'];
|
||||
$this->assertIdentical(RestResourceConfigInterface::METHOD_GRANULARITY, $node_resource_config_entity->get('granularity'));
|
||||
$this->assertIdentical($node_configuration, $node_resource_config_entity->get('configuration'));
|
||||
$this->assertIdentical(RestResourceConfigInterface::RESOURCE_GRANULARITY, $node_resource_config_entity->get('granularity'));
|
||||
$this->assertIdentical([
|
||||
'methods' => ['GET'],
|
||||
'formats' => ['json'],
|
||||
'authentication' => ['basic_auth'],
|
||||
], $node_resource_config_entity->get('configuration'));
|
||||
$this->assertIdentical(['module' => ['basic_auth', 'node', 'serialization']], $node_resource_config_entity->getDependencies());
|
||||
}
|
||||
|
||||
|
|
BIN
core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_post_update_resource_granularity.php
vendored
Normal file
BIN
core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_post_update_resource_granularity.php
vendored
Normal file
Binary file not shown.
32
core/modules/rest/tests/fixtures/update/rest.resource.entity.comment_2721595.yml
vendored
Normal file
32
core/modules/rest/tests/fixtures/update/rest.resource.entity.comment_2721595.yml
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
id: entity.comment
|
||||
plugin_id: 'entity:comment'
|
||||
granularity: method
|
||||
configuration:
|
||||
GET:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
# This resource has a method-specific format.
|
||||
# @see \Drupal\rest\Tests\Update\ResourceGranularityUpdateTest
|
||||
- xml
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
POST:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
PATCH:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
DELETE:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
dependencies:
|
||||
module:
|
||||
- node
|
||||
- basic_auth
|
||||
- hal
|
29
core/modules/rest/tests/fixtures/update/rest.resource.entity.node_2721595.yml
vendored
Normal file
29
core/modules/rest/tests/fixtures/update/rest.resource.entity.node_2721595.yml
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
id: entity.node
|
||||
plugin_id: 'entity:node'
|
||||
granularity: method
|
||||
configuration:
|
||||
GET:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
POST:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
PATCH:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
DELETE:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
dependencies:
|
||||
module:
|
||||
- node
|
||||
- basic_auth
|
||||
- hal
|
32
core/modules/rest/tests/fixtures/update/rest.resource.entity.user_2721595.yml
vendored
Normal file
32
core/modules/rest/tests/fixtures/update/rest.resource.entity.user_2721595.yml
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
id: entity.user
|
||||
plugin_id: 'entity:user'
|
||||
granularity: method
|
||||
configuration:
|
||||
GET:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
# This resource has a method-specific authentication.
|
||||
# @see \Drupal\rest\Tests\Update\ResourceGranularityUpdateTest
|
||||
- oauth
|
||||
POST:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
PATCH:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
DELETE:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
dependencies:
|
||||
module:
|
||||
- node
|
||||
- basic_auth
|
||||
- hal
|
|
@ -21,72 +21,78 @@ class ConfigDependenciesTest extends KernelTestBase {
|
|||
|
||||
/**
|
||||
* @covers ::calculateDependencies
|
||||
* @covers ::calculateDependenciesForMethodGranularity
|
||||
*
|
||||
* @dataProvider providerBasicDependencies
|
||||
*/
|
||||
public function testCalculateDependencies() {
|
||||
public function testCalculateDependencies(array $configuration) {
|
||||
$config_dependencies = new ConfigDependencies(['hal_json' => 'hal', 'json' => 'serialization'], ['basic_auth' => 'basic_auth']);
|
||||
|
||||
$rest_config = RestResourceConfig::create([
|
||||
'plugin_id' => 'entity:entity_test',
|
||||
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
|
||||
'configuration' => [
|
||||
'GET' => [
|
||||
'supported_auth' => ['cookie'],
|
||||
'supported_formats' => ['json'],
|
||||
],
|
||||
'POST' => [
|
||||
'supported_auth' => ['basic_auth'],
|
||||
'supported_formats' => ['hal_json'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$rest_config = RestResourceConfig::create($configuration);
|
||||
|
||||
$result = $config_dependencies->calculateDependencies($rest_config);
|
||||
$this->assertEquals(['module' => [
|
||||
'serialization', 'basic_auth', 'hal',
|
||||
'basic_auth', 'hal', 'serialization',
|
||||
]], $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::onDependencyRemoval
|
||||
* @covers ::calculateDependenciesForMethodGranularity
|
||||
* @covers ::onDependencyRemovalForMethodGranularity
|
||||
* @covers ::onDependencyRemovalForResourceGranularity
|
||||
*
|
||||
* @dataProvider providerBasicDependencies
|
||||
*/
|
||||
public function testOnDependencyRemovalRemoveUnrelatedDependency() {
|
||||
public function testOnDependencyRemovalRemoveUnrelatedDependency(array $configuration) {
|
||||
$config_dependencies = new ConfigDependencies(['hal_json' => 'hal', 'json' => 'serialization'], ['basic_auth' => 'basic_auth']);
|
||||
|
||||
$rest_config = RestResourceConfig::create([
|
||||
'plugin_id' => 'entity:entity_test',
|
||||
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
|
||||
'configuration' => [
|
||||
'GET' => [
|
||||
'supported_auth' => ['cookie'],
|
||||
'supported_formats' => ['json'],
|
||||
],
|
||||
'POST' => [
|
||||
'supported_auth' => ['basic_auth'],
|
||||
'supported_formats' => ['hal_json'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$rest_config = RestResourceConfig::create($configuration);
|
||||
|
||||
$this->assertFalse($config_dependencies->onDependencyRemoval($rest_config, ['module' => ['node']]));
|
||||
$this->assertEquals([
|
||||
'GET' => [
|
||||
'supported_auth' => ['cookie'],
|
||||
'supported_formats' => ['json'],
|
||||
$this->assertEquals($configuration['configuration'], $rest_config->get('configuration'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* An array with numerical keys:
|
||||
* 0. The original REST resource configuration.
|
||||
*/
|
||||
public function providerBasicDependencies() {
|
||||
return [
|
||||
'method' => [
|
||||
[
|
||||
'plugin_id' => 'entity:entity_test',
|
||||
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
|
||||
'configuration' => [
|
||||
'GET' => [
|
||||
'supported_auth' => ['cookie'],
|
||||
'supported_formats' => ['json'],
|
||||
],
|
||||
'POST' => [
|
||||
'supported_auth' => ['basic_auth'],
|
||||
'supported_formats' => ['hal_json'],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'POST' => [
|
||||
'supported_auth' => ['basic_auth'],
|
||||
'supported_formats' => ['hal_json'],
|
||||
'resource' => [
|
||||
[
|
||||
'plugin_id' => 'entity:entity_test',
|
||||
'granularity' => RestResourceConfigInterface::RESOURCE_GRANULARITY,
|
||||
'configuration' => [
|
||||
'methods' => ['GET', 'POST'],
|
||||
'formats' => ['json', 'hal_json'],
|
||||
'authentication' => ['cookie', 'basic_auth'],
|
||||
],
|
||||
],
|
||||
],
|
||||
], $rest_config->get('configuration'));
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::onDependencyRemoval
|
||||
* @covers ::calculateDependenciesForMethodGranularity
|
||||
* @covers ::onDependencyRemovalForMethodGranularity
|
||||
*/
|
||||
public function testOnDependencyRemovalRemoveFormat() {
|
||||
public function testOnDependencyRemovalRemoveFormatForMethodGranularity() {
|
||||
$config_dependencies = new ConfigDependencies(['hal_json' => 'hal', 'json' => 'serialization'], ['basic_auth' => 'basic_auth']);
|
||||
|
||||
$rest_config = RestResourceConfig::create([
|
||||
|
@ -120,7 +126,7 @@ class ConfigDependenciesTest extends KernelTestBase {
|
|||
|
||||
/**
|
||||
* @covers ::onDependencyRemoval
|
||||
* @covers ::calculateDependenciesForMethodGranularity
|
||||
* @covers ::onDependencyRemovalForMethodGranularity
|
||||
*/
|
||||
public function testOnDependencyRemovalRemoveAuth() {
|
||||
$config_dependencies = new ConfigDependencies(['hal_json' => 'hal', 'json' => 'serialization'], ['basic_auth' => 'basic_auth']);
|
||||
|
@ -156,7 +162,7 @@ class ConfigDependenciesTest extends KernelTestBase {
|
|||
|
||||
/**
|
||||
* @covers ::onDependencyRemoval
|
||||
* @covers ::calculateDependenciesForMethodGranularity
|
||||
* @covers ::onDependencyRemovalForMethodGranularity
|
||||
*/
|
||||
public function testOnDependencyRemovalRemoveAuthAndFormats() {
|
||||
$config_dependencies = new ConfigDependencies(['hal_json' => 'hal', 'json' => 'serialization'], ['basic_auth' => 'basic_auth']);
|
||||
|
@ -189,4 +195,95 @@ class ConfigDependenciesTest extends KernelTestBase {
|
|||
], $rest_config->get('configuration'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::onDependencyRemoval
|
||||
* @covers ::onDependencyRemovalForResourceGranularity
|
||||
*
|
||||
* @dataProvider providerOnDependencyRemovalForResourceGranularity
|
||||
*/
|
||||
public function testOnDependencyRemovalForResourceGranularity(array $configuration, $module, $expected_configuration) {
|
||||
assert('is_string($module)');
|
||||
assert('$expected_configuration === FALSE || is_array($expected_configuration)');
|
||||
$config_dependencies = new ConfigDependencies(['hal_json' => 'hal', 'json' => 'serialization'], ['basic_auth' => 'basic_auth']);
|
||||
|
||||
$rest_config = RestResourceConfig::create($configuration);
|
||||
|
||||
$this->assertSame(!empty($expected_configuration), $config_dependencies->onDependencyRemoval($rest_config, ['module' => [$module]]));
|
||||
if (!empty($expected_configuration)) {
|
||||
$this->assertEquals($expected_configuration, $rest_config->get('configuration'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* An array with numerical keys:
|
||||
* 0. The original REST resource configuration.
|
||||
* 1. The module to uninstall (the dependency that is about to be removed).
|
||||
* 2. The expected configuration after uninstalling this module.
|
||||
*/
|
||||
public function providerOnDependencyRemovalForResourceGranularity() {
|
||||
return [
|
||||
'resource with multiple formats' => [
|
||||
[
|
||||
'plugin_id' => 'entity:entity_test',
|
||||
'granularity' => RestResourceConfigInterface::RESOURCE_GRANULARITY,
|
||||
'configuration' => [
|
||||
'methods' => ['GET', 'POST'],
|
||||
'formats' => ['json', 'hal_json'],
|
||||
'authentication' => ['cookie', 'basic_auth'],
|
||||
],
|
||||
],
|
||||
'hal',
|
||||
[
|
||||
'methods' => ['GET', 'POST'],
|
||||
'formats' => ['json'],
|
||||
'authentication' => ['cookie', 'basic_auth'],
|
||||
]
|
||||
],
|
||||
'resource with only HAL+JSON format' => [
|
||||
[
|
||||
'plugin_id' => 'entity:entity_test',
|
||||
'granularity' => RestResourceConfigInterface::RESOURCE_GRANULARITY,
|
||||
'configuration' => [
|
||||
'methods' => ['GET', 'POST'],
|
||||
'formats' => ['hal_json'],
|
||||
'authentication' => ['cookie', 'basic_auth'],
|
||||
],
|
||||
],
|
||||
'hal',
|
||||
FALSE
|
||||
],
|
||||
'resource with multiple authentication providers' => [
|
||||
[
|
||||
'plugin_id' => 'entity:entity_test',
|
||||
'granularity' => RestResourceConfigInterface::RESOURCE_GRANULARITY,
|
||||
'configuration' => [
|
||||
'methods' => ['GET', 'POST'],
|
||||
'formats' => ['json', 'hal_json'],
|
||||
'authentication' => ['cookie', 'basic_auth'],
|
||||
],
|
||||
],
|
||||
'basic_auth',
|
||||
[
|
||||
'methods' => ['GET', 'POST'],
|
||||
'formats' => ['json', 'hal_json'],
|
||||
'authentication' => ['cookie'],
|
||||
]
|
||||
],
|
||||
'resource with only basic_auth authentication' => [
|
||||
[
|
||||
'plugin_id' => 'entity:entity_test',
|
||||
'granularity' => RestResourceConfigInterface::RESOURCE_GRANULARITY,
|
||||
'configuration' => [
|
||||
'methods' => ['GET', 'POST'],
|
||||
'formats' => ['json', 'hal_json'],
|
||||
'authentication' => ['basic_auth'],
|
||||
],
|
||||
],
|
||||
'basic_auth',
|
||||
FALSE,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -53,13 +53,18 @@ class ResponseGeneratorTest extends RESTTestBase {
|
|||
$this->assertEqual('text/html; charset=UTF-8', $this->drupalGetHeader('Content-Type'));
|
||||
$this->assertEqual($expectedGeneratorHeader, $this->drupalGetHeader('X-Generator'));
|
||||
|
||||
// Enable rest API for nodes
|
||||
$this->enableService('entity:node', 'GET', 'json');
|
||||
// Enable cookie-based authentication for the entity:node REST resource.
|
||||
/** @var \Drupal\rest\RestResourceConfigInterface $resource_config */
|
||||
$resource_config = $this->resourceConfigStorage->load('entity.node');
|
||||
$configuration = $resource_config->get('configuration');
|
||||
$configuration['authentication'][] = 'cookie';
|
||||
$resource_config->set('configuration', $configuration)->save();
|
||||
$this->rebuildCache();
|
||||
|
||||
// Tests to see if this also works for a non-html request
|
||||
$this->httpRequest($node->urlInfo()->setOption('query', ['_format' => 'json']), 'GET');
|
||||
$this->httpRequest($node->urlInfo()->setOption('query', ['_format' => 'hal_json']), 'GET');
|
||||
$this->assertResponse(200);
|
||||
$this->assertEqual('application/json', $this->drupalGetHeader('Content-Type'));
|
||||
$this->assertEqual('application/hal+json', $this->drupalGetHeader('Content-Type'));
|
||||
$this->assertEqual($expectedGeneratorHeader, $this->drupalGetHeader('X-Generator'));
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue