summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreffulgentsia2016-07-26 21:57:39 (GMT)
committereffulgentsia2016-07-26 21:57:39 (GMT)
commit3a13f94634574f27ffa3a2821da3b7746b1b7810 (patch)
tree18a08bcc5d7d28a931095217943f470913a2b897
parentdf1fe18178c456eb98f8072690d36e7a9600dc14 (diff)
Issue #2721595 by Wim Leers, dawehner: Simplify REST configuration
-rw-r--r--core/modules/rest/config/optional/rest.resource.entity.node.yml31
-rw-r--r--core/modules/rest/config/schema/rest.schema.yml24
-rw-r--r--core/modules/rest/rest.install2
-rw-r--r--core/modules/rest/rest.post_update.php42
-rw-r--r--core/modules/rest/src/Entity/ConfigDependencies.php117
-rw-r--r--core/modules/rest/src/Entity/RestResourceConfig.php43
-rw-r--r--core/modules/rest/src/RestResourceConfigInterface.php5
-rw-r--r--core/modules/rest/src/Tests/Update/ResourceGranularityUpdateTest.php71
-rw-r--r--core/modules/rest/src/Tests/Update/RestConfigurationEntitiesUpdateTest.php14
-rw-r--r--core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_post_update_resource_granularity.phpbin0 -> 5322 bytes
-rw-r--r--core/modules/rest/tests/fixtures/update/rest.resource.entity.comment_2721595.yml32
-rw-r--r--core/modules/rest/tests/fixtures/update/rest.resource.entity.node_2721595.yml29
-rw-r--r--core/modules/rest/tests/fixtures/update/rest.resource.entity.user_2721595.yml32
-rw-r--r--core/modules/rest/tests/src/Kernel/Entity/ConfigDependenciesTest.php187
-rw-r--r--core/modules/system/src/Tests/System/ResponseGeneratorTest.php13
15 files changed, 515 insertions, 127 deletions
diff --git a/core/modules/rest/config/optional/rest.resource.entity.node.yml b/core/modules/rest/config/optional/rest.resource.entity.node.yml
index caeed78..1388245 100644
--- a/core/modules/rest/config/optional/rest.resource.entity.node.yml
+++ b/core/modules/rest/config/optional/rest.resource.entity.node.yml
@@ -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
diff --git a/core/modules/rest/config/schema/rest.schema.yml b/core/modules/rest/config/schema/rest.schema.yml
index 41bc2bf..04f88a6 100644
--- a/core/modules/rest/config/schema/rest.schema.yml
+++ b/core/modules/rest/config/schema/rest.schema.yml
@@ -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:
diff --git a/core/modules/rest/rest.install b/core/modules/rest/rest.install
index 918b4f5..4cfaa11 100644
--- a/core/modules/rest/rest.install
+++ b/core/modules/rest/rest.install
@@ -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'));
diff --git a/core/modules/rest/rest.post_update.php b/core/modules/rest/rest.post_update.php
index 7068662..ecbc73c 100644
--- a/core/modules/rest/rest.post_update.php
+++ b/core/modules/rest/rest.post_update.php
@@ -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', []);
@@ -35,5 +32,42 @@ 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".
*/
diff --git a/core/modules/rest/src/Entity/ConfigDependencies.php b/core/modules/rest/src/Entity/ConfigDependencies.php
index 72fc8cc..3b39ccf 100644
--- a/core/modules/rest/src/Entity/ConfigDependencies.php
+++ b/core/modules/rest/src/Entity/ConfigDependencies.php
@@ -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.
+
+ // 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.');
}
- }
- /**
- * 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) {
// 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.
diff --git a/core/modules/rest/src/Entity/RestResourceConfig.php b/core/modules/rest/src/Entity/RestResourceConfig.php
index f2b8b0e..a31a1a4 100644
--- a/core/modules/rest/src/Entity/RestResourceConfig.php
+++ b/core/modules/rest/src/Entity/RestResourceConfig.php
@@ -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.');
}
}
diff --git a/core/modules/rest/src/RestResourceConfigInterface.php b/core/modules/rest/src/RestResourceConfigInterface.php
index 7f34bc4..601bb0e 100644
--- a/core/modules/rest/src/RestResourceConfigInterface.php
+++ b/core/modules/rest/src/RestResourceConfigInterface.php
@@ -16,6 +16,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.
*
* @return \Drupal\rest\Plugin\ResourceInterface
diff --git a/core/modules/rest/src/Tests/Update/ResourceGranularityUpdateTest.php b/core/modules/rest/src/Tests/Update/ResourceGranularityUpdateTest.php
new file mode 100644
index 0000000..c8cf89a
--- /dev/null
+++ b/core/modules/rest/src/Tests/Update/ResourceGranularityUpdateTest.php
@@ -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'));
+ }
+
+}
diff --git a/core/modules/rest/src/Tests/Update/RestConfigurationEntitiesUpdateTest.php b/core/modules/rest/src/Tests/Update/RestConfigurationEntitiesUpdateTest.php
index 9100f16..097da35 100644
--- a/core/modules/rest/src/Tests/Update/RestConfigurationEntitiesUpdateTest.php
+++ b/core/modules/rest/src/Tests/Update/RestConfigurationEntitiesUpdateTest.php
@@ -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());
}
diff --git a/core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_post_update_resource_granularity.php b/core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_post_update_resource_granularity.php
new file mode 100644
index 0000000..d657afc
--- /dev/null
+++ b/core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_post_update_resource_granularity.php
Binary files differ
diff --git a/core/modules/rest/tests/fixtures/update/rest.resource.entity.comment_2721595.yml b/core/modules/rest/tests/fixtures/update/rest.resource.entity.comment_2721595.yml
new file mode 100644
index 0000000..7e86bab
--- /dev/null
+++ b/core/modules/rest/tests/fixtures/update/rest.resource.entity.comment_2721595.yml
@@ -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
diff --git a/core/modules/rest/tests/fixtures/update/rest.resource.entity.node_2721595.yml b/core/modules/rest/tests/fixtures/update/rest.resource.entity.node_2721595.yml
new file mode 100644
index 0000000..0cf4d78
--- /dev/null
+++ b/core/modules/rest/tests/fixtures/update/rest.resource.entity.node_2721595.yml
@@ -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
diff --git a/core/modules/rest/tests/fixtures/update/rest.resource.entity.user_2721595.yml b/core/modules/rest/tests/fixtures/update/rest.resource.entity.user_2721595.yml
new file mode 100644
index 0000000..593a260
--- /dev/null
+++ b/core/modules/rest/tests/fixtures/update/rest.resource.entity.user_2721595.yml
@@ -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
diff --git a/core/modules/rest/tests/src/Kernel/Entity/ConfigDependenciesTest.php b/core/modules/rest/tests/src/Kernel/Entity/ConfigDependenciesTest.php
index b9a9062..86e80f2 100644
--- a/core/modules/rest/tests/src/Kernel/Entity/ConfigDependenciesTest.php
+++ b/core/modules/rest/tests/src/Kernel/Entity/ConfigDependenciesTest.php
@@ -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,
+ ],
+ ];
+ }
+
}
diff --git a/core/modules/system/src/Tests/System/ResponseGeneratorTest.php b/core/modules/system/src/Tests/System/ResponseGeneratorTest.php
index d0d22a2..d2f8f5f 100644
--- a/core/modules/system/src/Tests/System/ResponseGeneratorTest.php
+++ b/core/modules/system/src/Tests/System/ResponseGeneratorTest.php
@@ -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'));
}