L'éditeur peut créer n'importe quel nouvel utilisateur sauf l'administrateur

36

J'ai mis en place un site WordPress pour un client. Le client a le rôle d’éditeur, mais j’ai installé le plug - in Membres et lui ai donné la possibilité d’ajouter de nouveaux utilisateurs à l’administrateur WP. Cela fonctionne très bien.

La question que j'ai est que je voudrais que le client ait la possibilité de créer un nouvel utilisateur avec les rôles de contributeur, abonné, éditeur et auteur, mais PAS d'administrateur. Les nouveaux utilisateurs créés par le client ne doivent pas avoir le rôle d'administrateur. Est-il possible de cacher cette option?

Merci Vayu

Vayu
la source
2
Veuillez relier le plugin que vous utilisez, j'ai eu des problèmes pour trouver celui auquel vous faites référence.
hakre

Réponses:

39

C'est en fait assez facile. Vous devez filtrer dans map_meta_capset empêcher les éditeurs de créer / éditer des administrateurs, et supprimer le rôle d'administrateur du tableau 'editable roles'. Cette classe, en tant que plugin ou dans le fichier functions.php de votre thème, le ferait:

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();

MODIFIER

Ok, j’ai donc cherché à savoir pourquoi la suppression par l’utilisateur était laissée de côté. Il semble que delete_user soit géré légèrement différemment de edit_user; J'ai modifié la méthode map_meta_cap pour résoudre ce problème. J'ai testé sur la version 3.0.3 et cela empêchera quiconque, à l'exception des administrateurs, de supprimer, éditer ou créer un administrateur.

EDIT 2

J'ai mis à jour le code pour refléter la réponse de @ bugnumber9 ci-dessous. S'il vous plaît allez donner cette réponse un vote positif!

John P Bloch
la source
Est-ce que quelqu'un peut vérifier que ce code empêche les autres de supprimer des administrateurs? Je ne peux pas reproduire ce comportement. Cela les empêche de les éditer, mais le lien de survol "supprimer" apparaît toujours et WP permet à l'utilisateur d'exécuter la suppression ...
somatic
@somatic - vous étiez sur place. Merci d'avoir fait remarquer cela. Le problème est résolu maintenant.
John P Bloch
J'ai besoin de le faire aussi mais je ne sais pas où je mets ce code! Dans le functions.php? Sinon, comment pourrait-il être fait pour fonctionner à partir du fichier functions.php? meilleur, Dc
v3nt
@daniel a lu le premier paragraphe.
John P Bloch
1
A bien fonctionné en 3.4.1, merci! Assurez-vous d'ajouter des fonctionnalités pour create_users, delete_users, add_users, remove_users, edit_users, list_users et promotion_users
Jon Raasch le
8

Bien qu’il ait environ 7 ans, ce fil peut facilement être cherché dans Google et constitue toujours une solution efficace. Je parle du code fourni par @John P Bloch.

Cela dit, sous PHP 7, cela produit une erreur non critique (PHP obsolète) comme suit:

PHP obsolète: les méthodes portant le même nom que leur classe ne seront pas des constructeurs dans une future version de PHP; JPB_User_Caps a un constructeur déconseillé dans ...

Pour résoudre ce problème, remplacez simplement cette pièce:

// 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);
  }

avec ça:

// 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 );
  }

Cela résoudra le problème.

numéro de bug9
la source
1
Merci merci merci. J'apprécie le dévouement envers la qualité du code et j'ai mis à jour ma réponse afin que les utilisateurs occasionnels puissent également recevoir le mémo. Tu gères!
John P Bloch
3

Je cherchais une solution où l'éditeur ne pourrait éditer que des menus ET créer / éditer des utilisateurs sans avoir besoin d'un plugin. Alors j'ai fini par le faire pour ceux qui sont intéressés.

// 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
la source
1

La solution de @John P Blochs fonctionne toujours bien, mais je pensais aussi ajouter mon petit filtre pour 'map_meta_cap'. Juste un peu plus court et plus propre, au moins pour mes yeux;)

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
la source