diff --git a/core/modules/menu_link_content/src/MenuLinkContentAccessControlHandler.php b/core/modules/menu_link_content/src/MenuLinkContentAccessControlHandler.php index c69349e9e934bef0f263d28169b2ba95c035d42f..eadf04532c5b17a720d12ec59fef0e728f777754 100644 --- a/core/modules/menu_link_content/src/MenuLinkContentAccessControlHandler.php +++ b/core/modules/menu_link_content/src/MenuLinkContentAccessControlHandler.php @@ -59,11 +59,12 @@ protected function checkAccess(EntityInterface $entity, $operation, AccountInter return AccessResult::neutral("The 'administer menu' permission is required.")->cachePerPermissions(); } else { - // If there is a URL, this is an external link so always accessible. + // Assume that access is allowed. $access = AccessResult::allowed()->cachePerPermissions()->addCacheableDependency($entity); /** @var \Drupal\menu_link_content\MenuLinkContentInterface $entity */ - // We allow access, but only if the link is accessible as well. - if (($url_object = $entity->getUrlObject()) && $url_object->isRouted()) { + // If the link is routed determine whether the user has access unless + // they have the 'link to any page' permission. + if (!$account->hasPermission('link to any page') && ($url_object = $entity->getUrlObject()) && $url_object->isRouted()) { $link_access = $this->accessManager->checkNamedRoute($url_object->getRouteName(), $url_object->getRouteParameters(), $account, TRUE); $access = $access->andIf($link_access); } diff --git a/core/modules/menu_link_content/src/Tests/MenuLinkContentFormTest.php b/core/modules/menu_link_content/src/Tests/MenuLinkContentFormTest.php index c8244fe089cf433c62fca0534ccd966874c433c3..1e726fc2f93a463a72a02c2ed9ee3767ee86ae13 100644 --- a/core/modules/menu_link_content/src/Tests/MenuLinkContentFormTest.php +++ b/core/modules/menu_link_content/src/Tests/MenuLinkContentFormTest.php @@ -2,6 +2,7 @@ namespace Drupal\menu_link_content\Tests; +use Drupal\menu_link_content\Entity\MenuLinkContent; use Drupal\simpletest\WebTestBase; /** @@ -20,13 +21,53 @@ class MenuLinkContentFormTest extends WebTestBase { 'menu_link_content', ]; + /** + * User with 'administer menu' and 'link to any page' permission. + * + * @var \Drupal\user\Entity\User + */ + + protected $adminUser; + + /** + * User with only 'administer menu' permission. + * + * @var \Drupal\user\Entity\User + */ + + protected $basicUser; + /** * {@inheritdoc} */ protected function setUp() { parent::setUp(); - $web_user = $this->drupalCreateUser(['administer menu']); - $this->drupalLogin($web_user); + $this->adminUser = $this->drupalCreateUser(['administer menu', 'link to any page']); + $this->basicUser = $this->drupalCreateUser(['administer menu']); + $this->drupalLogin($this->adminUser); + } + + /** + * Tests the 'link to any page' permission for a restricted page. + */ + public function testMenuLinkContentFormLinkToAnyPage() { + $menu_link = MenuLinkContent::create([ + 'title' => 'Menu link test', + 'provider' => 'menu_link_content', + 'menu_name' => 'admin', + 'link' => ['uri' => 'internal:/user/login'], + ]); + $menu_link->save(); + + // The user should be able to edit a menu link to the page, even though + // the user cannot access the page itself. + $this->drupalGet('/admin/structure/menu/item/' . $menu_link->id() . '/edit'); + $this->assertResponse(200); + + $this->drupalLogin($this->basicUser); + + $this->drupalGet('/admin/structure/menu/item/' . $menu_link->id() . '/edit'); + $this->assertResponse(403); } /**