7

I have a few sites in a network. I don't want the site administrators to manage things like network plugins, but I would like them to be able to edit profiles of all network users, not use those on their site.

At the top of the /wp-admin/network/users.php file is this:

if ( ! current_user_can( 'manage_network_users' ) )
    wp_die( __( 'You do not have permission to access this page.' ) );

How can I grant site administrators priviledges to manage_network_users without promoting them to Super Admin?

Here's what the code is looking like:


/**
 * Retrieve a list of super admins.
 *
 * @since 3.0.0
 *
 * @uses $super_admins Super admins global variable, if set.
 *
 * @return array List of super admin logins
 */
function get_super_admins() {
    global $super_admins;

    if ( isset($super_admins) )
        return $super_admins;
    else
        return get_site_option( 'site_admins', array('admin') );
}

/**
 * Determine if user is a site admin.
 *
 * @since 3.0.0
 *
 * @param int $user_id (Optional) The ID of a user. Defaults to the current user.
 * @return bool True if the user is a site admin.
 */
function is_super_admin( $user_id = false ) {
    if ( $user_id )
        $user = new WP_User( $user_id );
    else
        $user = wp_get_current_user();

    if ( empty( $user->id ) )
        return false;

    if ( is_multisite() ) {
        $super_admins = get_super_admins();
        if ( is_array( $super_admins ) && in_array( $user->user_login, $super_admins ) )
            return true;
    } else {
        if ( $user->has_cap('delete_users') )
            return true;
    }

    return false;
}

    /**
     * Whether user has capability or role name.
     *
     * This is useful for looking up whether the user has a specific role
     * assigned to the user. The second optional parameter can also be used to
     * check for capabilities against a specfic post.
     *
     * @since 2.0.0
     * @access public
     *
     * @param string|int $cap Capability or role name to search.
     * @param int $post_id Optional. Post ID to check capability against specific post.
     * @return bool True, if user has capability; false, if user does not have capability.
     */
    function has_cap( $cap ) {
#       fb($cap);
        if ( is_numeric( $cap ) ) {
            _deprecated_argument( __FUNCTION__, '2.0', __('Usage of user levels by plugins and themes is deprecated. Use roles and capabilities instead.') );
            $cap = $this->translate_level_to_cap( $cap );
        }

        $args = array_slice( func_get_args(), 1 );
        $args = array_merge( array( $cap, $this->ID ), $args );
        $caps = call_user_func_array( 'map_meta_cap', $args );

        // Multisite super admin has all caps by definition, Unless specifically denied.
        if ( is_multisite() && is_super_admin( $this->ID ) ) {
            if ( in_array('do_not_allow', $caps) )
                return false;
            return true;
        }

        // Must have ALL requested caps
        $capabilities = apply_filters( 'user_has_cap', $this->allcaps, $caps, $args );
        $capabilities['exist'] = true; // Everyone is allowed to exist
        foreach ( (array) $caps as $cap ) {
            //echo "Checking cap $cap
"; if ( empty( $capabilities[$cap] ) || !$capabilities[$cap] ) return false; } return true; }

Code from users.php in wp-admin showing a second capability check for editing network users:

// Only allow super admins on multisite to edit every user.
if ( is_multisite() && ! current_user_can( 'manage_network_users' ) && $user_id != $current_user->ID && ! apply_filters( 'enable_edit_any_user_configuration', true ) )
    wp_die( __( 'You do not have permission to edit this user.' ) );

8
  • possible duplicate of How to add a Capability to a User Role?
    – kaiser
    Jun 28, 2011 at 20:10
  • 1
    I do not believe this to be a duplicate. It is a fairly hard question as some of the network user admin functions are coded in a way that seems to make it very hard to extend them.
    – cwd
    Jun 30, 2011 at 3:20
  • @cwd You want to add a capability (you name it "priviledges") to a role. Administrator (or Site Administrator) is a role. And manage_network_users is a capability. So "How can I grant site administrators priviledges to manage_network_users without promoting them to Super Admin?" means "How can I add the capability of manage_network_users to the role of 'administrator'". Same Q, same solution = dublicate. Further reading material here in the Codex.
    – kaiser
    Jun 30, 2011 at 4:03
  • 1
    I already tried using the "Members" plugin to simply add the capability "manage_network_users" for Administrators, but it did not work. Simply adding the capability in that fashion won't solve the whole problem as there are other checks in place for network capabilities. I'm not sure if you can tell from the code I've added above, but the Super Administrator role / capabilities work quite differently from the others. A solution that does not work is not a solution.
    – cwd
    Jun 30, 2011 at 11:57
  • @cwd: consider opening a ticket: core.trac.wordpress.org
    – scribu
    Jun 30, 2011 at 13:30

3 Answers 3

8

Here's a solution that worked for me:

http://thereforei.am/2011/03/15/how-to-allow-administrators-to-edit-users-in-a-wordpress-network/

Pretty elegant and doesn't involve messing with core.

4
  • 1
    You may want to test first before accepting, as other users with this problem will see this too
    – Tom J Nowell
    Nov 21, 2012 at 12:46
  • Don't use this, it will allow any users to access your network dashboard as a super admin.
    – VoidZA
    Aug 5, 2021 at 9:29
  • 1
    Upvoted. I'm not sure about @VoidZA's comment. I tested now on Wordpress 5.5 multisite, using the code from the link (be sure to use the Update 21 May 2012 code block) and was not able to access the network dashboard. When I tried as a 'regular' admin as well as a subscriber, I saw the message You attempted to access the "XYZ" dashboard, but you do not currently have privileges on this site. If you believe you should be able to access the "XYZ" dashboard, please contact your network administrator., as expected. Aug 19, 2021 at 19:47
  • @TylerCollier I used WordPress 5.8. I can't remember exactly under which conditions it occurred, but iirc it happened when a new user, any role, gets added (invited) directly to a sub site. My setup was using subdomains and not subdirectories. If I get a gap somewhere I will test again and provide more info. Just be careful with this. Also, if you are just looking for a solution for admins to be able to edit users on their own sites (not all sites), then you can use this instead: wp_roles()->role_objects['administrator']->add_cap( 'manage_network_users' );
    – VoidZA
    Aug 21, 2021 at 14:09
3

Unfortunately I don't have enough points to add a comment or vote up @Michael's answer above, but I wanted to point out to another post which gives a nicer solution to the problem of stopping non-admin users from editing admin/super-admin accounts.

The solution in the post link given by Michael works fine, I just applied it to a WP multi-site v4.1. However, it calls die() function when a non-admin user tries to edit an admin account. So instead I used this solution (which is initially for a single site installation of WP) which hides all admin user accounts from the list of user when it is accessed by a non-admin user.

The final solution, a combination of the above two, gives this...

function mc_admin_users_caps( $caps, $cap, $user_id, $args ){

    foreach( $caps as $key => $capability ){

        if( $capability != 'do_not_allow' )
            continue;

        switch( $cap ) {
            case 'edit_user':
            case 'edit_users':
                $caps[$key] = 'edit_users';
                break;
            case 'delete_user':
            case 'delete_users':
                $caps[$key] = 'delete_users';
                break;
            case 'create_users':
                $caps[$key] = $cap;
                break;
        }
    }

    return $caps;
}
add_filter( 'map_meta_cap', 'mc_admin_users_caps', 1, 4 );
remove_all_filters( 'enable_edit_any_user_configuration' );
add_filter( 'enable_edit_any_user_configuration', '__return_true');

/*
 * hide admin from user list
 */
add_action('pre_user_query','isa_pre_user_query');
function isa_pre_user_query($user_search) {
  $user = wp_get_current_user();
  if ($user->ID!=1) { // Is not administrator, remove administrator
    global $wpdb;
    $user_search->query_where = str_replace('WHERE 1=1',
      "WHERE 1=1 AND {$wpdb->users}.ID<>1",$user_search->query_where);
  }
}
0

The code above only hides the super admin with ID = 1. Here's a a code to hide all super users:

/*
 * hide super admin from user list
 */
add_action('pre_user_query','isa_pre_user_query');
function isa_pre_user_query($user_search) {
  $user = wp_get_current_user();
  if ( !is_super_admin($user->ID) ) { // Is not administrator, remove administrator
    global $wpdb;
        $admins = get_network_option(1, 'site_admins', [1]);
        $admin_user = implode("','", $admins);
    $user_search->query_where = str_replace('WHERE 1=1', "WHERE 1=1 AND {$wpdb->users}.user_login NOT IN ('{$admin_user}')", $user_search->query_where);
  }
}

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.