reverted: --- b/core/modules/system/src/EventSubscriber/GroupRouteSubscriber.php +++ /dev/null @@ -1,146 +0,0 @@ -accessManager = $access_manager; - $this->menuLinkTree = $menu_link_tree; - $this->entityTypeManager = $entity_type_manager; - } - - /** - * {@inheritdoc} - */ - protected function alterRoutes(RouteCollection $collection) { - // Load all roles and leave only non-admin ones with necessary permission. - try { - $roles = $this->entityTypeManager->getStorage('user_role') - ->loadMultiple(); - $user_storage = $this->entityTypeManager->getStorage('user'); - } catch (\Exception $e) { - return; - } - $access_roles = []; - $admin_role = ''; - foreach ($roles as $role_id => $role) { - if ($role->isAdmin()) { - $admin_role = $role_id; - continue; - } - if ($role->hasPermission('access administration pages')) { - $access_roles[$role_id] = $user_storage->create([ - 'roles' => [ - $role_id, - ], - ]); - } - } - if (empty($admin_role) || empty($access_roles)) { - return; - } - foreach ($collection->all() as $route_id => $route) { - if ($route->hasOption('_group_route')) { - // Add admin role in order to restrict access for other roles. - $route_accessible_roles = [$admin_role]; - // Perform check. - $this->checkAccess($route_accessible_roles, $collection, $route_id, NULL, NULL, $access_roles); - $route->setRequirement('_role', (string) implode('', $route_accessible_roles)); - } - } - } - - /** - * Checks route and its children. - * - * @param array $route_accessible_roles - * Array with role names, which are allowed to access route. - * @param \Symfony\Component\Routing\RouteCollection $collection - * Routes collection. - * @param string $route_id - * Route ID. - * @param \Drupal\user\Entity\User $user - * User object for test. - * @param string $role - * User's role to be added in array. - * @param array $access_roles - * Array with test users for access checking. - */ - protected function checkAccess(array &$route_accessible_roles, RouteCollection $collection, $route_id, User $user = NULL, $role = NULL, array $access_roles = NULL) { - // Load menu links and check if route has any accessible children. - $parameters = new MenuTreeParameters(); - $parameters->setRoot($route_id) - ->excludeRoot() - ->setTopLevelOnly() - ->onlyEnabledLinks(); - $tree = $this->menuLinkTree->load(NULL, $parameters); - if (empty($tree)) { - if ($collection->get($route_id)->hasOption('_group_route')) { - return; - } - $route_accessible_roles[] = $role; - } - else { - foreach ($tree as $element_id => $element) { - $url = $element->link->getUrlObject(); - if (!empty($access_roles)) { - foreach ($access_roles as $route_role => $role_user) { - if ($this->accessManager->checkNamedRoute($url->getRouteName(), $url->getRouteParameters(), $role_user) && !in_array($route_role, $route_accessible_roles)) { - // Check if it is a _group_route with inaccessible children. - $this->checkAccess($route_accessible_roles, $collection, $element_id, $role_user, $route_role); - } - } - } - else { - if ($this->accessManager->checkNamedRoute($url->getRouteName(), $url->getRouteParameters(), $user) && !in_array($role, $route_accessible_roles)) { - $route_accessible_roles[] = $role; - } - } - } - } - } - -} only in patch2: unchanged: --- a/core/modules/system/tests/src/Functional/Menu/MenuAccessTest.php +++ b/core/modules/system/tests/src/Functional/Menu/MenuAccessTest.php @@ -17,7 +17,7 @@ class MenuAccessTest extends BrowserTestBase { * * @var array */ - protected static $modules = ['block', 'menu_test']; + public static $modules = ['block', 'menu_test', 'toolbar']; /** * {@inheritdoc} @@ -69,5 +69,53 @@ public function testMenuBlockLinksAccessCheck() { $this->assertSession()->linkByHrefNotExists('foo/asdf/b'); $this->assertSession()->linkByHrefNotExists('foo/asdf/c'); } + + /** + * Tests menu access as per user role permissions. + */ + public function testMenuAccessByUserRole() { + // Create an admin user and login. + $this->adminUser = $this->drupalCreateUser([ + 'administer site configuration', + 'access administration pages', + 'administer permissions', + 'administer users', + ]); + $this->drupalLogin($this->adminUser); + + // Create a test role. + $edit = [ + 'label' => 'Test role', + 'id' => 'test_role', + ]; + $this->drupalGet('admin/people/roles/add'); + $this->submitForm($edit, 'Save'); + $this->assertSession()->statusCodeEquals(200); + + // Give access to toolbar, theme and admin pages. + $edit = [ + 'test_role[access administration pages]' => TRUE, + 'test_role[view the administration theme]' => TRUE, + 'test_role[access toolbar]' => TRUE, + ]; + $this->drupalGet('admin/people/permissions/test_role'); + $this->submitForm($edit, 'Save permissions'); + $this->assertSession()->statusCodeEquals(200); + + // Create a user with the role created above and login with this user. + $webUser = $this->drupalCreateUser(); + $edit = [ + 'roles[test_role]' => 'test_role', + ]; + $this->drupalGet('user/' . $webUser->id() . '/edit'); + $this->submitForm($edit, 'Save'); + $this->assertSession()->statusCodeEquals(200); + $this->drupalLogout(); + $this->drupalLogin($webUser); + + // Verify that the structure menu item is not present in the toolbar. + $this->assertSession() + ->responseNotContains('class="toolbar-icon toolbar-icon-system-admin-structure"'); + } }