Skip to content
Snippets Groups Projects
Commit 2ec23349 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #2664780 by Wim Leers, tedbow, dawehner, klausi: Remove REST's resource-...

Issue #2664780 by Wim Leers, tedbow, dawehner, klausi: Remove REST's resource- and verb-specific permissions for EntityResource, but provide BC and document why it's necessary for other resources
parent 23ed767a
No related branches found
No related tags found
No related merge requests found
Showing
with 242 additions and 65 deletions
......@@ -53,13 +53,13 @@ public function testWatchdog() {
$response = $this->httpRequest(Url::fromRoute('rest.dblog.GET.' . $this->defaultFormat, ['id' => 9999, '_format' => $this->defaultFormat]), 'GET');
$this->assertResponse(404);
$decoded = Json::decode($response);
$this->assertEqual($decoded['error'], 'Log entry with ID 9999 was not found', 'Response message is correct.');
$this->assertEqual($decoded['message'], 'Log entry with ID 9999 was not found', 'Response message is correct.');
// Make a bad request (a true malformed request would never be a route match).
$response = $this->httpRequest(Url::fromRoute('rest.dblog.GET.' . $this->defaultFormat, ['id' => 0, '_format' => $this->defaultFormat]), 'GET');
$this->assertResponse(400);
$decoded = Json::decode($response);
$this->assertEqual($decoded['error'], 'No log entry ID was provided', 'Response message is correct.');
$this->assertEqual($decoded['message'], 'No log entry ID was provided', 'Response message is correct.');
}
}
......@@ -8,7 +8,6 @@
use Drupal\entity_test\Entity\EntityTest;
use Drupal\simpletest\WebTestBase;
use Drupal\Core\Cache\Cache;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;
/**
......@@ -136,10 +135,6 @@ function testQueryParameterFormatRequests() {
$node = $this->drupalCreateNode(['type' => 'article']);
$node_uri = $node->urlInfo();
$node_url_with_hal_json_format = $node->urlInfo('canonical')->setRouteParameter('_format', 'hal_json');
/** @var \Drupal\user\RoleInterface $role */
$role = Role::load('anonymous');
$role->grantPermission('restful get entity:node');
$role->save();
$this->drupalGet($node_uri);
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
......
# Set the domain for REST type and relation links.
# If left blank, the site's domain will be used.
link_domain: ~
# Before Drupal 8.2, EntityResource used permissions as well as the entity
# access system for access checking. This was confusing, and it only did this
# for historical reasons. New Drupal installations opt out from this by default
# (hence this is set to false), existing installations opt in to it.
# @see rest_update_8203()
# @see https://www.drupal.org/node/2664780
bc_entity_resource_permissions: false
......@@ -6,6 +6,9 @@ rest.settings:
link_domain:
type: string
label: 'Domain of the relation'
bc_entity_resource_permissions:
type: boolean
label: 'Whether the pre Drupal 8.2.x behavior of having permissions for EntityResource is enabled or not.'
# Method-level granularity of REST resource configuration.
rest_resource.method:
......
......@@ -65,6 +65,16 @@ function rest_update_8202() {
}
}
/**
* Enable BC for EntityResource: continue to use permissions.
*/
function rest_update_8203() {
$config_factory = \Drupal::configFactory();
$rest_settings = $config_factory->getEditable('rest.settings');
$rest_settings->set('bc_entity_resource_permissions', TRUE)
->save(TRUE);
}
/**
* @} End of "defgroup updates-8.1.x-to-8.2.x".
*/
......@@ -12,6 +12,11 @@
/**
* Common base class for resource plugins.
*
* Note that this base class' implementation of the permissions() method
* generates a permission for every method for a resource. If your resource
* already has its own access control mechanism, you should opt out from this
* default permissions() method by overriding it.
*
* @see \Drupal\rest\Annotation\RestResource
* @see \Drupal\rest\Plugin\Type\ResourcePluginManager
* @see \Drupal\rest\Plugin\ResourceInterface
......@@ -179,7 +184,7 @@ public function availableMethods() {
}
/**
* Setups the base route for all HTTP methods.
* Gets the base route for a particular method.
*
* @param string $canonical_path
* The canonical path for the resource.
......@@ -190,20 +195,48 @@ public function availableMethods() {
* The created base route.
*/
protected function getBaseRoute($canonical_path, $method) {
$lower_method = strtolower($method);
$route = new Route($canonical_path, array(
return new Route($canonical_path, array(
'_controller' => 'Drupal\rest\RequestHandler::handle',
), array(
'_permission' => "restful $lower_method $this->pluginId",
),
$this->getBaseRouteRequirements($method),
array(),
'',
array(),
// The HTTP method is a requirement for this route.
array($method)
);
return $route;
}
/**
* Gets the base route requirements for a particular method.
*
* @param $method
* The HTTP method to be used for the route.
*
* @return array
* An array of requirements for parameters.
*/
protected function getBaseRouteRequirements($method) {
$lower_method = strtolower($method);
// Every route MUST have requirements that result in the access manager
// having access checks to check. If it does not, the route is made
// inaccessible. So, we default to granting access to everyone. If a
// permission exists, then we add that below. The access manager requires
// that ALL access checks must grant access, so this still results in
// correct behavior.
$requirements = [
'_access' => 'TRUE',
];
// Only specify route requirements if the default permission exists. For any
// more advanced route definition, resource plugins extending this base
// class must override this method.
$permission = "restful $lower_method $this->pluginId";
if (isset($this->permissions()[$permission])) {
$requirements['_permission'] = $permission;
}
return $requirements;
}
}
......@@ -33,6 +33,10 @@ public function routes();
* A resource plugin can define a set of user permissions that are used on the
* routes for this resource or for other purposes.
*
* It is not required for a resource plugin to specify permissions: if they
* have their own access control mechanism, they can use that, and return the
* empty array.
*
* @return array
* The permission array.
*/
......
......@@ -6,6 +6,7 @@
use Drupal\Core\Config\Entity\ConfigEntityType;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\rest\Plugin\ResourceBase;
......@@ -42,6 +43,13 @@ class EntityResource extends ResourceBase implements DependentPluginInterface {
*/
protected $entityType;
/**
* The config factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* Constructs a Drupal\rest\Plugin\rest\resource\EntityResource object.
*
......@@ -57,10 +65,13 @@ class EntityResource extends ResourceBase implements DependentPluginInterface {
* The available serialization formats.
* @param \Psr\Log\LoggerInterface $logger
* A logger instance.
* @param \Drupal\Core\Config\ConfigFactoryInterface
* The config factory.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, $serializer_formats, LoggerInterface $logger) {
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, $serializer_formats, LoggerInterface $logger, ConfigFactoryInterface $config_factory) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);
$this->entityType = $entity_type_manager->getDefinition($plugin_definition['entity_type']);
$this->configFactory = $config_factory;
}
/**
......@@ -73,7 +84,8 @@ public static function create(ContainerInterface $container, array $configuratio
$plugin_definition,
$container->get('entity_type.manager'),
$container->getParameter('serializer.formats'),
$container->get('logger.factory')->get('rest')
$container->get('logger.factory')->get('rest'),
$container->get('config.factory')
);
}
......@@ -297,6 +309,21 @@ protected function validate(EntityInterface $entity) {
}
}
/**
* {@inheritdoc}
*/
public function permissions() {
// @see https://www.drupal.org/node/2664780
if ($this->configFactory->get('rest.settings')->get('bc_entity_resource_permissions')) {
// The default Drupal 8.0.x and 8.1.x behavior.
return parent::permissions();
}
else {
// The default Drupal 8.2.x behavior.
return [];
}
}
/**
* {@inheritdoc}
*/
......
......@@ -12,7 +12,6 @@
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
use Symfony\Component\Serializer\SerializerInterface;
......@@ -131,17 +130,7 @@ public function handle(RouteMatchInterface $route_match, Request $request) {
// Invoke the operation on the resource plugin.
$format = $this->getResponseFormat($route_match, $request);
try {
$response = call_user_func_array(array($resource, $method), array_merge($parameters, array($unserialized, $request)));
}
catch (HttpException $e) {
$error['error'] = $e->getMessage();
$content = $serializer->serialize($error, $format);
// Add the default content type, but only if the headers from the
// exception have not specified it already.
$headers = $e->getHeaders() + array('Content-Type' => $request->getMimeType($format));
return new Response($content, $e->getStatusCode(), $headers);
}
$response = call_user_func_array(array($resource, $method), array_merge($parameters, array($unserialized, $request)));
return $response instanceof ResourceResponseInterface ?
$this->renderResponse($request, $response, $serializer, $format, $resource_config) :
......
......@@ -43,7 +43,6 @@ public function testRead() {
// resources via the REST API, but the request is authenticated
// with session cookies.
$permissions = $this->entityPermissions($entity_type, 'view');
$permissions[] = 'restful get entity:' . $entity_type;
$account = $this->drupalCreateUser($permissions);
$this->drupalLogin($account);
......
......@@ -5,6 +5,7 @@
use Drupal\comment\Tests\CommentTestTrait;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Url;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\node\Entity\Node;
use Drupal\user\Entity\User;
......@@ -49,8 +50,6 @@ public function testCreateResourceRestApiNotEnabled() {
// Get the necessary user permissions to create the current entity type.
$permissions = $this->entityPermissions($entity_type, 'create');
// POST method must be allowed for the current entity type.
$permissions[] = 'restful post entity:' . $entity_type;
// Create the user.
$account = $this->drupalCreateUser($permissions);
......@@ -77,7 +76,11 @@ public function testCreateResourceRestApiNotEnabled() {
/**
* Ensure that an entity cannot be created without the restful permission.
*/
public function testCreateWithoutPermission() {
public function testCreateWithoutPermissionIfBcFlagIsOn() {
$rest_settings = $this->config('rest.settings');
$rest_settings->set('bc_entity_resource_permissions', TRUE)
->save(TRUE);
$entity_type = 'entity_test';
// Enables the REST service for 'entity_test' entity type.
$this->enableService('entity:' . $entity_type, 'POST');
......@@ -96,6 +99,14 @@ public function testCreateWithoutPermission() {
$this->httpRequest('entity/' . $entity_type, 'POST', $serialized, $this->defaultMimeType);
$this->assertResponse(403);
$this->assertFalse(EntityTest::loadMultiple(), 'No entity has been created in the database.');
// Create a user with the 'restful post entity:entity_test permission and
// try again. This time, we should be able to create an entity.
$permissions[] = 'restful post entity:' . $entity_type;
$account = $this->drupalCreateUser($permissions);
$this->drupalLogin($account);
$this->httpRequest('entity/' . $entity_type, 'POST', $serialized, $this->defaultMimeType);
$this->assertResponse(201);
}
/**
......@@ -331,8 +342,6 @@ public function createAccountPerEntity($entity_type) {
$accounts = array();
// Get the necessary user permissions for the current $entity_type creation.
$permissions = $this->entityPermissions($entity_type, 'create');
// POST method must be allowed for the current entity type.
$permissions[] = 'restful post entity:' . $entity_type;
// Create user without administrative permissions.
$accounts[] = $this->drupalCreateUser($permissions);
// Add administrative permissions for nodes and users.
......@@ -440,14 +449,14 @@ public function assertCreateEntityInvalidSerialized(EntityInterface $entity, $en
$entity->set('uuid', $this->randomMachineName(129));
$invalid_serialized = $this->serializer->serialize($entity, $this->defaultFormat, $context);
$response = $this->httpRequest('entity/' . $entity_type, 'POST', $invalid_serialized, $this->defaultMimeType);
$response = $this->httpRequest(Url::fromRoute("rest.entity.$entity_type.POST")->setRouteParameter('_format', $this->defaultFormat), 'POST', $invalid_serialized, $this->defaultMimeType);
// Unprocessable Entity as response.
$this->assertResponse(422);
// Verify that the text of the response is correct.
$error = Json::decode($response);
$this->assertEqual($error['error'], "Unprocessable Entity: validation failed.\nuuid.0.value: <em class=\"placeholder\">UUID</em>: may not be longer than 128 characters.\n");
$this->assertEqual($error['message'], "Unprocessable Entity: validation failed.\nuuid.0.value: <em class=\"placeholder\">UUID</em>: may not be longer than 128 characters.\n");
}
/**
......
......@@ -43,7 +43,6 @@ protected function setUp() {
// Create a user account that has the required permissions to create
// resources via the REST API.
$permissions = $this->entityPermissions($this->testEntityType, 'create');
$permissions[] = 'restful post entity:' . $this->testEntityType;
$this->account = $this->drupalCreateUser($permissions);
// Serialize an entity to a string to use in the content body of the POST
......
......@@ -31,7 +31,6 @@ public function testDelete() {
// Create a user account that has the required permissions to delete
// resources via the REST API.
$permissions = $this->entityPermissions($entity_type, 'delete');
$permissions[] = 'restful delete entity:' . $entity_type;
$account = $this->drupalCreateUser($permissions);
$this->drupalLogin($account);
......
......@@ -32,7 +32,6 @@ class NodeTest extends RESTTestBase {
protected function enableNodeConfiguration($method, $operation) {
$this->enableService('entity:node', $method);
$permissions = $this->entityPermissions('node', $operation);
$permissions[] = 'restful ' . strtolower($method) . ' entity:node';
$account = $this->drupalCreateUser($permissions);
$this->drupalLogin($account);
}
......
......@@ -48,10 +48,6 @@ public function testConfigChangePageCache() {
$this->enableService('entity:entity_test', 'POST');
$permissions = [
'administer entity_test content',
'restful post entity:entity_test',
'restful get entity:entity_test',
'restful patch entity:entity_test',
'restful delete entity:entity_test',
];
$account = $this->drupalCreateUser($permissions);
......
......@@ -48,7 +48,6 @@ public function testRead() {
// Create a user account that has the required permissions to read
// resources via the REST API.
$permissions = $this->entityPermissions($entity_type, 'view');
$permissions[] = 'restful get entity:' . $entity_type;
$account = $this->drupalCreateUser($permissions);
$this->drupalLogin($account);
......@@ -123,12 +122,6 @@ public function testRead() {
$data = Json::decode($response);
$this->assertFalse(isset($data['field_test_text']), 'Field access protected field is not visible in the response.');
}
// Try to read an entity without proper permissions.
$this->drupalLogout();
$response = $this->httpRequest($this->getReadUrl($entity), 'GET');
$this->assertResponse(403);
$this->assertIdentical('{"message":""}', $response);
}
// Try to read a resource, the user entity, which is not REST API enabled.
$account = $this->drupalCreateUser();
......@@ -155,7 +148,6 @@ public function testResourceStructure() {
// Create a user account that has the required permissions to read
// resources via the REST API.
$permissions = $this->entityPermissions('node', 'view');
$permissions[] = 'restful get entity:node';
$account = $this->drupalCreateUser($permissions);
$this->drupalLogin($account);
......
<?php
namespace Drupal\rest\Tests\Update;
use Drupal\system\Tests\Update\UpdatePathTestBase;
/**
* Tests that existing sites continue to use permissions for EntityResource.
*
* @see https://www.drupal.org/node/2664780
*
* @group rest
*/
class EntityResourcePermissionsUpdateTest 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_update_8203.php',
];
}
/**
* Tests rest_update_8203().
*/
public function testBcEntityResourcePermissionSettingAdded() {
$permission_handler = $this->container->get('user.permissions');
$is_rest_resource_permission = function ($permission) {
return $permission['provider'] === 'rest' && (string) $permission['title'] !== 'Administer REST resource configuration';
};
// Make sure we have the expected values before the update.
$rest_settings = $this->config('rest.settings');
$this->assertFalse(array_key_exists('bc_entity_resource_permissions', $rest_settings->getRawData()));
$this->assertEqual([], array_filter($permission_handler->getPermissions(), $is_rest_resource_permission));
$this->runUpdates();
// Make sure we have the expected values after the update.
$rest_settings = $this->config('rest.settings');
$this->assertTrue(array_key_exists('bc_entity_resource_permissions', $rest_settings->getRawData()));
$this->assertTrue($rest_settings->get('bc_entity_resource_permissions'));
$rest_permissions = array_keys(array_filter($permission_handler->getPermissions(), $is_rest_resource_permission));
$this->assertEqual(['restful delete entity:node', 'restful get entity:node', 'restful patch entity:node', 'restful post entity:node'], $rest_permissions);
}
}
......@@ -46,7 +46,6 @@ public function testPatchUpdate() {
// Create a user account that has the required permissions to create
// resources via the REST API.
$permissions = $this->entityPermissions($entity_type, 'update');
$permissions[] = 'restful patch entity:' . $entity_type;
$account = $this->drupalCreateUser($permissions);
$this->drupalLogin($account);
......@@ -176,10 +175,10 @@ public function testPatchUpdate() {
// Send a UUID that is too long.
$entity->set('uuid', $this->randomMachineName(129));
$invalid_serialized = $serializer->serialize($entity, $this->defaultFormat, $context);
$response = $this->httpRequest($entity->urlInfo(), 'PATCH', $invalid_serialized, $this->defaultMimeType);
$response = $this->httpRequest($entity->toUrl()->setRouteParameter('_format', $this->defaultFormat), 'PATCH', $invalid_serialized, $this->defaultMimeType);
$this->assertResponse(422);
$error = Json::decode($response);
$this->assertEqual($error['error'], "Unprocessable Entity: validation failed.\nuuid.0.value: <em class=\"placeholder\">UUID</em>: may not be longer than 128 characters.\n");
$this->assertEqual($error['message'], "Unprocessable Entity: validation failed.\nuuid.0.value: <em class=\"placeholder\">UUID</em>: may not be longer than 128 characters.\n");
// Try to update an entity without proper permissions.
$this->drupalLogout();
......@@ -202,7 +201,6 @@ public function testUpdateUser() {
// Enables the REST service for 'user' entity type.
$this->enableService('entity:' . $entity_type, 'PATCH');
$permissions = $this->entityPermissions($entity_type, 'update');
$permissions[] = 'restful patch entity:' . $entity_type;
$account = $this->drupalCreateUser($permissions);
$account->set('mail', 'old-email@example.com');
$this->drupalLogin($account);
......@@ -216,18 +214,18 @@ public function testUpdateUser() {
$context = ['account' => $account];
$normalized = $serializer->normalize($account, $this->defaultFormat, $context);
$serialized = $serializer->serialize($normalized, $this->defaultFormat, $context);
$response = $this->httpRequest($account->urlInfo(), 'PATCH', $serialized, $this->defaultMimeType);
$response = $this->httpRequest($account->toUrl()->setRouteParameter('_format', $this->defaultFormat), 'PATCH', $serialized, $this->defaultMimeType);
$this->assertResponse(422);
$error = Json::decode($response);
$this->assertEqual($error['error'], "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the <em class=\"placeholder\">Email</em>.\n");
$this->assertEqual($error['message'], "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the <em class=\"placeholder\">Email</em>.\n");
// Try and send the new email with a password.
$normalized['pass'][0]['existing'] = 'wrong';
$serialized = $serializer->serialize($normalized, $this->defaultFormat, $context);
$response = $this->httpRequest($account->urlInfo(), 'PATCH', $serialized, $this->defaultMimeType);
$response = $this->httpRequest($account->toUrl()->setRouteParameter('_format', $this->defaultFormat), 'PATCH', $serialized, $this->defaultMimeType);
$this->assertResponse(422);
$error = Json::decode($response);
$this->assertEqual($error['error'], "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the <em class=\"placeholder\">Email</em>.\n");
$this->assertEqual($error['message'], "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the <em class=\"placeholder\">Email</em>.\n");
// Try again with the password.
$normalized['pass'][0]['existing'] = $account->pass_raw;
......@@ -240,10 +238,10 @@ public function testUpdateUser() {
$normalized = $serializer->normalize($account, $this->defaultFormat, $context);
$normalized['pass'][0]['value'] = $new_password;
$serialized = $serializer->serialize($normalized, $this->defaultFormat, $context);
$response = $this->httpRequest($account->urlInfo(), 'PATCH', $serialized, $this->defaultMimeType);
$response = $this->httpRequest($account->toUrl()->setRouteParameter('_format', $this->defaultFormat), 'PATCH', $serialized, $this->defaultMimeType);
$this->assertResponse(422);
$error = Json::decode($response);
$this->assertEqual($error['error'], "Unprocessable Entity: validation failed.\npass: Your current password is missing or incorrect; it's required to change the <em class=\"placeholder\">Password</em>.\n");
$this->assertEqual($error['message'], "Unprocessable Entity: validation failed.\npass: Your current password is missing or incorrect; it's required to change the <em class=\"placeholder\">Password</em>.\n");
// Try again with the password.
$normalized['pass'][0]['existing'] = $account->pass_raw;
......@@ -264,7 +262,6 @@ public function testUpdateComment() {
// Enables the REST service for 'comment' entity type.
$this->enableService('entity:' . $entity_type, 'PATCH', ['hal_json', 'json']);
$permissions = $this->entityPermissions($entity_type, 'update');
$permissions[] = 'restful patch entity:' . $entity_type;
$account = $this->drupalCreateUser($permissions);
$account->set('mail', 'old-email@example.com');
$this->drupalLogin($account);
......@@ -336,7 +333,7 @@ public function testUpdateComment() {
protected function patchEntity(EntityInterface $entity, array $read_only_fields, AccountInterface $account, $format, $mime_type) {
$serializer = $this->container->get('serializer');
$url = $entity->toUrl();
$url = $entity->toUrl()->setRouteParameter('_format', $this->defaultFormat);
$context = ['account' => $account];
// Certain fields are always read-only, others this user simply is not
// allowed to modify. For all of them, ensure they are not serialized, else
......@@ -359,7 +356,7 @@ protected function patchEntity(EntityInterface $entity, array $read_only_fields,
$this->httpRequest($url, 'PATCH', $serialized, $mime_type);
$this->assertResponse(403);
$this->assertResponseBody('{"error":"Access denied on updating field \'' . $field . '\'."}');
$this->assertResponseBody('{"message":"Access denied on updating field \\u0027' . $field . '\\u0027."}');
if ($format === 'hal_json') {
// We've just tried with this read-only field, now unset it.
......
<?php
/**
* @file
* Contains database additions to drupal-8.bare.standard.php.gz for testing the
* upgrade path of rest_update_8203().
*/
use Drupal\Core\Database\Database;
$connection = Database::getConnection();
// Set the schema version.
$connection->insert('key_value')
->fields([
'collection' => 'system.schema',
'name' => 'rest',
'value' => 'i:8000;',
])
->fields([
'collection' => 'system.schema',
'name' => 'serialization',
'value' => 'i:8000;',
])
->execute();
// Update core.extension.
$extensions = $connection->select('config')
->fields('config', ['data'])
->condition('collection', '')
->condition('name', 'core.extension')
->execute()
->fetchField();
$extensions = unserialize($extensions);
$extensions['module']['rest'] = 8000;
$extensions['module']['serialization'] = 8000;
$connection->update('config')
->fields([
'data' => serialize($extensions),
])
->condition('collection', '')
->condition('name', 'core.extension')
->execute();
// Install the rest configuration.
$config = [
'resources' => [
'entity:node' => [
'GET' => [
'supported_formats' => ['json'],
'supported_auth' => ['basic_auth'],
],
],
],
'link_domain' => '~',
];
$data = $connection->insert('config')
->fields([
'name' => 'rest.settings',
'data' => serialize($config),
'collection' => ''
])
->execute();
......@@ -26,7 +26,6 @@ protected function setUp() {
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
$permissions = $this->entityPermissions('node', 'view');
$permissions[] = 'restful get entity:node';
$account = $this->drupalCreateUser($permissions);
$this->drupalLogin($account);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment