diff --git a/modules/comment/comment.test b/modules/comment/comment.test index 9e69ba6..a63b453 100644 --- a/modules/comment/comment.test +++ b/modules/comment/comment.test @@ -13,7 +13,7 @@ class CommentHelperCase extends DrupalWebTestCase { function setUp() { parent::setUp('comment', 'search'); // Create users and test node. - $this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer comments', 'administer blocks')); + $this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer comments', 'administer blocks', 'administer fields')); $this->web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'create article content', 'edit own comments')); $this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'uid' => $this->web_user->uid)); } diff --git a/modules/field/modules/list/tests/list.test b/modules/field/modules/list/tests/list.test index 84de7e8..b476b5a 100644 --- a/modules/field/modules/list/tests/list.test +++ b/modules/field/modules/list/tests/list.test @@ -212,7 +212,7 @@ class ListFieldUITestCase extends FieldTestCase { parent::setUp('field_test', 'field_ui'); // Create test user. - $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy')); + $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy', 'administer fields')); $this->drupalLogin($admin_user); // Create content type, with underscores. diff --git a/modules/field/modules/number/number.test b/modules/field/modules/number/number.test index 88029cd..c88b4c1 100644 --- a/modules/field/modules/number/number.test +++ b/modules/field/modules/number/number.test @@ -23,7 +23,7 @@ class NumberFieldTestCase extends DrupalWebTestCase { function setUp() { parent::setUp('field_test'); - $this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer content types')); + $this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer content types', 'administer fields')); $this->drupalLogin($this->web_user); } diff --git a/modules/field/modules/options/options.test b/modules/field/modules/options/options.test index 7183311..270fcad 100644 --- a/modules/field/modules/options/options.test +++ b/modules/field/modules/options/options.test @@ -54,7 +54,7 @@ class OptionsWidgetsTestCase extends FieldTestCase { $this->bool = field_create_field($this->bool); // Create a web user. - $this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content')); + $this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer fields')); $this->drupalLogin($this->web_user); } @@ -459,7 +459,7 @@ class OptionsWidgetsTestCase extends FieldTestCase { $this->assertNoFieldChecked("edit-bool-$langcode"); // Create admin user. - $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy')); + $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy', 'administer fields')); $this->drupalLogin($admin_user); // Create a test field instance. diff --git a/modules/field/modules/text/text.test b/modules/field/modules/text/text.test index 2f14738..ad803cf 100644 --- a/modules/field/modules/text/text.test +++ b/modules/field/modules/text/text.test @@ -424,6 +424,7 @@ class TextTranslationTestCase extends DrupalWebTestCase { 'administer content types', 'access administration pages', 'bypass node access', + 'administer fields', filter_permission_name($full_html_format), )); $this->translator = $this->drupalCreateUser(array('create article content', 'edit own article content', 'translate content')); diff --git a/modules/field_ui/field_ui.install b/modules/field_ui/field_ui.install new file mode 100644 index 0000000..7390d6e --- /dev/null +++ b/modules/field_ui/field_ui.install @@ -0,0 +1,19 @@ + $role_name) { + user_role_grant_permissions($rid, array('administer fields')); + } +} diff --git a/modules/field_ui/field_ui.module b/modules/field_ui/field_ui.module index ed833fe..262ba6a 100644 --- a/modules/field_ui/field_ui.module +++ b/modules/field_ui/field_ui.module @@ -104,10 +104,26 @@ function field_ui_menu() { // Extract access information, providing defaults. $access = array_intersect_key($bundle_info['admin'], drupal_map_assoc(array('access callback', 'access arguments'))); - $access += array( - 'access callback' => 'user_access', - 'access arguments' => array('administer site configuration'), - ); + + // Add the "administer fields" permission on top of the access + // restriction because the field UI should only be accessible to + // trusted users. + if (empty($access)) { + $field_ui_access = array( + 'access callback' => 'user_access', + 'access arguments' => array('administer fields'), + ); + } + else { + $access += array( + 'access callback' => 'user_access', + 'access arguments' => array('administer fields'), + ); + $field_ui_access = array( + 'access callback' => 'field_ui_admin_access', + 'access arguments' => array($access['access callback'], $access['access arguments']), + ); + } $items["$path/fields"] = array( 'title' => 'Manage fields', @@ -116,7 +132,7 @@ function field_ui_menu() { 'type' => MENU_LOCAL_TASK, 'weight' => 1, 'file' => 'field_ui.admin.inc', - ) + $access; + ) + $field_ui_access; $items["$path/fields/%field_ui_menu"] = array( 'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'), 'title callback' => 'field_ui_menu_title', @@ -124,7 +140,7 @@ function field_ui_menu() { 'page callback' => 'drupal_get_form', 'page arguments' => array('field_ui_field_edit_form', $field_position), 'file' => 'field_ui.admin.inc', - ) + $access; + ) + $field_ui_access; $items["$path/fields/%field_ui_menu/edit"] = array( 'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'), 'title' => 'Edit', @@ -132,7 +148,7 @@ function field_ui_menu() { 'page arguments' => array('field_ui_field_edit_form', $field_position), 'type' => MENU_DEFAULT_LOCAL_TASK, 'file' => 'field_ui.admin.inc', - ) + $access; + ) + $field_ui_access; $items["$path/fields/%field_ui_menu/field-settings"] = array( 'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'), 'title' => 'Field settings', @@ -140,7 +156,7 @@ function field_ui_menu() { 'page arguments' => array('field_ui_field_settings_form', $field_position), 'type' => MENU_LOCAL_TASK, 'file' => 'field_ui.admin.inc', - ) + $access; + ) + $field_ui_access; $items["$path/fields/%field_ui_menu/widget-type"] = array( 'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'), 'title' => 'Widget type', @@ -148,7 +164,7 @@ function field_ui_menu() { 'page arguments' => array('field_ui_widget_type_form', $field_position), 'type' => MENU_LOCAL_TASK, 'file' => 'field_ui.admin.inc', - ) + $access; + ) + $field_ui_access; $items["$path/fields/%field_ui_menu/delete"] = array( 'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'), 'title' => 'Delete', @@ -157,7 +173,7 @@ function field_ui_menu() { 'type' => MENU_LOCAL_TASK, 'weight' => 10, 'file' => 'field_ui.admin.inc', - ) + $access; + ) + $field_ui_access; // 'Manage display' tab. $items["$path/display"] = array( @@ -167,7 +183,7 @@ function field_ui_menu() { 'type' => MENU_LOCAL_TASK, 'weight' => 2, 'file' => 'field_ui.admin.inc', - ) + $access; + ) + $field_ui_access; // View modes secondary tabs. // The same base $path for the menu item (with a placeholder) can be @@ -186,7 +202,7 @@ function field_ui_menu() { // display' setting for the view mode, and the overall access // rules for the bundle admin pages. 'access callback' => '_field_ui_view_mode_menu_access', - 'access arguments' => array_merge(array($entity_type, $bundle_arg, $view_mode, $access['access callback']), $access['access arguments']), + 'access arguments' => array_merge(array($entity_type, $bundle_arg, $view_mode, $field_ui_access['access callback']), $field_ui_access['access arguments']), 'type' => ($view_mode == 'default' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK), 'weight' => ($view_mode == 'default' ? -10 : $weight++), 'file' => 'field_ui.admin.inc', @@ -392,3 +408,26 @@ function field_ui_form_node_type_form_submit($form, &$form_state) { $form_state['redirect'] = _field_ui_bundle_admin_path('node', $form_state['values']['type']) .'/fields'; } } + +/** + * Implements hook_permission(). + */ +function field_ui_permission() { + return array( + 'administer fields' => array( + 'title' => t('Administer fields'), + 'description' => t('Create, change and delete fields on entities.'), + 'restrict access' => TRUE, + ), + ); +} + +/** + * Access callback to determine if a user is allowed to use the field UI. + * + * Only grant access if the user has both the "administer fields" permission and + * is granted access by the entity specific restrictions. + */ +function field_ui_admin_access($access_callback, $access_arguments) { + return user_access('administer fields') && call_user_func_array($access_callback, $access_arguments); +} diff --git a/modules/field_ui/field_ui.test b/modules/field_ui/field_ui.test index 21767d6..73697c6 100644 --- a/modules/field_ui/field_ui.test +++ b/modules/field_ui/field_ui.test @@ -22,7 +22,7 @@ class FieldUITestCase extends DrupalWebTestCase { parent::setUp($modules); // Create test user. - $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy')); + $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy', 'administer fields')); $this->drupalLogin($admin_user); // Create content type, with underscores. @@ -682,7 +682,7 @@ class FieldUIAlterTestCase extends DrupalWebTestCase { parent::setUp(array('field_test')); // Create test user. - $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer users')); + $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer users', 'administer fields')); $this->drupalLogin($admin_user); } diff --git a/modules/file/tests/file.test b/modules/file/tests/file.test index 0f6a578..53d9a03 100644 --- a/modules/file/tests/file.test +++ b/modules/file/tests/file.test @@ -22,7 +22,7 @@ class FileFieldTestCase extends DrupalWebTestCase { $modules[] = 'file'; $modules[] = 'file_module_test'; parent::setUp($modules); - $this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer nodes', 'bypass node access')); + $this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer nodes', 'bypass node access', 'administer fields')); $this->drupalLogin($this->admin_user); } diff --git a/modules/image/image.test b/modules/image/image.test index 2387314..2fe07c2 100644 --- a/modules/image/image.test +++ b/modules/image/image.test @@ -32,7 +32,7 @@ class ImageFieldTestCase extends DrupalWebTestCase { function setUp() { parent::setUp('image'); - $this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer content types', 'administer nodes', 'create article content', 'edit any article content', 'delete any article content', 'administer image styles')); + $this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer content types', 'administer nodes', 'create article content', 'edit any article content', 'delete any article content', 'administer image styles', 'administer fields')); $this->drupalLogin($this->admin_user); } diff --git a/modules/node/content_types.inc b/modules/node/content_types.inc index 55af667..c451dc7 100644 --- a/modules/node/content_types.inc +++ b/modules/node/content_types.inc @@ -11,7 +11,7 @@ function node_overview_types() { $types = node_type_get_types(); $names = node_type_get_names(); - $field_ui = module_exists('field_ui'); + $field_ui = module_exists('field_ui') && user_access('administer fields'); $header = array(t('Name'), array('data' => t('Operations'), 'colspan' => $field_ui ? '4' : '2')); $rows = array(); diff --git a/modules/node/node.test b/modules/node/node.test index 5c9118e..496f7a8 100644 --- a/modules/node/node.test +++ b/modules/node/node.test @@ -1448,7 +1448,7 @@ class NodeTypeTestCase extends DrupalWebTestCase { * Tests editing a node type using the UI. */ function testNodeTypeEditing() { - $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types')); + $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer fields')); $this->drupalLogin($web_user); $instance = field_info_instance('node', 'body', 'page'); @@ -2698,8 +2698,8 @@ class NodeAccessFieldTestCase extends NodeWebTestCase { node_access_rebuild(); // Create some users. - $this->admin_user = $this->drupalCreateUser(array('access content', 'bypass node access')); - $this->content_admin_user = $this->drupalCreateUser(array('access content', 'administer content types')); + $this->admin_user = $this->drupalCreateUser(array('access content', 'bypass node access', 'administer fields')); + $this->content_admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer fields')); // Add a custom field to the page content type. $this->field_name = drupal_strtolower($this->randomName() . '_field_name'); diff --git a/modules/taxonomy/taxonomy.test b/modules/taxonomy/taxonomy.test index fdf354b..e9dac1e 100644 --- a/modules/taxonomy/taxonomy.test +++ b/modules/taxonomy/taxonomy.test @@ -1025,7 +1025,7 @@ class TaxonomyRSSTestCase extends TaxonomyWebTestCase { function setUp() { parent::setUp('taxonomy'); - $this->admin_user = $this->drupalCreateUser(array('administer taxonomy', 'bypass node access', 'administer content types')); + $this->admin_user = $this->drupalCreateUser(array('administer taxonomy', 'bypass node access', 'administer content types', 'administer fields')); $this->drupalLogin($this->admin_user); $this->vocabulary = $this->createVocabulary();