Editor dapat membuat pengguna baru apa pun kecuali administrator

36

Saya telah menyiapkan situs WordPress untuk klien. Klien memiliki peran Editor, namun saya telah menginstal plugin Anggota dan memberi klien kemampuan untuk menambahkan pengguna baru ke admin WP. Ini berfungsi dengan baik.

Pertanyaan yang saya miliki adalah bahwa saya ingin agar klien memiliki kemampuan untuk membuat pengguna baru dengan peran sebagai Kontributor, Pelanggan, Editor dan Penulis, tetapi BUKAN Administrator. Pengguna baru yang dibuat klien tidak boleh memiliki peran Administrator. Apakah mungkin menyembunyikan opsi ini?

Terima kasih Vayu

Vayu
sumber
2
Harap tautkan plugin yang Anda gunakan, saya punya masalah untuk mencari tahu mana yang Anda maksud.
hakre

Jawaban:

39

Ini sebenarnya cukup mudah. Anda perlu memfilter map_meta_capsdan menghentikan editor dari membuat / mengedit admin, dan menghapus peran administrator dari larik 'peran yang dapat diedit'. Kelas ini, sebagai plugin atau dalam file functions.php tema Anda akan melakukannya:

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

EDIT

Ok, jadi saya melihat mengapa itu membiarkan penghapusan pengguna lewat. Sepertinya delete_user ditangani sedikit berbeda dari edit_user; Saya telah memodifikasi metode map_meta_cap untuk mengatasi ini. Saya telah menguji pada 3.0.3 dan ini akan mencegah siapa pun selain administrator untuk benar-benar menghapus, mengedit, atau membuat administrator.

EDIT 2

Saya memperbarui kode untuk mencerminkan jawaban @ bugnumber9 di bawah ini. Tolong, berikan jawaban itu sebagai jawaban!

John P Bloch
sumber
Dapatkah seseorang memverifikasi bahwa kode ini mencegah orang lain menghapus admin? Saya tidak bisa mereproduksi perilaku itu. Itu memang mencegah mereka dari mengedit, tetapi tautan "delete" hover masih muncul, dan WP memungkinkan pengguna untuk melanjutkan dengan penghapusan ...
somatic
@ Otomatis - Anda tepat. Terima kasih telah menunjukkannya. Masalah sudah diperbaiki sekarang.
John P Bloch
saya perlu melakukan ini juga tetapi tidak yakin di mana saya meletakkan kode ini! Di functions.php? Jika tidak, bagaimana bisa dilakukan untuk bekerja dari functions.php? terbaik, Dc
v3nt
@aniel membaca paragraf pertama.
John P Bloch
1
Bekerja hebat di 3.4.1, terima kasih! Pastikan untuk menambahkan kemampuan untuk create_users, delete_users, add_users, remove_users, edit_users, list_users dan promot_users
Jon Raasch
8

Meskipun berumur ~ 7 tahun, utas ini dapat dengan mudah di-Google-kan dan masih memberikan solusi yang berfungsi. Maksudku kode yang disediakan oleh @John P Bloch.

Yang mengatakan, di bawah PHP 7 itu menghasilkan kesalahan non-kritis (PHP Deprecated) sebagai berikut:

PHP Deprecated: Metode dengan nama yang sama dengan kelas mereka tidak akan menjadi konstruktor dalam versi PHP di masa depan; JPB_User_Caps memiliki konstruktor usang di ...

Untuk memperbaikinya cukup ganti bagian ini:

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

dengan ini:

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

Ini akan memperbaiki masalah.

bugnumber9
sumber
1
Terima kasih terima kasih terima kasih. Saya menghargai dedikasi terhadap kualitas kode dan telah memperbarui jawaban saya sehingga googler biasa juga akan mendapatkan memo itu. Kamu keren!
John P Bloch
3

Saya mencari solusi di mana Editor hanya dapat mengedit menu DAN membuat / mengedit pengguna tanpa memerlukan plugin. Jadi saya akhirnya membuatnya untuk mereka yang tertarik.

// 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
sumber
1

@John P Blochs solusi masih berfungsi dengan baik, tapi saya pikir saya akan membuang filter kecil saya untuk 'map_meta_cap' juga. Sedikit lebih pendek dan lebih bersih, setidaknya untuk mataku;)

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
sumber