diff --git a/core/core.services.yml b/core/core.services.yml index 2b54b88..192af35 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -382,7 +382,7 @@ services: - [setRequest, ['@?request']] access_manager: class: Drupal\Core\Access\AccessManager - arguments: ['@router.route_provider', '@url_generator', '@paramconverter_manager', '@current_user'] + arguments: ['@router.route_provider', '@url_generator', '@paramconverter_manager'] calls: - [setContainer, ['@service_container']] - [setRequest, ['@?request']] @@ -390,6 +390,12 @@ services: class: Drupal\Core\EventSubscriber\AccessSubscriber tags: - { name: event_subscriber } + arguments: ['@access_manager', '@current_user'] + scope: request + access_route_subscriber: + class: Drupal\Core\EventSubscriber\AccessRouteSubscriber + tags: + - { name: event_subscriber } arguments: ['@access_manager'] access_check.default: class: Drupal\Core\Access\DefaultAccessCheck @@ -608,6 +614,7 @@ services: factory_method: authenticate factory_service: authentication arguments: ['@request'] + scope: request asset.css.collection_renderer: class: Drupal\Core\Asset\CssCollectionRenderer asset.css.collection_optimizer: diff --git a/core/lib/Drupal/Core/Access/AccessManager.php b/core/lib/Drupal/Core/Access/AccessManager.php index 00c981c..7e5cb6a 100644 --- a/core/lib/Drupal/Core/Access/AccessManager.php +++ b/core/lib/Drupal/Core/Access/AccessManager.php @@ -84,13 +84,6 @@ class AccessManager extends ContainerAware { protected $request; /** - * The current user. - * - * @var \Drupal\Core\Session\AccountInterface - */ - protected $account; - - /** * Constructs a AccessManager instance. * * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider @@ -99,14 +92,11 @@ class AccessManager extends ContainerAware { * The url generator. * @param \Drupal\Core\ParamConverter\ParamConverterManager $paramconverter_manager * The param converter manager. - * @param \Drupal\Core\Session\AccountInterface $account - * The current user. */ - public function __construct(RouteProviderInterface $route_provider, UrlGeneratorInterface $url_generator, ParamConverterManager $paramconverter_manager, AccountInterface $account) { + public function __construct(RouteProviderInterface $route_provider, UrlGeneratorInterface $url_generator, ParamConverterManager $paramconverter_manager) { $this->routeProvider = $route_provider; $this->urlGenerator = $url_generator; $this->paramConverterManager = $paramconverter_manager; - $this->account = $account; } /** @@ -190,6 +180,8 @@ protected function applies(Route $route) { * The route to check access to. * @param array $parameters * Optional array of values to substitute into the route path patern. + * @param \Drupal\Core\Session\AccountInterface $account + * The current user. * @param \Symfony\Component\HttpFoundation\Request $route_request * Optional incoming request object. If not provided, one will be built * using the route information and the current request from the container. @@ -197,7 +189,7 @@ protected function applies(Route $route) { * @return bool * Returns TRUE if the user has access to the route, otherwise FALSE. */ - public function checkNamedRoute($route_name, array $parameters = array(), Request $route_request = NULL) { + public function checkNamedRoute($route_name, array $parameters = array(), AccountInterface $account, Request $route_request = NULL) { try { $route = $this->routeProvider->getRouteByName($route_name, $parameters); if (empty($route_request)) { @@ -207,7 +199,7 @@ public function checkNamedRoute($route_name, array $parameters = array(), Reques $defaults[RouteObjectInterface::ROUTE_OBJECT] = $route; $route_request->attributes->add($this->paramConverterManager->enhance($defaults, $route_request)); } - return $this->check($route, $route_request); + return $this->check($route, $route_request, $account); } catch (RouteNotFoundException $e) { return FALSE; @@ -226,22 +218,21 @@ public function checkNamedRoute($route_name, array $parameters = array(), Reques * The route to check access to. * @param \Symfony\Component\HttpFoundation\Request $request * The incoming request object. + * @param \Drupal\Core\Session\AccountInterface $account + * The current account. * * @return bool * Returns TRUE if the user has access to the route, otherwise FALSE. - * - * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException - * If any access check denies access or none explicitly approve. */ - public function check(Route $route, Request $request) { + public function check(Route $route, Request $request, AccountInterface $account) { $checks = $route->getOption('_access_checks') ?: array(); $conjunction = $route->getOption('_access_mode') ?: 'ANY'; if ($conjunction == 'ALL') { - return $this->checkAll($checks, $route, $request); + return $this->checkAll($checks, $route, $request, $account); } else { - return $this->checkAny($checks, $route, $request); + return $this->checkAny($checks, $route, $request, $account); } } @@ -254,11 +245,13 @@ public function check(Route $route, Request $request) { * The route to check access to. * @param \Symfony\Component\HttpFoundation\Request $request * The incoming request object. + * @param \Drupal\Core\Session\AccountInterface $account + * The current user. * * @return bool * Returns TRUE if the user has access to the route, else FALSE. */ - protected function checkAll(array $checks, Route $route, Request $request) { + protected function checkAll(array $checks, Route $route, Request $request, AccountInterface $account) { $access = FALSE; foreach ($checks as $service_id) { @@ -266,7 +259,7 @@ protected function checkAll(array $checks, Route $route, Request $request) { $this->loadCheck($service_id); } - $service_access = $this->checks[$service_id]->access($route, $request, $this->account); + $service_access = $this->checks[$service_id]->access($route, $request, $account); if ($service_access === AccessInterface::ALLOW) { $access = TRUE; } @@ -289,11 +282,13 @@ protected function checkAll(array $checks, Route $route, Request $request) { * The route to check access to. * @param \Symfony\Component\HttpFoundation\Request $request * The incoming request object. + * @param \Drupal\Core\Session\AccountInterface $account + * The current user. * * @return bool * Returns TRUE if the user has access to the route, else FALSE. */ - protected function checkAny(array $checks, $route, $request) { + protected function checkAny(array $checks, $route, $request, AccountInterface $account) { // No checks == deny by default. $access = FALSE; @@ -302,7 +297,7 @@ protected function checkAny(array $checks, $route, $request) { $this->loadCheck($service_id); } - $service_access = $this->checks[$service_id]->access($route, $request, $this->account); + $service_access = $this->checks[$service_id]->access($route, $request, $account); if ($service_access === AccessInterface::ALLOW) { $access = TRUE; } diff --git a/core/lib/Drupal/Core/EventSubscriber/AccessSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/AccessSubscriber.php index 6f18839..4c0e13f 100644 --- a/core/lib/Drupal/Core/EventSubscriber/AccessSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/AccessSubscriber.php @@ -7,6 +7,7 @@ namespace Drupal\Core\EventSubscriber; +use Drupal\Core\Session\AccountInterface; use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseEvent; @@ -22,14 +23,31 @@ class AccessSubscriber implements EventSubscriberInterface { /** + * The access manager. + * + * @var \Drupal\Core\Access\AccessManager + */ + protected $accessManager; + + /** + * The current user. + * + * @var \Drupal\Core\Session\AccountInterface + */ + protected $account; + + /** * Constructs a new AccessSubscriber. * * @param \Drupal\Core\Access\AccessManager $access_manager * The access check manager that will be responsible for applying * AccessCheckers against routes. + * @param \Drupal\Core\Session\AccountInterface $account + * The current account. */ - public function __construct(AccessManager $access_manager) { + public function __construct(AccessManager $access_manager, AccountInterface $account) { $this->accessManager = $access_manager; + $this->account = $account; } /** @@ -37,6 +55,9 @@ public function __construct(AccessManager $access_manager) { * * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event * The Event to process. + * + * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException + * Thrown when the user does not have access. */ public function onKernelRequestAccessCheck(GetResponseEvent $event) { $request = $event->getRequest(); @@ -46,23 +67,13 @@ public function onKernelRequestAccessCheck(GetResponseEvent $event) { return; } - $access = $this->accessManager->check($request->attributes->get(RouteObjectInterface::ROUTE_OBJECT), $request); + $access = $this->accessManager->check($request->attributes->get(RouteObjectInterface::ROUTE_OBJECT), $request, $this->account); if (!$access) { throw new AccessDeniedHttpException(); } } /** - * Apply access checks to routes. - * - * @param \Drupal\Core\Routing\RouteBuildEvent $event - * The event to process. - */ - public function onRoutingRouteAlterSetAccessCheck(RouteBuildEvent $event) { - $this->accessManager->setChecks($event->getRouteCollection()); - } - - /** * Registers the methods in this class that should be listeners. * * @return array @@ -70,9 +81,8 @@ public function onRoutingRouteAlterSetAccessCheck(RouteBuildEvent $event) { */ static function getSubscribedEvents() { $events[KernelEvents::REQUEST][] = array('onKernelRequestAccessCheck', 30); - // Setting very low priority to ensure access checks are run after alters. - $events[RoutingEvents::ALTER][] = array('onRoutingRouteAlterSetAccessCheck', 0); return $events; } + } diff --git a/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php b/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php index bfc6c0c..f1cc4a9 100644 --- a/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php @@ -156,7 +156,7 @@ public function testCheck() { // Check check without any access checker defined yet. foreach ($this->routeCollection->all() as $route) { - $this->assertFalse($this->accessManager->check($route, $request)); + $this->assertFalse($this->accessManager->check($route, $request, $this->account)); } $this->setupAccessChecker(); @@ -164,14 +164,14 @@ public function testCheck() { // An access checker got setup, but the routes haven't been setup using // setChecks. foreach ($this->routeCollection->all() as $route) { - $this->assertFalse($this->accessManager->check($route, $request)); + $this->assertFalse($this->accessManager->check($route, $request, $this->account)); } $this->accessManager->setChecks($this->routeCollection); - $this->assertFalse($this->accessManager->check($this->routeCollection->get('test_route_1'), $request)); - $this->assertTrue($this->accessManager->check($this->routeCollection->get('test_route_2'), $request)); - $this->assertFalse($this->accessManager->check($this->routeCollection->get('test_route_3'), $request)); + $this->assertFalse($this->accessManager->check($this->routeCollection->get('test_route_1'), $request, $this->account)); + $this->assertTrue($this->accessManager->check($this->routeCollection->get('test_route_2'), $request, $this->account)); + $this->assertFalse($this->accessManager->check($this->routeCollection->get('test_route_3'), $request, $this->account)); } /** @@ -296,7 +296,7 @@ public function testCheckConjunctions($conjunction, $name, $condition_one, $cond $route_collection->add($name, $route); $this->accessManager->setChecks($route_collection); - $this->assertSame($this->accessManager->check($route, $request), $expected_access); + $this->assertSame($this->accessManager->check($route, $request, $this->account), $expected_access); } /** @@ -325,14 +325,14 @@ public function testCheckNamedRoute() { // Tests the access with routes without parameters. $request = new Request(); - $this->assertTrue($this->accessManager->checkNamedRoute('test_route_2', array(), $request)); - $this->assertFalse($this->accessManager->checkNamedRoute('test_route_3', array(), $request)); + $this->assertTrue($this->accessManager->checkNamedRoute('test_route_2', array(), $this->account, $request)); + $this->assertFalse($this->accessManager->checkNamedRoute('test_route_3', array(), $this->account, $request)); // Tests the access with routes with parameters with given request. $request = new Request(); $request->attributes->set('value', 'example'); $request->attributes->set('value2', 'example2'); - $this->assertTrue($this->accessManager->checkNamedRoute('test_route_4', array(), $request)); + $this->assertTrue($this->accessManager->checkNamedRoute('test_route_4', array(), $this->account, $request)); // Tests the access with routes without given request. $this->accessManager->setRequest(new Request()); @@ -346,8 +346,8 @@ public function testCheckNamedRoute() { ->will($this->returnValue(array())); // Tests the access with routes with parameters without given request. - $this->assertTrue($this->accessManager->checkNamedRoute('test_route_2', array())); - $this->assertTrue($this->accessManager->checkNamedRoute('test_route_4', array('value' => 'example'))); + $this->assertTrue($this->accessManager->checkNamedRoute('test_route_2', array(), $this->account)); + $this->assertTrue($this->accessManager->checkNamedRoute('test_route_4', array('value' => 'example'), $this->account)); } /** @@ -408,7 +408,7 @@ public function testCheckNamedRouteWithUpcastedValues() { $this->accessManager->addCheckService('test_access'); $this->accessManager->setChecks($this->routeCollection); - $this->assertFalse($this->accessManager->checkNamedRoute('test_route_1', array('value' => 'example'))); + $this->assertFalse($this->accessManager->checkNamedRoute('test_route_1', array('value' => 'example'), $this->account)); } /** @@ -423,7 +423,7 @@ public function testCheckNamedRouteWithNonExistingRoute() { $this->setupAccessChecker(); - $this->assertFalse($this->accessManager->checkNamedRoute('test_route_1'), 'A non existing route lead to access.'); + $this->assertFalse($this->accessManager->checkNamedRoute('test_route_1', array(), $this->account), 'A non existing route lead to access.'); } /**