diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php index 91bba3c..5bfb9cd 100644 --- a/core/lib/Drupal/Core/CoreBundle.php +++ b/core/lib/Drupal/Core/CoreBundle.php @@ -269,6 +269,8 @@ public function build(ContainerBuilder $container) { ->addTag('event_subscriber'); $container->register('access_check.default', 'Drupal\Core\Access\DefaultAccessCheck') ->addTag('access_check'); + $container->register('access_check.entity', 'Drupal\Core\Entity\EntityAccessCheck') + ->addTag('access_check'); $container->register('maintenance_mode_subscriber', 'Drupal\Core\EventSubscriber\MaintenanceModeSubscriber') ->addTag('event_subscriber'); $container->register('path_subscriber', 'Drupal\Core\EventSubscriber\PathSubscriber') diff --git a/core/lib/Drupal/Core/Entity/EntityAccessCheck.php b/core/lib/Drupal/Core/Entity/EntityAccessCheck.php new file mode 100644 index 0000000..2cd2b64 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/EntityAccessCheck.php @@ -0,0 +1,52 @@ +getRequirements()); + } + + /** + * Implements \Drupal\Core\Access\AccessCheckInterface::access(). + * + * The value of the '_access_entity' key must be in the pattern + * 'slug.operation.' The slug corresponds to the named param {slug}. + * This will check a node for 'update' access: + * @code + * pattern: '/foo/{node}/bar' + * requirements: + * _access_entity: 'node.update' + * @endcode + */ + public function access(Route $route, Request $request) { + $requirements = $route->getRequirements(); + // Split up the slug and the operation. + list($slug, $operation) = explode('.', $requirements['_access_entity']); + // If this slug is in the request, and it is an entity, check its access. + if ($request->attributes->has($slug)) { + $entity = $request->attributes->get($slug); + if ($entity instanceof EntityInterface) { + return $entity->access($operation); + } + } + } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityRouteAccessTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityRouteAccessTest.php new file mode 100644 index 0000000..ce2ef71 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityRouteAccessTest.php @@ -0,0 +1,52 @@ + 'Entity Route Access', + 'description' => 'Tests route-based Entity access.', + 'group' => 'Entity API', + ); + } + + /** + * Tests access to delete an entity. + */ + public function testDelete() { + entity_create('entity_test', array())->save(); + + // Attempt to delete the entity without permission. + $this->drupalGet('entity_test/1/delete'); + $this->assertResponse(403); + + // Log in as a privileged user and delete the entity. + $this->drupalLogin($this->drupalCreateUser(array('administer entity_test content'))); + $this->drupalGet('entity_test/1/delete'); + $this->assertResponse(200); + + // Attempt to delete the entity again. + $this->drupalGet('entity_test/1/delete'); + $this->assertResponse(404); + } + +} diff --git a/core/modules/system/tests/modules/entity_test/entity_test.routing.yml b/core/modules/system/tests/modules/entity_test/entity_test.routing.yml new file mode 100644 index 0000000..fcb7ea4 --- /dev/null +++ b/core/modules/system/tests/modules/entity_test/entity_test.routing.yml @@ -0,0 +1,6 @@ +entity_test_access: + pattern: '/entity_test/{entity_test}/delete' + defaults: + _content: 'Drupal\entity_test\Controller\EntityTestController::deletePage' + requirements: + _access_entity: 'entity_test.delete' diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Controller/EntityTestController.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Controller/EntityTestController.php new file mode 100644 index 0000000..2cdb98a --- /dev/null +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Controller/EntityTestController.php @@ -0,0 +1,25 @@ +delete(); + return t('The test entity has been deleted.'); + } + +}