diff --git a/core/modules/rest/src/Entity/RestEndpoint.php b/core/modules/rest/src/Entity/RestEndpoint.php index df756b6..aadb7c4 100644 --- a/core/modules/rest/src/Entity/RestEndpoint.php +++ b/core/modules/rest/src/Entity/RestEndpoint.php @@ -71,15 +71,105 @@ public function getPluginID() { /** * {@inheritdoc} */ - public function getSettings() { - return $this->configuration; + public function getSupportedAuthenticationProviders($method) { + if (isset($this->configuration[$method]) && isset($this->configuration[$method]['supported_auth'])) { + return $this->configuration[$method]['supported_auth']; + } + return []; + } + + /** + * {@inheritdoc} + */ + public function hasSupportForAuthenticationProvider($method, $auth) { + return $this->hasSupportedAuthenticationProviders($method) + && in_array($auth, $this->configuration[$method]['supported_auth']); + } + + public function hasSupportedAuthenticationProviders($method) { + return isset($this->configuration[$method]) + && isset($this->configuration[$method]['supported_auth']) + && !empty($this->configuration[$method]['supported_auth']); + } + + /** + * {@inheritdoc} + */ + public function addSupportedAuthenticationProvider($method, $auth) { + if (!isset($this->configuration[$method])) { + $this->configuration[$method] = [ 'supported_auth' => [] ]; + } + if (!isset($this->configuration[$method]['supported_auth'])){ + $this->configuration[$method]['supported_auth'] = []; + } + if (!in_array($auth, $this->configuration[$method]['supported_auth'])) { + $this->configuration[$method]['supported_auth'][] = $auth; + } + return $this; + } + + /** + * {@inheritdoc} + */ + public function removeSupportedAuthenticationProvider($method, $auth) { + $new_auth = array_filter($this->configuration[$method]['supported_auth'], function ($val) use ($auth) { + return ($val != $auth); + }); + $this->configuration[$method]['supported_auth'] = $new_auth; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getSupportedFormats($method) { + if (isset($this->configuration[$method]) && isset($this->configuration[$method]['supported_formats'])) { + return $this->configuration[$method]['supported_formats']; + } + return []; + } + + /** + * {@inheritdoc} + */ + public function supportsFormat($method, $format) { + return $this->hasSupportedFormats($method) + && in_array($format, $this->configuration[$method]['supported_formats']); + } + + /** + * {@inheritdoc} + */ + public function hasSupportedFormats($method) { + return isset($this->configuration[$method]) + && isset($this->configuration[$method]['supported_formats']) + && !empty($this->configuration[$method]['supported_formats']); } /** * {@inheritdoc} */ - public function setSettings(array $settings) { - $this->configuration = $settings; + public function addSupportedFormat($method, $format) { + if (!isset($this->configuration[$method])) { + $this->configuration[$method] = [ 'supported_formats' => [] ]; + } + if (!isset($this->configuration[$method]['supported_formats'])){ + $this->configuration[$method]['supported_formats'] = []; + } + if (!in_array($format, $this->configuration[$method]['supported_formats'])) { + $this->configuration[$method]['supported_formats'][] = $format; + } + return $this; } + /** + * {@inheritdoc} + */ + public function removeSupportedFormat($method, $format) { + $new_auth = array_filter($this->configuration[$method]['supported_formats'], function ($val) use ($format) { + return ($val != $format); + }); + $this->configuration[$method]['supported_formats'] = $new_auth; + return $this; + } } diff --git a/core/modules/rest/src/RequestHandler.php b/core/modules/rest/src/RequestHandler.php index 121f32c..ea69fea 100644 --- a/core/modules/rest/src/RequestHandler.php +++ b/core/modules/rest/src/RequestHandler.php @@ -62,9 +62,8 @@ public function handle(RouteMatchInterface $route_match, Request $request) { // formats are configured allow all and hope that the serializer knows the // format. If the serializer cannot handle it an exception will be thrown // that bubbles up to the client. - $config = $endpoint->getSettings(); - $method_settings = $config[$request->getMethod()]; - if (empty($method_settings['supported_formats']) || in_array($format, $method_settings['supported_formats'])) { + $request_method = $request->getMethod(); + if (!$endpoint->hasSupportedFormats($request_method) || $endpoint->supportsFormat($request_method, $format)) { $definition = $resource->getPluginDefinition(); $class = $definition['serialization_class']; try { diff --git a/core/modules/rest/src/RestEndpointInterface.php b/core/modules/rest/src/RestEndpointInterface.php index c2a0fb9..cc372e5 100644 --- a/core/modules/rest/src/RestEndpointInterface.php +++ b/core/modules/rest/src/RestEndpointInterface.php @@ -6,17 +6,105 @@ interface RestEndpointInterface extends ConfigEntityInterface { /** - * @return array + * @return string The plugin id of the resource for this REST endpoint. */ - public function getSettings(); + public function getPluginID(); /** - * @param array $settings + * Retrieves a list of supported authentication mechanisms + * for a specific request method. + * + * @param string $method The request method e.g GET or POST + * @return string[] An array of supported authentication provider plugin id's */ - public function setSettings(array $settings); + public function getSupportedAuthenticationProviders($method); /** - * @return string The plugin id of the resource for this REST endpoint. + * Denotes whether the given request method supports + * the specified authentication provider on this endpoint + * + * @param string $method The request method e.g GET or POST + * @param string $auth An authentication provider plugin id + * @return bool */ - public function getPluginID(); + public function hasSupportForAuthenticationProvider($method, $auth); + + /** + * Denotes whether the given request method + * supports at least one authentication provider. + * + * @param string $method The request method e.g GET or POST + * @return bool + */ + public function hasSupportedAuthenticationProviders($method); + + /** + * Add the specified authentication provider to + * the list of supported authentication providers + * for the given request method. + * + * @param string $method The request method e.g GET or POST + * @param string $auth An authentication provider plugin id + * @return $this + */ + public function addSupportedAuthenticationProvider($method, $auth); + + /** + * Remove the specified authentication provider from + * the list of supported authentication providers + * for the given request method. + * + * @param string $method The request method e.g GET or POST + * @param string $auth An authentication provider plugin id + * @return $this + */ + public function removeSupportedAuthenticationProvider($method, $auth); + + /** + * Retrieves a list of supported formats for a specific request method. + * + * @param string $method The request method e.g GET or POST + * @return string[] An array of supported format plugin id's + */ + public function getSupportedFormats($method); + + /** + * Denotes whether the given request method supports + * the specified format on this endpoint + * + * @param string $method The request method e.g GET or POST + * @param string $format A format plugin id + * @return bool + */ + public function supportsFormat($method, $format); + + /** + * Denotes whether the given request method supports at least one format. + * + * @param string $method The request method e.g GET or POST + * @return bool + */ + public function hasSupportedFormats($method); + + /** + * Add the specified format to + * the list of supported authentication providers + * for the given request method. + * + * @param string $method The request method e.g GET or POST + * @param string $format A format plugin id + * @return $this + */ + public function addSupportedFormat($method, $format); + + /** + * Remove the specified format from + * the list of supported authentication providers + * for the given request method. + * + * @param string $method The request method e.g GET or POST + * @param string $format A format plugin id + * @return $this + */ + public function removeSupportedFormat($method, $format); } diff --git a/core/modules/rest/src/Routing/ResourceRoutes.php b/core/modules/rest/src/Routing/ResourceRoutes.php index 31b6a84..8ef3e70 100644 --- a/core/modules/rest/src/Routing/ResourceRoutes.php +++ b/core/modules/rest/src/Routing/ResourceRoutes.php @@ -7,15 +7,10 @@ namespace Drupal\rest\Routing; -use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Routing\RouteSubscriberBase; use Drupal\rest\Plugin\Type\ResourcePluginManager; -use Drupal\rest\RestEndpointRepositoryInterface; use Psr\Log\LoggerInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Routing\RouteCollection; /** @@ -49,8 +44,8 @@ class ResourceRoutes extends RouteSubscriberBase{ * * @param \Drupal\rest\Plugin\Type\ResourcePluginManager $manager * The resource plugin manager. - * @param \Drupal\rest\RestEndpointRepositoryInterface $endpoint_repository - * The REST endpoint repository + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager * @param \Psr\Log\LoggerInterface $logger * A logger instance. */ @@ -75,7 +70,6 @@ protected function alterRoutes(RouteCollection $collection) { $endpoints = $this->endpoint_storage->loadMultiple(); foreach ($endpoints as $endpoint) { $plugin = $this->manager->getInstance(array('id' => $endpoint->getPluginID())); - $enabled_methods = $endpoint->getSettings(); foreach ($plugin->routes() as $name => $route) { $method = $route->getRequirement('_method'); @@ -84,13 +78,13 @@ protected function alterRoutes(RouteCollection $collection) { $route->setRequirement('_access_rest_csrf', 'TRUE'); // Check that authentication providers are defined. - if (empty($enabled_methods[$method]['supported_auth']) || !is_array($enabled_methods[$method]['supported_auth'])) { + if (!$endpoint->hasSupportedAuthenticationProviders($method)) { $this->logger->error('At least one authentication provider must be defined for resource @id', array(':id' => $endpoint->id())); continue; } // Check that formats are defined. - if (empty($enabled_methods[$method]['supported_formats']) || !is_array($enabled_methods[$method]['supported_formats'])) { + if (!$endpoint->hasSupportedFormats($method)) { $this->logger->error('At least one format must be defined for resource @id', array(':id' => $endpoint->id())); continue; } @@ -98,13 +92,13 @@ protected function alterRoutes(RouteCollection $collection) { // If the route has a format requirement, then verify that the // resource has it. $format_requirement = $route->getRequirement('_format'); - if ($format_requirement && !in_array($format_requirement, $enabled_methods[$method]['supported_formats'])) { + if ($format_requirement && $endpoint->supportsFormat($method, $format_requirement)) { continue; } // The configuration seems legit at this point, so we set the // authentication provider and add the route. - $route->setOption('_auth', $enabled_methods[$method]['supported_auth']); + $route->setOption('_auth', $endpoint->getSupportedAuthenticationProviders($method)); $routes["rest.$name"] = $route; $collection->add("rest.$name", $route); } diff --git a/core/modules/rest/src/Tests/RESTTestBase.php b/core/modules/rest/src/Tests/RESTTestBase.php index 5f305ef..0bfbccf 100644 --- a/core/modules/rest/src/Tests/RESTTestBase.php +++ b/core/modules/rest/src/Tests/RESTTestBase.php @@ -242,25 +242,23 @@ protected function entityValues($entity_type) { * (Optional) The list of valid authentication methods. */ protected function enableService($resource_type, $method = 'GET', $format = NULL, $auth = NULL) { - // Enable REST API for this entity type. - $endpoint_id = str_replace(':', '__', $resource_type); - // get entity by id - /** @var \Drupal\rest\RestEndpointInterface $endpoint */ - $endpoint = $this->endpoint_storage->load($endpoint_id); - $endpoint = ($endpoint !== NULL) ? $endpoint : $this->endpoint_storage->create(['id' => $endpoint_id]); - $settings = array(); - if ($resource_type) { + // Enable REST API for this entity type. + $endpoint_id = str_replace(':', '__', $resource_type); + // get entity by id + /** @var \Drupal\rest\RestEndpointInterface $endpoint */ + $endpoint = $this->endpoint_storage->load($endpoint_id); + $endpoint = ($endpoint !== NULL) ? $endpoint : $this->endpoint_storage->create(['id' => $endpoint_id]); + if ($format == NULL) { $format = $this->defaultFormat; } - $settings[$method]['supported_formats'][] = $format; + $endpoint->addSupportedFormat($method, $format); if ($auth == NULL) { $auth = $this->defaultAuth; } - $settings[$method]['supported_auth'] = $auth; - $endpoint->setSettings($settings); + $endpoint->addSupportedAuthenticationProvider($method, $auth); $endpoint->save(); } else { foreach ($this->endpoint_storage->loadMultiple() AS $endpoint) { diff --git a/core/modules/rest/src/Tests/ResourceTest.php b/core/modules/rest/src/Tests/ResourceTest.php index 2b74fef..233b078 100644 --- a/core/modules/rest/src/Tests/ResourceTest.php +++ b/core/modules/rest/src/Tests/ResourceTest.php @@ -37,15 +37,9 @@ protected function setUp() { public function testFormats() { /** @var \Drupal\rest\RestEndpointInterface $endpoint */ $endpoint = $this->endpoint_storage->create(['id' => 'entity__entity_test']); - $endpoint->setSettings([ - 'GET' => [ - 'supported_auth' => [ - 'basic_auth', - ], - ], - ]); - // Attempt to enable the resource. - $endpoint->save(); + $endpoint + ->addSupportedAuthenticationProvider('GET', 'basic_auth') + ->save();// Attempt to enable the resource. $this->rebuildCache(); // Verify that accessing the resource returns 401. @@ -64,15 +58,9 @@ public function testFormats() { public function testAuthentication() { /** @var \Drupal\rest\RestEndpointInterface $endpoint */ $endpoint = $this->endpoint_storage->create(['id' => 'entity__entity_test']); - $endpoint->setSettings([ - 'GET' => [ - 'supported_formats' => [ - 'hal_json', - ], - ], - ]); - // Attempt to enable the resource. - $endpoint->save(); + $endpoint + ->addSupportedFormat('GET', 'hal_json') + ->save();// Attempt to enable the resource. $this->rebuildCache(); // Verify that accessing the resource returns 401.