El editor puede crear cualquier usuario nuevo excepto el administrador

36

He configurado un sitio de WordPress para un cliente. El cliente tiene el rol de Editor, sin embargo, instalé el complemento Miembros y le di al cliente la capacidad de agregar nuevos usuarios al administrador de WP. Esto está funcionando bien.

La pregunta que tengo es que me gustaría que el cliente tenga la capacidad de crear un nuevo usuario como con las funciones de colaborador, suscriptor, editor y autor, pero NO como administrador. Los nuevos usuarios que crea el cliente no deben tener el rol de administrador. ¿Es posible ocultar esta opción de alguna manera?

Gracias vayu

Vayu
fuente
2
Enlace el complemento que está utilizando. Tuve problemas para averiguar a qué se refiere.
Hakre

Respuestas:

39

En realidad es bastante fácil. Debe filtrar map_meta_capsy evitar que los editores creen / editen administradores, y elimine la función de administrador de la matriz de 'funciones editables'. Esta clase, como complemento o en el archivo functions.php de su tema lo haría:

class JPB_User_Caps {

  // Add our filters
  function __construct(){
    add_filter( 'editable_roles', array($this, 'editable_roles'));
    add_filter( 'map_meta_cap', array($this, 'map_meta_cap'), 10, 4);
  }

  // Remove 'Administrator' from the list of roles if the current user is not an admin
  function editable_roles( $roles ){
    if( isset( $roles['administrator'] ) && !current_user_can('administrator') ){
      unset( $roles['administrator']);
    }
    return $roles;
  }

  // If someone is trying to edit or delete and admin and that user isn't an admin, don't allow it
  function map_meta_cap( $caps, $cap, $user_id, $args ){

    switch( $cap ){
        case 'edit_user':
        case 'remove_user':
        case 'promote_user':
            if( isset($args[0]) && $args[0] == $user_id )
                break;
            elseif( !isset($args[0]) )
                $caps[] = 'do_not_allow';
            $other = new WP_User( absint($args[0]) );
            if( $other->has_cap( 'administrator' ) ){
                if(!current_user_can('administrator')){
                    $caps[] = 'do_not_allow';
                }
            }
            break;
        case 'delete_user':
        case 'delete_users':
            if( !isset($args[0]) )
                break;
            $other = new WP_User( absint($args[0]) );
            if( $other->has_cap( 'administrator' ) ){
                if(!current_user_can('administrator')){
                    $caps[] = 'do_not_allow';
                }
            }
            break;
        default:
            break;
    }
    return $caps;
  }

}

$jpb_user_caps = new JPB_User_Caps();

EDITAR

Ok, eché un vistazo a por qué dejaba pasar la eliminación de usuarios. Parece que delete_user se maneja de manera ligeramente diferente de edit_user; He modificado el método map_meta_cap para evitar esto. He probado en 3.0.3 y esto evitará que nadie, excepto los administradores, elimine, edite o cree un administrador.

EDITAR 2

Actualicé el código para reflejar la respuesta de @ bugnumber9 a continuación. ¡Por favor, dale una respuesta a esa respuesta!

John P Bloch
fuente
¿Alguien puede verificar que este código impide que otros eliminen administradores? No puedo reproducir ese comportamiento. Sí evita que se editen, pero el enlace emergente "eliminar" aún aparece, y WP permite al usuario realizar la eliminación ...
somático
@somatic - estabas en el clavo. Gracias por señalar eso. El problema ya está solucionado.
John P Bloch
¡Necesito hacer esto también, pero no estoy seguro de dónde pongo este código! En las funciones.php? Si no, ¿cómo podría hacerse para trabajar desde functions.php? mejor, DC
v3nt
@daniel leyó el primer párrafo.
John P Bloch
1
Funcionó muy bien en 3.4.1, ¡gracias! Asegúrese de agregar capacidades para create_users, delete_users, add_users, remove_users, edit_users, list_users y promote_users
Jon Raasch
8

A pesar de tener ~ 7 años, este hilo se puede buscar en Google fácilmente y aún así proporciona una solución de trabajo. Me refiero al código proporcionado por @John P Bloch.

Dicho esto, en PHP 7 produce un error no crítico (PHP obsoleto) de la siguiente manera:

PHP obsoleto: los métodos con el mismo nombre que su clase no serán constructores en una versión futura de PHP; JPB_User_Caps tiene un constructor obsoleto en ...

Para solucionar esto, simplemente reemplace esta pieza:

// Add our filters
  function JPB_User_Caps(){
    add_filter( 'editable_roles', array(&$this, 'editable_roles'));
    add_filter( 'map_meta_cap', array(&$this, 'map_meta_cap'),10,4);
  }

con este:

// Add our filters
  function __construct() {
    add_filter( 'editable_roles', array(&$this, 'editable_roles') );
    add_filter( 'map_meta_cap', array(&$this, 'map_meta_cap'), 10, 4 );
  }

Esto arreglará el problema.

bugnumber9
fuente
1
Gracias, gracias, gracias. Aprecio la dedicación a la calidad del código y he actualizado mi respuesta para que los googlers casuales también reciban el memo. Tu rock!
John P Bloch
3

Estaba buscando una solución en la que el Editor pudiera editar solo menús Y crear / editar usuarios sin necesidad de un complemento. Así que terminé haciéndolo para aquellos que están interesados.

// Customizes 'Editor' role to have the ability to modify menus, add new users
// and more.
class Custom_Admin {
    // Add our filters
    public function __construct(){
        // Allow editor to edit theme options (ie Menu)
        add_action('init', array($this, 'init'));
        add_filter('editable_roles', array($this, 'editable_roles'));
        add_filter('map_meta_cap', array($this, 'map_meta_cap'), 10, 4);
    }

    public function init() {
        if ($this->is_client_admin()) {
            // Disable access to the theme/widget pages if not admin
            add_action('admin_head', array($this, 'modify_menus'));
            add_action('load-themes.php', array($this, 'wp_die'));
            add_action('load-widgets.php', array($this, 'wp_die'));
            add_action('load-customize.php', array($this, 'wp_die'));

            add_filter('user_has_cap', array($this, 'user_has_cap'));
        }
    }

    public function wp_die() {
        _default_wp_die_handler(__('You do not have sufficient permissions to access this page.'));
    }

    public function modify_menus() 
    {
        remove_submenu_page( 'themes.php', 'themes.php' ); // hide the theme selection submenu
        remove_submenu_page( 'themes.php', 'widgets.php' ); // hide the widgets submenu

        // Appearance Menu
        global $menu;
        global $submenu;
        if (isset($menu[60][0])) {
            $menu[60][0] = "Menus"; // Rename Appearance to Menus
        }
        unset($submenu['themes.php'][6]); // Customize
    }

    // Remove 'Administrator' from the list of roles if the current user is not an admin
    public function editable_roles( $roles ){
        if( isset( $roles['administrator'] ) && !current_user_can('administrator') ){
            unset( $roles['administrator']);
        }
        return $roles;
    }

    public function user_has_cap( $caps ){
        $caps['list_users'] = true;
        $caps['create_users'] = true;

        $caps['edit_users'] = true;
        $caps['promote_users'] = true;

        $caps['delete_users'] = true;
        $caps['remove_users'] = true;

        $caps['edit_theme_options'] = true;
        return $caps;
    }

    // If someone is trying to edit or delete and admin and that user isn't an admin, don't allow it
    public function map_meta_cap( $caps, $cap, $user_id, $args ){
        // $args[0] == other_user_id
        foreach($caps as $key => $capability)
        {
            switch ($cap)
            {
                case 'edit_user':
                case 'remove_user':
                case 'promote_user':
                    if(isset($args[0]) && $args[0] == $user_id) {
                        break;
                    }
                    else if(!isset($args[0])) {
                        $caps[] = 'do_not_allow';
                    }
                    // Do not allow non-admin to edit admin
                    $other = new WP_User( absint($args[0]) );
                    if( $other->has_cap( 'administrator' ) ){
                        if(!current_user_can('administrator')){
                            $caps[] = 'do_not_allow';
                        }
                    }
                    break;
                case 'delete_user':
                case 'delete_users':
                    if( !isset($args[0])) {
                        break;
                    }
                    // Do not allow non-admin to delete admin
                    $other = new WP_User(absint($args[0]));
                    if( $other->has_cap( 'administrator' ) ){
                        if(!current_user_can('administrator')){
                            $caps[] = 'do_not_allow';
                        }
                    }
                    break;
                break;
            }
        }
        return $caps;
    }

    // If current user is called admin or administrative and is an editor
    protected function is_client_admin() {
        $current_user = wp_get_current_user();
        $is_editor = isset($current_user->caps['editor']) ? $current_user->caps['editor'] : false;
        return ($is_editor);
    }
}
new Custom_Admin();
SilbinaryWolf
fuente
1

La solución @John P Blochs todavía funciona bien, pero pensé que también agregaría mi pequeño filtro para 'map_meta_cap'. Solo un poco más corto y limpio, al menos para mis ojos;)

function my_map_meta_cap( $caps, $cap, $user_id, $args ) {
  $check_caps = [
    'edit_user',
    'remove_user',
    'promote_user',
    'delete_user',
    'delete_users'
  ];
  if( !in_array( $cap, $check_caps ) || current_user_can('administrator') ) {
    return $caps;
  }
  $other = get_user_by( 'id', $args[0] ?? false ); // PHP 7 check for variable in $args... 
  if( $other && $other->has_cap('administrator') ) {
    $caps[] = 'do_not_allow';
  }
  return $caps;
}
add_filter('map_meta_cap', 'my_map_meta_cap', 10, 4 );
rassoh
fuente