diff --git a/core/lib/Drupal/Core/Access/AccessManager.php b/core/lib/Drupal/Core/Access/AccessManager.php index f5b3733df09d49dadbdf727d111317be7ac0f0ae..f33d47f34518c3d4eeb17e91967caa675dcc281b 100644 --- a/core/lib/Drupal/Core/Access/AccessManager.php +++ b/core/lib/Drupal/Core/Access/AccessManager.php @@ -159,13 +159,11 @@ protected function applies(Route $route) { $checks[] = $service_id; } } - // This means appliesTo() method was empty. Iterate through all checkers. - else { - foreach ($this->dynamicRequirementMap as $service_id) { - if ($this->checks[$service_id]->applies($route)) { - $checks[] = $service_id; - } - } + } + // Finally, see if any dynamic access checkers apply. + foreach ($this->dynamicRequirementMap as $service_id) { + if ($this->checks[$service_id]->applies($route)) { + $checks[] = $service_id; } } diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 79d8b8f54449497ff2fc2a899eba34cbebf9374a..7541fb26af3309cce81ca11a373c069d2a27a106 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -645,6 +645,9 @@ protected function drupalLogin(AccountInterface $account) { if ($pass) { $this->loggedInUser = $account; $this->container->set('current_user', $account); + // @todo Temporary workaround for not being able to use synchronized + // services in non dumped container. + $this->container->get('access_subscriber')->setCurrentUser($account); } } diff --git a/core/modules/user/lib/Drupal/user/Plugin/views/access/Role.php b/core/modules/user/lib/Drupal/user/Plugin/views/access/Role.php index d8122706f6b4ee1f8b92e8bd30ffcf6f4494e55d..1c4fecc4a60be0c85e1a5c44af96aedeedb66f60 100644 --- a/core/modules/user/lib/Drupal/user/Plugin/views/access/Role.php +++ b/core/modules/user/lib/Drupal/user/Plugin/views/access/Role.php @@ -42,7 +42,9 @@ public function access(AccountInterface $account) { * {@inheritdoc} */ public function alterRouteDefinition(Route $route) { - $route->setRequirement('_role_id', $this->options['role']); + if ($this->options['role']) { + $route->setRequirement('_role', (string) implode(',', $this->options['role'])); + } } public function summaryTitle() { @@ -74,7 +76,7 @@ public function buildOptionsForm(&$form, &$form_state) { '#type' => 'checkboxes', '#title' => t('Role'), '#default_value' => $this->options['role'], - '#options' => array_map('check_plain', $this->getRoles()), + '#options' => array_map('\Drupal\Component\Utility\String::checkPlain', user_role_names()), '#description' => t('Only the checked roles will be able to access this display. Note that users with "access all views" can see any view, regardless of role.'), ); } diff --git a/core/modules/user/lib/Drupal/user/Tests/Views/AccessRoleTest.php b/core/modules/user/lib/Drupal/user/Tests/Views/AccessRoleTest.php index 7218046381145a8a885950c72409b84a0d0f92df..df4a6a72d483f4345555e9cbd5c198ef5a160245 100644 --- a/core/modules/user/lib/Drupal/user/Tests/Views/AccessRoleTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/Views/AccessRoleTest.php @@ -8,6 +8,9 @@ namespace Drupal\user\Tests\Views; use Drupal\user\Plugin\views\access\Role; +use Drupal\views\Views; +use Drupal\views\ViewStorageInterface; +use Symfony\Component\HttpFoundation\Request; /** * Tests views role access plugin. @@ -35,19 +38,36 @@ public static function getInfo() { * Tests role access plugin. */ function testAccessRole() { - $view = views_get_view('test_access_role'); - $view->setDisplay(); - - $view->displayHandlers->get('default')->options['access']['options']['role'] = array( + /** @var \Drupal\views\ViewStorageInterface $view */ + $view = \Drupal::entityManager()->getStorageController('view')->load('test_access_role'); + $display = &$view->getDisplay('default'); + $display['display_options']['access']['options']['role'] = array( $this->normalRole => $this->normalRole, ); + $view->save(); + + $executable = Views::executableFactory()->get($view); + $executable->setDisplay('page_1'); - $access_plugin = $view->display_handler->getPlugin('access'); + $access_plugin = $executable->display_handler->getPlugin('access'); $this->assertTrue($access_plugin instanceof Role, 'Make sure the right class got instantiated.'); - $this->assertTrue($view->display_handler->access($this->adminUser), 'Admin-Account should be able to access the view everytime'); - $this->assertFalse($view->display_handler->access($this->webUser)); - $this->assertTrue($view->display_handler->access($this->normalUser)); + // Test the access() method on the access plugin. + $this->assertTrue($executable->display_handler->access($this->adminUser), 'Admin-Account should be able to access the view everytime'); + $this->assertFalse($executable->display_handler->access($this->webUser)); + $this->assertTrue($executable->display_handler->access($this->normalUser)); + + $this->drupalLogin($this->adminUser); + $this->drupalGet('test-role'); + $this->assertResponse(200); + + $this->drupalLogin($this->webUser); + $this->drupalGet('test-role'); + $this->assertResponse(403); + + $this->drupalLogin($this->normalUser); + $this->drupalGet('test-role'); + $this->assertResponse(200); } } diff --git a/core/modules/user/lib/Drupal/user/Tests/Views/AccessRoleUITest.php b/core/modules/user/lib/Drupal/user/Tests/Views/AccessRoleUITest.php new file mode 100644 index 0000000000000000000000000000000000000000..3ae1dc6552d1fc2810f1297e4ce77f644eb48ae3 --- /dev/null +++ b/core/modules/user/lib/Drupal/user/Tests/Views/AccessRoleUITest.php @@ -0,0 +1,71 @@ +<?php + +/** + * @file + * Contains \Drupal\user\Tests\Views\AccessRoleUITest. + */ + +namespace Drupal\user\Tests\Views; + +use Drupal\views\Tests\ViewTestData; +use Drupal\views_ui\Tests\UITestBase; + +/** + * Tests views role access plugin UI. + * + * @see Drupal\user\Plugin\views\access\Role + */ +class AccessRoleUITest extends UITestBase { + + /** + * Views used by this test. + * + * @var array + */ + public static $testViews = array('test_access_role'); + + /** + * Modules to enable. + * + * @var array + */ + public static $modules = array('user', 'user_test_views'); + + /** + * {@inheritdoc} + */ + public static function getInfo() { + return array( + 'name' => 'User: Access role (UI)', + 'description' => 'Tests views role access plugin UI.', + 'group' => 'Views module integration', + ); + } + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + ViewTestData::createTestViews(get_class($this), array('user_test_views')); + } + + /** + * Tests the role access plugin UI. + */ + public function testAccessRoleUI() { + $entity_manager = $this->container->get('entity.manager'); + $entity_manager->getStorageController('user_role')->create(array('id' => 'custom_role', 'label' => 'Custom role'))->save(); + $access_url = "admin/structure/views/nojs/display/test_access_role/default/access_options"; + $this->drupalPostForm($access_url, array('access_options[role][custom_role]' => 1), t('Apply')); + $this->assertResponse(200); + + $this->drupalPostForm(NULL, array(), t('Save')); + $view = $entity_manager->getStorageController('view')->load('test_access_role'); + + $display = $view->getDisplay('default'); + $this->assertEqual($display['display_options']['access']['options']['role'], array('custom_role' => 'custom_role')); + } + +} diff --git a/core/modules/user/lib/Drupal/user/Tests/Views/AccessTestBase.php b/core/modules/user/lib/Drupal/user/Tests/Views/AccessTestBase.php index 4ec709d9bdf9ab9e82754563569cd8fc790a1fe4..5fac787d6884b31a9c5bc5f0d8e01e6a6afe8881 100644 --- a/core/modules/user/lib/Drupal/user/Tests/Views/AccessTestBase.php +++ b/core/modules/user/lib/Drupal/user/Tests/Views/AccessTestBase.php @@ -60,6 +60,7 @@ protected function setUp() { $this->normalRole = $this->drupalCreateRole(array()); $this->normalUser = $this->drupalCreateUser(array('views_test_data test permission')); $this->normalUser->addRole($this->normalRole); + $this->normalUser->save(); // @todo when all the plugin information is cached make a reset function and // call it here. } diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_access_role.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_access_role.yml index 870b4bbe2e3338eb5bcf7207094e54bec3c768d0..f971f75de3c3e4b40290f71bd51c01a7a4560589 100644 --- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_access_role.yml +++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_access_role.yml @@ -1,10 +1,16 @@ -base_table: node +base_table: views_test_data core: '8' description: '' status: '1' display: default: display_options: + fields: + id: + id: id + field: id + table: views_test_data + plugin_id: numeric access: type: role cache: @@ -21,6 +27,13 @@ display: display_title: Master id: default position: '0' + page_1: + display_options: + path: test-role + display_plugin: page + display_title: Page + id: page_1 + position: '1' label: '' id: test_access_role tag: '' diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/display/PathPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/display/PathPluginBase.php index 1879e13aacb4f51287cb2f9d437ac5dd5ef09024..58a46d7c050658a4cbccd3e123edd2099571c4e3 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/display/PathPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/PathPluginBase.php @@ -186,6 +186,10 @@ protected function getRoute($view_id, $display_id) { $access_plugin = Views::pluginManager('access')->createInstance('none'); } $access_plugin->alterRouteDefinition($route); + // @todo Figure out whether _access_mode ANY is the proper one. This is + // particular important for altering routes. + $route->setOption('_access_mode', 'ANY'); + return $route; } diff --git a/core/modules/views/lib/Drupal/views/ViewsAccessCheck.php b/core/modules/views/lib/Drupal/views/ViewsAccessCheck.php index 483f5821a1d1484457de8082d07ae0dedb286d9d..8a81fb70ef04fb4747cd9f8d7779dd966db73578 100644 --- a/core/modules/views/lib/Drupal/views/ViewsAccessCheck.php +++ b/core/modules/views/lib/Drupal/views/ViewsAccessCheck.php @@ -7,7 +7,7 @@ namespace Drupal\views; -use Drupal\Core\Access\StaticAccessCheckInterface; +use Drupal\Core\Access\AccessCheckInterface; use Drupal\Core\Session\AccountInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Route; @@ -17,13 +17,13 @@ * * @todo We could leverage the permission one as well? */ -class ViewsAccessCheck implements StaticAccessCheckInterface { +class ViewsAccessCheck implements AccessCheckInterface { /** * {@inheritdoc} */ - public function appliesTo() { - return array('views_id'); + public function applies(Route $route) { + return $route->hasDefault('view_id'); } /** diff --git a/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php b/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php index 740191c4a375e9123fb0ca89e70932d5593957f7..689cdf94464ae56d8bef2ebd27659edf44d59134 100644 --- a/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php @@ -146,6 +146,37 @@ public function testSetChecks() { $this->assertEquals($this->routeCollection->get('test_route_3')->getOption('_access_checks'), array('test_access_default')); } + /** + * Tests setChecks with a dynamic access checker. + */ + public function testSetChecksWithDynamicAccessChecker() { + // Setup the access manager. + $this->accessManager = new AccessManager($this->routeProvider, $this->urlGenerator, $this->paramConverter, $this->account); + $this->accessManager->setContainer($this->container); + + // Setup the dynamic access checker. + $access_check = $this->getMock('Drupal\Core\Access\AccessCheckInterface'); + $this->container->set('test_access', $access_check); + $this->accessManager->addCheckService('test_access'); + + $route = new Route('/test-path', array(), array('_foo' => '1', '_bar' => '1')); + $route2 = new Route('/test-path', array(), array('_foo' => '1', '_bar' => '2')); + $collection = new RouteCollection(); + $collection->add('test_route', $route); + $collection->add('test_route2', $route2); + + $access_check->expects($this->exactly(2)) + ->method('applies') + ->with($this->isInstanceOf('Symfony\Component\Routing\Route')) + ->will($this->returnCallback(function (Route $route) { + return $route->getRequirement('_bar') == 2; + })); + + $this->accessManager->setChecks($collection); + $this->assertEmpty($route->getOption('_access_checks')); + $this->assertEquals(array('test_access'), $route2->getOption('_access_checks')); + } + /** * Tests \Drupal\Core\Access\AccessManager::check(). */