El Editor puede crear cualquier nuevo usuario excepto administrador

24 nov 2010, 12:34:04
Vistas: 21.8K
Votos: 42

He configurado un sitio WordPress para un cliente. El cliente tiene el rol de Editor, sin embargo, he instalado el plugin Members y le he dado al cliente la capacidad de agregar nuevos usuarios al panel de administración de WordPress. Esto está funcionando perfectamente.

La pregunta que tengo es que me gustaría que el cliente tenga la capacidad de crear nuevos usuarios con los roles de Colaborador, Suscriptor, Editor y Autor, pero NO como Administrador. Los nuevos usuarios que el cliente cree no deberían tener el rol de Administrador. ¿Es posible ocultar esta opción de alguna manera?

Gracias Vayu

1
Comentarios

Por favor, enlaza el plugin que estás usando, tuve problemas para descubrir a cuál te refieres.

hakre hakre
24 nov 2010 14:22:02
Todas las respuestas a la pregunta 4
8
45

En realidad es bastante sencillo. Necesitas filtrar en map_meta_caps para evitar que los editores creen/editen administradores, y eliminar el rol de administrador del array de 'editable roles'. Esta clase, como plugin o en el archivo functions.php de tu tema, lo haría:

class JPB_User_Caps {

  // Añadir nuestros filtros
  function __construct(){
    add_filter( 'editable_roles', array($this, 'editable_roles'));
    add_filter( 'map_meta_cap', array($this, 'map_meta_cap'), 10, 4);
  }

  // Eliminar 'Administrador' de la lista de roles si el usuario actual no es admin
  function editable_roles( $roles ){
    if( isset( $roles['administrator'] ) && !current_user_can('administrator') ){
      unset( $roles['administrator']);
    }
    return $roles;
  }

  // Si alguien intenta editar o eliminar un admin y ese usuario no es admin, no permitirlo
  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();

EDITADO

Ok, he investigado por qué permitía la eliminación de usuarios. Parece que delete_user se maneja ligeramente diferente a edit_user; he modificado el método map_meta_cap para solucionarlo. Lo he probado en 3.0.3 y esto evitará que cualquier persona que no sea administrador pueda eliminar, editar o crear un administrador.

EDITADO 2

He actualizado el código para reflejar la respuesta de @bugnumber9 más abajo. ¡Por favor, vota positivamente esa respuesta!

25 nov 2010 00:07:34
Comentarios

¿Alguien puede verificar que este código evita que otros eliminen administradores? No puedo reproducir ese comportamiento. Evita que los editen, pero el enlace flotante de "eliminar" sigue apareciendo, y WP permite que el usuario proceda con la eliminación...

somatic somatic
15 dic 2010 14:47:17

@somatic - tenías toda la razón. Gracias por señalarlo. El problema ya está solucionado.

John P Bloch John P Bloch
20 dic 2010 19:24:34

Yo también necesito hacer esto pero no estoy seguro de dónde poner este código. ¿En el functions.php? Si no, ¿cómo podría hacerse para que funcione desde el functions.php? Saludos, Dc

v3nt v3nt
27 jul 2011 15:16:42

@daniel lee el primer párrafo.

John P Bloch John P Bloch
27 jul 2011 17:02:44

si alguien más está buscando restringir roles adicionales solo necesitas agregar una línea adicional por rol debajo de esta línea: unset( $roles['administrator']); … así que después de esta línea puedes agregar por ejemplo: unset( $roles['editor']);

User User
4 nov 2011 05:32:32

Funcionó perfectamente en 3.4.1, ¡gracias! Asegúrate de añadir las capacidades para create_users, delete_users, add_users, remove_users, edit_users, list_users y promote_users

Jon Raasch Jon Raasch
14 sept 2012 02:11:39

Excelente código. Para cualquiera que lo use, asegúrese de ver el pequeño ajuste a continuación de @bugnumber9. (¿Quizás John P Block editará su código?)

Eric Eric
11 jul 2017 09:40:24

Eso no funcionó para mí.

avia avia
2 ago 2021 05:33:42
Mostrar los 3 comentarios restantes
1
11

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

Dicho esto, bajo PHP 7 produce un error no crítico (PHP Deprecated) como sigue:

PHP Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; JPB_User_Caps has a deprecated constructor in ...

Para solucionar esto, simplemente reemplaza este fragmento:

// Añadir nuestros filtros
  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:

// Añadir nuestros filtros
  function __construct() {
    add_filter( 'editable_roles', array(&$this, 'editable_roles') );
    add_filter( 'map_meta_cap', array(&$this, 'map_meta_cap'), 10, 4 );
  }

Esto solucionará el problema.

2 jul 2017 12:51:59
Comentarios

Gracias, gracias, gracias. Aprecio la dedicación a la calidad del código y he actualizado mi respuesta para que los buscadores ocasionales también reciban el mensaje. ¡Eres increíble!

John P Bloch John P Bloch
18 jul 2017 06:04:09
0

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

// Personaliza el rol 'Editor' para tener la capacidad de modificar menús, agregar nuevos usuarios
// y más.
class Custom_Admin {
    // Añade nuestros filtros
    public function __construct(){
        // Permite al editor editar opciones del tema (ej. Menú)
        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()) {
            // Deshabilita el acceso a las páginas de temas/widgets si no es 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(__('No tienes permisos suficientes para acceder a esta página.'));
    }

    public function modify_menus() 
    {
        remove_submenu_page( 'themes.php', 'themes.php' ); // oculta el submenú de selección de temas
        remove_submenu_page( 'themes.php', 'widgets.php' ); // oculta el submenú de widgets

        // Menú Apariencia
        global $menu;
        global $submenu;
        if (isset($menu[60][0])) {
            $menu[60][0] = "Menús"; // Renombra Apariencia a Menús
        }
        unset($submenu['themes.php'][6]); // Personalizar
    }

    // Elimina 'Administrador' de la lista de roles si el usuario actual no es un 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;
    }

    // Si alguien intenta editar o eliminar un admin y ese usuario no es admin, no lo permitas
    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';
                    }
                    // No permitas que un no-admin edite a un 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;
                    }
                    // No permitas que un no-admin elimine a un 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;
    }

    // Si el usuario actual se llama admin o administrativo y es un 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();
14 nov 2014 01:47:53
0

La solución de @John P Bloch sigue funcionando bien, pero pensé en compartir también mi pequeño filtro para 'map_meta_cap'. 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 ); // Comprobación en PHP 7 para variable en $args...
  if( $other && $other->has_cap('administrator') ) {
    $caps[] = 'do_not_allow';
  }
  return $caps;
}
add_filter('map_meta_cap', 'my_map_meta_cap', 10, 4 );
26 abr 2019 00:56:59