Commit 43a4ef25 authored by alexpott's avatar alexpott

Issue #2065193 by juampy, klausi: Supported_formats and supported_auth should work in the same way.

parent e048d17b
# Enable all methods on nodes.
# You must enable Hal and Basic_auth modules for this to work. Also, if you are
# going to use Basic_auth in a production environment then you should consider
# setting up SSL.
# There are alternatives to Basic_auth in contrib such as OAuth module.
resources:
entity:node:
GET: { }
POST: { }
PATCH: { }
DELETE: { }
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
# To enable only specific formats for an operation, list the supported_formats.
# For example, the following config makes JSON the only format available for
# node GET requests.
# resources:
# entity:node:
# GET:
# supported_formats:
# - json
# Multiple formats and multiple authentication providers can be defined for a
# resource:
#
# To enable only specific authentication methods for an operation, list them
# at supported_auth.
# For example, the following config only allows Basic HTTP authenticated
# requests for the POST method on the node entity.
# resources:
# entity:node:
# POST:
# supported_auth:
# - basic_auth
# resources:
# entity:node:
# GET:
# supported_formats:
# - json
# - hal_json
# - xml
# supported_auth:
# - cookie
# - basic_auth
#
# hal_json is the only format supported for POST and PATCH methods.
#
# The full documentation is located at
# https://drupal.org/documentation/modules/rest
......@@ -60,23 +60,29 @@ protected function routes(RouteCollection $collection) {
if ($method && isset($enabled_methods[$method])) {
$route->setRequirement('_access_rest_csrf', 'TRUE');
// If the array of configured format restrictions is empty for a
// method always add the route.
if (empty($enabled_methods[$method])) {
$collection->add("rest.$name", $route);
// Check that authentication providers are defined.
if (empty($enabled_methods[$method]['supported_auth']) || !is_array($enabled_methods[$method]['supported_auth'])) {
watchdog('rest', 'At least one authentication provider must be defined for resource @id', array(':id' => $id), WATCHDOG_ERROR);
continue;
}
// Check if there are authentication provider restrictions in the
// configuration and apply them to the route.
if (!empty($enabled_methods[$method]['supported_auth']) && is_array($enabled_methods[$method]['supported_auth'])) {
$route->setOption('_auth', $enabled_methods[$method]['supported_auth']);
// Check that formats are defined.
if (empty($enabled_methods[$method]['supported_formats']) || !is_array($enabled_methods[$method]['supported_formats'])) {
watchdog('rest', 'At least one format must be defined for resource @id', array(':id' => $id), WATCHDOG_ERROR);
continue;
}
// If there is no format requirement or if it matches the
// configuration also add the route.
// If the route has a format requirement, then verify that the
// resource has it.
$format_requirement = $route->getRequirement('_format');
if (!$format_requirement || empty($enabled_methods[$method]['supported_formats']) || in_array($format_requirement, $enabled_methods[$method]['supported_formats'])) {
$collection->add("rest.$name", $route);
if ($format_requirement && !in_array($format_requirement, $enabled_methods[$method]['supported_formats'])) {
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']);
$collection->add("rest.$name", $route);
}
}
}
......
......@@ -36,10 +36,18 @@ abstract class RESTTestBase extends WebTestBase {
*/
protected $testEntityType = 'entity_test';
/**
* The default authentication provider to use for testing REST operations.
*
* @var array
*/
protected $defaultAuth;
protected function setUp() {
parent::setUp();
$this->defaultFormat = 'hal_json';
$this->defaultMimeType = 'application/hal+json';
$this->defaultAuth = array('cookie');
// Create a test content type for node testing.
$this->drupalCreateContentType(array('name' => 'resttest', 'type' => 'resttest'));
}
......@@ -205,25 +213,31 @@ protected function entityValues($entity_type) {
* @param array $auth
* (Optional) The list of valid authentication methods.
*/
protected function enableService($resource_type, $method = 'GET', $format = NULL, $auth = array()) {
protected function enableService($resource_type, $method = 'GET', $format = NULL, $auth = NULL) {
// Enable REST API for this entity type.
$config = \Drupal::config('rest.settings');
$settings = array();
if ($resource_type) {
if ($format) {
$settings[$resource_type][$method]['supported_formats'][] = $format;
if ($format == NULL) {
$format = $this->defaultFormat;
}
else {
$settings[$resource_type][$method] = array();
$settings[$resource_type][$method]['supported_formats'][] = $format;
if ($auth == NULL) {
$auth = $this->defaultAuth;
}
}
if (is_array($auth) && !empty($auth)) {
$settings[$resource_type][$method]['supported_auth'] = $auth;
}
$config->set('resources', $settings);
$config->save();
$this->rebuildCache();
}
/**
* Rebuilds routing caches.
*/
protected function rebuildCache() {
// Rebuild routing cache, so that the REST API paths are available.
$this->container->get('router.builder')->rebuild();
// Reset the Simpletest permission cache, so that the new resource
......
<?php
/**
* @file
* Definition of Drupal\rest\test\ResourceTest.
*/
namespace Drupal\rest\Tests;
use Drupal\rest\Tests\RESTTestBase;
/**
* Tests the REST resource structure.
*/
class ResourceTest extends RESTTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('hal', 'rest', 'entity_test');
/**
* {@inheritdoc}
*/
public static function getInfo() {
return array(
'name' => 'Resource structure',
'description' => 'Tests the structure of a REST resource',
'group' => 'REST',
);
}
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->config = \Drupal::config('rest.settings');
// Create an entity programmatically.
$this->entity = $this->entityCreate('entity_test');
$this->entity->save();
}
/**
* Tests that a resource without formats cannot be enabled.
*/
public function testFormats() {
$settings = array(
'entity:entity_test' => array(
'GET' => array(
'supported_auth' => array(
'basic_auth',
),
),
),
);
// Attempt to enable the resource.
$this->config->set('resources', $settings);
$this->config->save();
$this->rebuildCache();
// Verify that accessing the resource returns 401.
$response = $this->httpRequest('entity/entity_test/' . $this->entity->id(), 'GET', NULL, $this->defaultMimeType);
$this->assertResponse('404', 'HTTP response code is 404 when the resource does not define formats.');
$this->curlClose();
}
/**
* Tests that a resource without authentication cannot be enabled.
*/
public function testAuthentication() {
$settings = array(
'entity:entity_test' => array(
'GET' => array(
'supported_formats' => array(
'hal_json',
),
),
),
);
// Attempt to enable the resource.
$this->config->set('resources', $settings);
$this->config->save();
$this->rebuildCache();
// Verify that accessing the resource returns 401.
$response = $this->httpRequest('entity/entity_test/' . $this->entity->id(), 'GET', NULL, $this->defaultMimeType);
$this->assertResponse('404', 'HTTP response code is 404 when the resource does not define authentication.');
$this->curlClose();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment