6

(Moderator's note: The original title was "Custom User Role Restrictions")

A project I am working on requires me to create two new user roles - one for the owner of the website and the other for agents of the company.

With the website owner user role I was just looking for a way to restrict users in this group from modifying core site settings while having access to modify all other settings.

The code below seems to work perfectly for everything other than the user management area. I did want users of this group to be able to add/modify website users BUT where I am running into a problem is that users of this group currently have the ability to create users in the "Administrator" category and they are also able to deleting existing "Administrators".

What I am looking for is a way to modify the code below so that such users can NOT delete or modify a user account which is set as "Administrator" and restrict the user from being able to create a new Administrator account.

Does anyone know how this can be done?

// CREATE CUSTOM - SITE OWNER - USER ROLE WITH CUSTOM CAPABILITIES
if (!get_role('website_owner')) {
  //let's use the editor as the base capabilities
  $caps = get_role('editor')->capabilities; 
  $caps = array_merge( $caps, array(
    'install_plugins'               => false,
    'activate_plugins'              => false,
    'update_plugins'                => false,
    'delete_plugins'                => false,
    'list_users'                    => true,
    'add_users'                     => true,
    'create_users'                  => true,
    'edit_users'                    => true,
    'delete_users'                  => true,
    'remove_users'                  => true,
    'unfiltered_upload'             => true,
    'install_themes'                => false,
    'update_themes'                 => false,
    'delete_themes'                 => false,
    'switch_themes'                 => false,
    'edit_theme_options'            => true,
    'manage_options'                => false,
    'import'                        => false,
    'update_core'                   => false,
    'edit_dashboard'                => false,
    'gravityforms_view_entries'     => true,
    'gravityforms_edit_entries'     => true,
    'gravityforms_delete_entries'   => true,
    'gravityforms_export_entries'   => true,
    'gravityforms_view_entry_notes' => true,
    'gravityforms_edit_entry_notes' => true,
    'gravityforms_feed'             => true,
  )); //adding new capabilities.
  // Ref: http://codex.wordpress.org/Roles_and_Capabilities#Capability_vs._Role_Table
  add_role( 'website_owner', 'Website Owner', $caps );
}
3
  • I've never done any customization of user roles, nor do I think this is going to help your problem, but you have an extra comma at the end of your array. The comma on 'gravityforms_feed' => true," shouldn't be there. Nov 9, 2010 at 1:13
  • 3
    @eileen: extra comma at the end of array is acceptable by php
    – ariefbayu
    Nov 9, 2010 at 6:59
  • 3
    @eileen.carpenter - Props to @silent, I almost always include a trailing comma on my arrays in PHP. The extra comma is, in my book, a best practice and one of the things the designers of PHP really got right. Why? Because it makes it easy to add a line via copy & paste without introducing a syntax error. Nov 9, 2010 at 7:58

2 Answers 2

9

Hi @NetConstructor:

I think this is what you need. Note that I didn't include the full setup of your 'website_owner' role, just the addition of a new capability called 'manage_administrators'.

Also, I only attempted to remove the "Delete" link from any users that don't have the 'manage_administrators' capability (which you'll need to add to the administrator role, of course) and I also simply removed the Administrator as a role option on the "Add New User" page. I didn't attempt to ensure they can't delete or add administrators via some nefarious method, and I didn't disable any other feature that might allow them to add or delete administrators. That said, maybe this is sufficient?

add_action('user_row_actions','yoursite_user_row_actions',10,2);
function yoursite_user_row_actions($actions, $user_object) {  // remove the ability to delete an administrator
  global $pagenow;
  if ($pagenow=='users.php' && isset($user_object->caps['administrator']) && !current_user_can('manage_administrators'))
    unset($actions['edit']);
    unset($actions['delete']);
  return $actions;
}
add_action('editable_roles','yoursite_editable_roles');
function yoursite_editable_roles($all_roles) { // remove the ability to add an administrator
  global $pagenow;
if (in_array($pagenow,array('user-edit.php','user-new.php')) &&           
       !current_user_can('manage_administrators'))
    unset($all_roles['administrator']);
  return $all_roles;
}
add_action('admin_init','yoursite_admin_init');
function yoursite_admin_init() {
  $wp_roles = new WP_Roles();
  $wp_roles->use_db = true;
  $administrator = $wp_roles->get_role('administrator');
  if (!$administrator->has_cap('manage_administrators'))
    $wp_roles->add_cap('administrator','manage_administrators');

  $website_owner = $wp_roles->get_role('website_owner');
  if (!$website_owner) {
    //let's use the editor as the base capabilities
    $caps = get_role('editor')->capabilities;
    $caps = array_merge( $caps, array(
      'install_plugins'               => false,
      'activate_plugins'              => false,
      'update_plugins'                => false,
      'delete_plugins'                => false,
      'list_users'                    => true,
      'add_users'                     => true,
      'create_users'                  => true,
      'edit_users'                    => true,
      'delete_users'                  => true,
      'remove_users'                  => true,
      'unfiltered_upload'             => true,
      'install_themes'                => false,
      'update_themes'                 => false,
      'delete_themes'                 => false,
      'switch_themes'                 => false,
      'edit_theme_options'            => true,
      'manage_options'                => false,
      'import'                        => false,
      'update_core'                   => false,
      'edit_dashboard'                => false,
      'gravityforms_view_entries'     => true,
      'gravityforms_edit_entries'     => true,
      'gravityforms_delete_entries'   => true,
      'gravityforms_export_entries'   => true,
      'gravityforms_view_entry_notes' => true,
      'gravityforms_edit_entry_notes' => true,
      'gravityforms_feed'             => true,
      'manage_administrators'         => false,
    ));
    $wp_roles->add_role('website_owner','Website Owner',$caps);
  }
}
12
  • @Mike -- has Mike, thanks for this... Can I assume that once this is added to my functions file that I just have to add 'manage_administrators' => true, to the code I posted above? Nov 11, 2010 at 11:44
  • @Mike -- Sorry I meant to define it as false above. Also, when I add your code and add the 'manage_administrators' => false, to my custom role then when I go to add a new user the "role" dropdown form field is blank. Nov 11, 2010 at 12:08
  • @NetConstructor.com - Weeelll... that's what I get for providing code I didn't fully test. Sheesh, on my part! The code's updated and I think it is now fully tested. FYI, the error was a copy/paste error where yoursite_editable_roles() was returning $action instead of $all_roles. I also tried to make the init hook fully workable so that hopefully anyone would be able to copy and paste this code into their theme's functions.php file to see it work. Nov 11, 2010 at 16:26
  • @Mike -- Thanks Mike but something must be wrong with this. I went ahead and deleted my code (which I originally posted in the question) and replaced it with the complete code you just posted. I then went to add a new user account and assign the "website owner" role and logged in with that account. When I access the user management area from that account I am still able to see the "Website Owner" and "Administrator" roles in the dropdown when viewing/editing a user account and I am able to select either of those and save the data. I think its not working... does it work for you? Nov 11, 2010 at 20:25
  • 3
    @NetConstructor.com - I don't want to be harsh but I am sensing a pattern from this and a few prior questions. The goal of an answer (for me) is to empower the question asker to solve their own issues which I do for challenge, learning and to help others. I don't answer to initiate an ongoing series of questions to handhold through every subsequent detail; that feels a lot like consulting and becomes very stressful for me. If you are struggling with follow ups to answers posted here maybe you should subcontract out these issues? I could help but others here or elsewhere could help too. Nov 12, 2010 at 20:36
0

I believe this is now meant to be done using map_meta_cap :

For example to block deleting or editing the admin user who has an id of 1 you would do this:

add_filter('map_meta_cap', function( $required_caps, $cap, $user_id, $args ){

   $protected_user = 1; // ID of admin user you want to block from being edited

    if ( $user_id === $protected_user ) // Don't block caps if current user = protected user
        return $required_caps;
    $blocked_caps = array(
        'delete_user',
        'edit_user',
        'remove_user'
        );
    if ( in_array( $cap, $blocked_caps ) && $args[0] === $protected_user )
        $required_caps[] = 'do_not_allow';
    return $required_caps;
}, 10, 4 );

You can add any additional capabilities that you want blocked to the $blocked_caps array.

I also add this in for hiding myself from the wp-admin/users.php page. It would probably be better unsetting the user with php, but it doesn't really make a different since the admin can't be edited anyway if you are using the above function.

function hide_admin_user_bw() {
  ?>
    <style type="text/css">
    .users-php tr#user-1 {
        display: none!important;
    }
    .users-php li.administrator {
        display: none!important;
    }
    </style>
  <?php
}
add_action('admin_head-users.php', 'hide_admin_user_bw');
1
  • The way you protect user id 1 is really good. Thank you. We want to use your method to hide an admin for a client. The only issue I find is that when I (as another admin) directly try to access profile id 1, I get the message: Sorry, you are not allowed to edit this user, which is a dead giveaway that the user does exist. It would be nice if (you could alter your code) so one would get Invalid user ID which is the returned message for a non-existing user. What do you think? Sep 28, 2016 at 16:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.