Under "admin/people/permissions" there is a permission that allows users to administer all the content types.
I want to create a role that can only administer an "Article" content type. How can I achieve this?
Drupal Answers is a question and answer site for Drupal developers and administrators. It only takes a minute to sign up.
Sign up to join this communityUnder "admin/people/permissions" there is a permission that allows users to administer all the content types.
I want to create a role that can only administer an "Article" content type. How can I achieve this?
The menu callback for "admin/structure/types/manage/%node_type" is defined in node_menu() using the following array item:
$items['admin/structure/types/manage/%node_type'] = array(
'title' => 'Edit content type',
'title callback' => 'node_type_page_title',
'title arguments' => array(4),
'page callback' => 'drupal_get_form',
'page arguments' => array('node_type_form', 4),
'access arguments' => array('administer content types'),
'file' => 'content_types.inc',
);
There are other two menu items that follow it, but they depend from that menu item for the access callback.
$items['admin/structure/types/manage/%node_type/edit'] = array(
'title' => 'Edit',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/structure/types/manage/%node_type/delete'] = array(
'title' => 'Delete',
'page arguments' => array('node_type_delete_confirm', 4),
'access arguments' => array('administer content types'),
'file' => 'content_types.inc',
);
Once you change the access callback for the first menu item, the other two will use the same access callback.
The first step, for the custom module I would implement to achieve what you want is to implement hook_permission()
. node_permission() is useful as guideline to write the code you need.
function mymodule_permission() {
$perms = array();
foreach (node_type_get_types() as $type => $info) {
$perms["administer $type content type"] = array(
'title' => t('%type_name: administer content type', array('%type_name' => $info->name)),
);
}
return $perms;
}
The foreach()
part could be rewritten as the following code:
foreach (node_permissions_get_configured_types() as $type) {
$info = node_type_get_type($type);
$perms["administer $type content type"] = array(
'title' => t('%type_name: administer content type', array('%type_name' => $info->name)),
);
}
The difference is that node_permissions_get_configured_types() is using some Drupal variables that are set in a settings page. The function is used also from the Node module when creating the list of the permissions associated to a node of a content type. The documentation for the function reports the following text:
To exclude a specific node from getting permissions defined for it, set the
"node_permissions_$type"
variable to 0. Core does not provide an interface for doing so; however, contrib modules may exclude their own nodes inhook_install()
. Alternatively, contrib modules may configure all node types at once, or decide to apply some otherhook_node_access()
implementation to some or all node types.
The second step is to alter the menu item already defined by the Node module.
function mymodule_menu_alter(&$items) {
if (isset($items['admin/structure/types/manage/%node_type']) {
$items['admin/structure/types/manage/%node_type']['access callback'] = '_mymodule_content_type_access';
$items['admin/structure/types/manage/%node_type']['access arguments'] = array(4);
}
}
_mymodule_content_type_access()
should contain code similar to the following one:
function _mymodule_content_type_access($type) {
return user_access("administer {$type->type} content type");
}
The easiest way I can think would be to provide a new separate permission for each available content type which you can assign to arbitrary roles, then override the access callback
for the content type edit form to use this new permission:
// Implements hook_permission()
function MYMODULE_permission() {
$permissions = array();
// Build up a permission for each content type
foreach (node_type_get_types() as $type) {
// Get the permission key
$permission_string = _MYMODULE_permission_string($type->type);
// Add the new permission
$permissions[$permission_string] = array(
'title' => 'Administer ' . $type->name . ' Content Type',
'restrict access' => TRUE
);
}
return $permissions;
}
// Implements hook_menu_alter()
function MYMODULE_menu_alter(&$items) {
// Override the access callback
$items['admin/structure/types/manage/%node_type']['access callback'] = 'MYMODULE_content_type_access';
// Override the access arguments so we receive the content type object
// rather than the standard permission name.
$items['admin/structure/types/manage/%node_type']['access arguments'] = array(4);
}
// Access callback function
function MYMODULE_content_type_access($content_type, $account = NULL) {
// If no account object is provided use the logged in user
if (!$account) {
global $user;
$account = $user;
}
// If the user has access to edit all content types then we should return
// TRUE.
if (user_access('administer content types', $account)) {
return TRUE;
}
// Otherwise create a permission string based on the provided content type.
$permission_string = _MYMODULE_permission_string($content_type->type);
// Return access based on the permission string
return user_access($permission_string, $account);
}
// Helper function to build up a standardised permission string
function _MYMODULE_permission_string($type_name) {
return 'administer ' . $type_name . ' content type';
}
$items['admin/structure/types']['access callback']
as well to check if the user had access to any of the content types before they could reach that page. I also had to override the table that is rendered to check for access to each content types. I need to see if there's a way to modify that table without overriding the page callback. If I get a chance, I'd love to roll this into a module at some point :-p
Apr 2, 2014 at 23:12
You also have, on permissions, for each role:
What else do you need?
Workbench module can also help here. Different roles can have access to steps in Workbench, ie you can have different roles access different steps in workbench.