Issue #2012916 by andypost, Berdir, pwieck: Implement access controller for the menu and menu link entity.

8.0.x
Alex Pott 2013-08-13 09:32:25 -05:00
parent 7833e61c45
commit 972406d591
11 changed files with 77 additions and 73 deletions

View File

@ -1,37 +0,0 @@
<?php
/**
* @file
* Contains \Drupal\menu\Access\DeleteLinkAccessCheck.
*/
namespace Drupal\menu\Access;
use Drupal\Core\Access\StaticAccessCheckInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\HttpFoundation\Request;
/**
* Access check for menu link delete routes.
*/
class DeleteLinkAccessCheck implements StaticAccessCheckInterface {
/**
* {@inheritdoc}
*/
public function appliesTo() {
return array('_access_menu_delete_link');
}
/**
* {@inheritdoc}
*/
public function access(Route $route, Request $request) {
if (user_access('administer menu') && $menu_link = $request->attributes->get('menu_link')) {
// Links defined via hook_menu may not be deleted. Updated items are an
// exception, as they can be broken.
return $menu_link->module !== 'system' || $menu_link->updated;
}
return FALSE;
}
}

View File

@ -174,10 +174,8 @@ class MenuFormController extends EntityFormController implements EntityControlle
*/ */
protected function actions(array $form, array &$form_state) { protected function actions(array $form, array &$form_state) {
$actions = parent::actions($form, $form_state); $actions = parent::actions($form, $form_state);
$menu = $this->entity;
$system_menus = menu_list_system_menus(); $actions['delete']['#access'] = !$this->entity->isNew() && $this->entity->access('delete');
$actions['delete']['#access'] = !$menu->isNew() && !isset($system_menus[$menu->id()]);
// Add the language configuration submit handler. This is needed because the // Add the language configuration submit handler. This is needed because the
// submit button has custom submit handlers. // submit button has custom submit handlers.
@ -223,8 +221,10 @@ class MenuFormController extends EntityFormController implements EntityControlle
*/ */
public function save(array $form, array &$form_state) { public function save(array $form, array &$form_state) {
$menu = $this->entity; $menu = $this->entity;
// @todo Get rid of menu_list_system_menus() https://drupal.org/node/1882552
// Supposed menu item declared by hook_menu()
// Should be moved to submitOverviewForm()
$system_menus = menu_list_system_menus(); $system_menus = menu_list_system_menus();
if (!$menu->isNew() || isset($system_menus[$menu->id()])) { if (!$menu->isNew() || isset($system_menus[$menu->id()])) {
$this->submitOverviewForm($form, $form_state); $this->submitOverviewForm($form, $form_state);
} }
@ -354,31 +354,27 @@ class MenuFormController extends EntityFormController implements EntityControlle
); );
// Build a list of operations. // Build a list of operations.
$operations = array(); $operations = array();
$links = array(); $operations['edit'] = array(
$links['edit'] = array(
'title' => t('Edit'), 'title' => t('Edit'),
'href' => 'admin/structure/menu/item/' . $item['mlid'] . '/edit', 'href' => 'admin/structure/menu/item/' . $item['mlid'] . '/edit',
); );
$operations['edit'] = array('#type' => 'link', '#title' => t('Edit'), '#href' => 'admin/structure/menu/item/' . $item['mlid'] . '/edit');
// Only items created by the menu module can be deleted. // Only items created by the menu module can be deleted.
if ($item['module'] == 'menu' || $item['updated'] == 1) { if ($item->access('delete')) {
$links['delete'] = array( $operations['delete'] = array(
'title' => t('Delete'), 'title' => t('Delete'),
'href' => 'admin/structure/menu/item/' . $item['mlid'] . '/delete', 'href' => 'admin/structure/menu/item/' . $item['mlid'] . '/delete',
); );
$operations['delete'] = array('#type' => 'link', '#title' => t('Delete'), '#href' => 'admin/structure/menu/item/' . $item['mlid'] . '/delete');
} }
// Set the reset column. // Set the reset column.
elseif ($item['module'] == 'system' && $item['customized']) { elseif ($item->access('reset')) {
$links['reset'] = array( $operations['reset'] = array(
'title' => t('Reset'), 'title' => t('Reset'),
'href' => 'admin/structure/menu/item/' . $item['mlid'] . '/reset', 'href' => 'admin/structure/menu/item/' . $item['mlid'] . '/reset',
); );
$operations['reset'] = array('#type' => 'link', '#title' => t('Reset'), '#href' => 'admin/structure/menu/item/' . $item['mlid'] . '/reset');
} }
$form[$mlid]['operations'] = array( $form[$mlid]['operations'] = array(
'#type' => 'operations', '#type' => 'operations',
'#links' => $links, '#links' => $operations,
); );
} }

View File

@ -49,16 +49,16 @@ class MenuListController extends ConfigEntityListController {
if (isset($operations['edit'])) { if (isset($operations['edit'])) {
$operations['edit']['title'] = t('Edit menu'); $operations['edit']['title'] = t('Edit menu');
$operations['add'] = array(
'title' => t('Add link'),
'href' => $uri['path'] . '/add',
'options' => $uri['options'],
'weight' => 20,
);
} }
if (isset($operations['delete'])) { if (isset($operations['delete'])) {
$operations['delete']['title'] = t('Delete menu'); $operations['delete']['title'] = t('Delete menu');
} }
$operations['add'] = array(
'title' => t('Add link'),
'href' => $uri['path'] . '/add',
'options' => $uri['options'],
'weight' => 20,
);
return $operations; return $operations;
} }

View File

@ -125,7 +125,6 @@ function menu_menu() {
*/ */
function menu_entity_info(&$entity_info) { function menu_entity_info(&$entity_info) {
$entity_info['menu']['controllers']['list'] = 'Drupal\menu\MenuListController'; $entity_info['menu']['controllers']['list'] = 'Drupal\menu\MenuListController';
$entity_info['menu']['controllers']['access'] = 'Drupal\menu\MenuAccessController';
$entity_info['menu']['uri_callback'] = 'menu_uri'; $entity_info['menu']['uri_callback'] = 'menu_uri';
$entity_info['menu']['controllers']['form'] = array( $entity_info['menu']['controllers']['form'] = array(
'add' => 'Drupal\menu\MenuFormController', 'add' => 'Drupal\menu\MenuFormController',

View File

@ -24,28 +24,28 @@ menu_link_add:
defaults: defaults:
_content: '\Drupal\menu\Controller\MenuController::addLink' _content: '\Drupal\menu\Controller\MenuController::addLink'
requirements: requirements:
_permission: 'administer menu' _entity_create_access: 'menu_link'
menu_link_edit: menu_link_edit:
pattern: '/admin/structure/menu/item/{menu_link}/edit' pattern: '/admin/structure/menu/item/{menu_link}/edit'
defaults: defaults:
_entity_form: 'menu_link' _entity_form: 'menu_link'
requirements: requirements:
_permission: 'administer menu' _entity_access: 'menu_link.update'
menu_link_reset: menu_link_reset:
pattern: 'admin/structure/menu/item/{menu_link}/reset' pattern: 'admin/structure/menu/item/{menu_link}/reset'
defaults: defaults:
_entity_form: 'menu_link.reset' _entity_form: 'menu_link.reset'
requirements: requirements:
_permission: 'administer menu' _entity_access: 'menu_link.reset'
menu_link_delete: menu_link_delete:
pattern: 'admin/structure/menu/item/{menu_link}/delete' pattern: 'admin/structure/menu/item/{menu_link}/delete'
defaults: defaults:
_entity_form: 'menu_link.delete' _entity_form: 'menu_link.delete'
requirements: requirements:
_access_menu_delete_link: 'TRUE' _entity_access: 'menu_link.delete'
menu_menu_add: menu_menu_add:
pattern: '/admin/structure/menu/add' pattern: '/admin/structure/menu/add'

View File

@ -1,5 +0,0 @@
services:
access_check.menu.delete_link:
class: Drupal\menu\Access\DeleteLinkAccessCheck
tags:
- { name: access_check }

View File

@ -0,0 +1,48 @@
<?php
/**
* @file
* Contains \Drupal\menu_link\MenuLinkAccessController.
*/
namespace Drupal\menu_link;
use Drupal\Core\Entity\EntityAccessController;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Defines an access controller for the menu link entity.
*
* @see \Drupal\menu_link\Plugin\Core\Entity\MenuLink
*/
class MenuLinkAccessController extends EntityAccessController {
/**
* {@inheritdoc}
*/
protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
$access = $account->hasPermission('administer menu');
if ($access) {
switch ($operation) {
case 'reset':
// Reset allowed for items defined via hook_menu() and customized.
return $entity->module == 'system' && $entity->customized;
case 'delete':
// Only items created by the menu module can be deleted.
return $entity->module == 'menu' || $entity->updated == 1;
}
}
return $access;
}
/**
* {@inheritdoc}
*/
protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
return $account->hasPermission('administer menu');
}
}

View File

@ -208,7 +208,7 @@ class MenuLinkFormController extends EntityFormController implements EntityContr
protected function actions(array $form, array &$form_state) { protected function actions(array $form, array &$form_state) {
$element = parent::actions($form, $form_state); $element = parent::actions($form, $form_state);
$element['submit']['#button_type'] = 'primary'; $element['submit']['#button_type'] = 'primary';
$element['delete']['#access'] = $this->entity->module == 'menu'; $element['delete']['#access'] = $this->entity->access('delete');
return $element; return $element;
} }

View File

@ -28,6 +28,7 @@ use Drupal\Core\Entity\Entity;
* module = "menu_link", * module = "menu_link",
* controllers = { * controllers = {
* "storage" = "Drupal\menu_link\MenuLinkStorageController", * "storage" = "Drupal\menu_link\MenuLinkStorageController",
* "access" = "Drupal\menu_link\MenuLinkAccessController",
* "render" = "Drupal\Core\Entity\EntityRenderController", * "render" = "Drupal\Core\Entity\EntityRenderController",
* "form" = { * "form" = {
* "default" = "Drupal\menu_link\MenuLinkFormController" * "default" = "Drupal\menu_link\MenuLinkFormController"

View File

@ -2,10 +2,10 @@
/** /**
* @file * @file
* Contains \Drupal\menu\MenuAccessController. * Contains \Drupal\system\MenuAccessController.
*/ */
namespace Drupal\menu; namespace Drupal\system;
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityAccessController; use Drupal\Core\Entity\EntityAccessController;
@ -25,6 +25,7 @@ class MenuAccessController extends EntityAccessController {
} }
elseif ($operation == 'delete') { elseif ($operation == 'delete') {
// System menus could not be deleted. // System menus could not be deleted.
// @todo Refactor in https://drupal.org/node/1882552
$system_menus = menu_list_system_menus(); $system_menus = menu_list_system_menus();
if (isset($system_menus[$entity->id()])) { if (isset($system_menus[$entity->id()])) {
return FALSE; return FALSE;
@ -32,7 +33,7 @@ class MenuAccessController extends EntityAccessController {
} }
if (in_array($operation, array('update', 'delete'))) { if (in_array($operation, array('update', 'delete'))) {
return user_access('administer menu', $account); return $account->hasPermission('administer menu');
} }
} }
@ -40,7 +41,7 @@ class MenuAccessController extends EntityAccessController {
* {@inheritdoc} * {@inheritdoc}
*/ */
protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
return user_access('administer menu', $account); return $account->hasPermission('administer menu');
} }
} }

View File

@ -20,7 +20,8 @@ use Drupal\system\MenuInterface;
* label = @Translation("Menu"), * label = @Translation("Menu"),
* module = "system", * module = "system",
* controllers = { * controllers = {
* "storage" = "Drupal\Core\Config\Entity\ConfigStorageController" * "storage" = "Drupal\Core\Config\Entity\ConfigStorageController",
* "access" = "Drupal\system\MenuAccessController"
* }, * },
* config_prefix = "menu.menu", * config_prefix = "menu.menu",
* entity_keys = { * entity_keys = {