diff --git a/core/core.services.yml b/core/core.services.yml index 24ef51e..0d113d3 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -423,6 +423,11 @@ services: class: Drupal\Core\Theme\ThemeAccessCheck tags: - { name: access_check } + access_check.custom: + class: Drupal\Core\Access\CustomAccessCheck + arguments: ['@controller_resolver'] + tags: + - { name: access_check } maintenance_mode_subscriber: class: Drupal\Core\EventSubscriber\MaintenanceModeSubscriber tags: diff --git a/core/lib/Drupal/Core/Access/CustomAccessCheck.php b/core/lib/Drupal/Core/Access/CustomAccessCheck.php new file mode 100644 index 0000000..3dc4bab --- /dev/null +++ b/core/lib/Drupal/Core/Access/CustomAccessCheck.php @@ -0,0 +1,55 @@ +controllerResolver = $controller_resolver; + } + + /** + * {@inheritdoc} + */ + public function appliesTo() { + return array('_custom_access'); + } + + /** + * {@inheritdoc} + */ + public function access(Route $route, Request $request) { + $access_controller = $route->getRequirement('_custom_access'); + + $controller = $this->controllerResolver->getControllerFromDefinition($access_controller); + $arguments = $this->controllerResolver->getArguments($request, $controller); + + return call_user_func_array($controller, $arguments); + } + +} diff --git a/core/modules/toolbar/lib/Drupal/toolbar/Routing/ToolbarController.php b/core/modules/toolbar/lib/Drupal/toolbar/Routing/ToolbarController.php index 7404555..f16e287 100644 --- a/core/modules/toolbar/lib/Drupal/toolbar/Routing/ToolbarController.php +++ b/core/modules/toolbar/lib/Drupal/toolbar/Routing/ToolbarController.php @@ -7,7 +7,9 @@ namespace Drupal\toolbar\Routing; +use Drupal\Core\Access\AccessInterface; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Request; /** * Defines a controller for the toolbar module. @@ -27,4 +29,12 @@ public function subtreesJsonp() { return $response; } + /** + * Checks access for the subtree controller. + */ + public function checkSubTreeAccess(Request $request) { + $hash = $request->get('hash'); + return (\Drupal::currentUser('access toolbar') && ($hash == _toolbar_get_subtrees_hash())) ? AccessInterface::ALLOW : AccessInterface::DENY; + } + } diff --git a/core/modules/toolbar/toolbar.routing.yml b/core/modules/toolbar/toolbar.routing.yml index 609d0c7..a4aabb1 100644 --- a/core/modules/toolbar/toolbar.routing.yml +++ b/core/modules/toolbar/toolbar.routing.yml @@ -3,4 +3,4 @@ toolbar.subtrees: defaults: _controller: '\Drupal\toolbar\Routing\ToolbarController::subtreesJsonp' requirements: - _access_toolbar_subtree: 'TRUE' + _custom_access: '\Drupal\toolbar\Routing\ToolbarController::checkSubTreeAccess' diff --git a/core/tests/Drupal/Tests/Core/Access/CustomAccessCheckTest.php b/core/tests/Drupal/Tests/Core/Access/CustomAccessCheckTest.php new file mode 100644 index 0000000..5eb1305 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Access/CustomAccessCheckTest.php @@ -0,0 +1,127 @@ + 'Custom access check', + 'description' => 'Tests the custom access checker.', + 'group' => 'Access' + ); + } + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->controllerResolver = $this->getMock('Drupal\Core\Controller\ControllerResolverInterface'); + $this->accessChecker = new CustomAccessCheck($this->controllerResolver); + } + + + /** + * Tests the appliesTo method. + */ + public function testAppliesTo() { + $this->assertEquals($this->accessChecker->appliesTo(), array('_custom_access')); + } + + /** + * Test the access method. + */ + public function testAccess() { + $request = new Request(array()); + + $this->controllerResolver->expects($this->at(0)) + ->method('getControllerFromDefinition') + ->with('\Drupal\Tests\Core\Access\TestController::accessDeny') + ->will($this->returnValue(array(new TestController(), 'accessDeny'))); + + $this->controllerResolver->expects($this->at(1)) + ->method('getArguments') + ->will($this->returnValue(array())); + + $this->controllerResolver->expects($this->at(2)) + ->method('getControllerFromDefinition') + ->with('\Drupal\Tests\Core\Access\TestController::accessAllow') + ->will($this->returnValue(array(new TestController(), 'accessAllow'))); + + $this->controllerResolver->expects($this->at(3)) + ->method('getArguments') + ->will($this->returnValue(array())); + + $this->controllerResolver->expects($this->at(4)) + ->method('getControllerFromDefinition') + ->with('\Drupal\Tests\Core\Access\TestController::accessParameter') + ->will($this->returnValue(array(new TestController(), 'accessParameter'))); + + $this->controllerResolver->expects($this->at(5)) + ->method('getArguments') + ->will($this->returnValue(array('parameter' => 'TRUE'))); + + $route = new Route('/test-route', array(), array('_custom_access' => '\Drupal\Tests\Core\Access\TestController::accessDeny')); + $this->assertNull($this->accessChecker->access($route, $request)); + + $route = new Route('/test-route', array(), array('_custom_access' => '\Drupal\Tests\Core\Access\TestController::accessAllow')); + $this->assertTrue($this->accessChecker->access($route, $request)); + + $route = new Route('/test-route', array('parameter' => 'TRUE'), array('_custom_access' => '\Drupal\Tests\Core\Access\TestController::accessParameter')); + $this->assertTrue($this->accessChecker->access($route, $request)); + } + +} + +class TestController { + + public function accessAllow() { + return AccessInterface::ALLOW; + } + + public function accessDeny() { + return AccessInterface::DENY; + } + + public function accessParameter($parameter) { + if ($parameter == 'TRUE') { + return AccessInterface::ALLOW; + } + else { + return AccessInterface::DENY; + } + } + +}