Trình chỉnh sửa có thể tạo bất kỳ người dùng mới nào ngoại trừ quản trị viên


36

Tôi đã thiết lập một trang web WordPress cho một khách hàng. Máy khách có vai trò Trình chỉnh sửa, tuy nhiên tôi đã cài đặt plugin Thành viên và cung cấp cho khách hàng khả năng thêm người dùng mới vào quản trị viên WP. Điều này là làm việc tốt.

Câu hỏi tôi có là tôi muốn khách hàng có khả năng tạo người dùng mới như với vai trò của Người đóng góp, Người đăng ký, Người chỉnh sửa và Tác giả, nhưng KHÔNG phải Quản trị viên. Người dùng mới mà khách hàng tạo không nên có vai trò Quản trị viên. Có thể ẩn tùy chọn này bằng cách nào đó?

Cảm ơn Vayu


2
Vui lòng liên kết các plugin bạn đang sử dụng, tôi gặp vấn đề để tìm ra cái nào bạn đang đề cập đến.
hakre

Câu trả lời:


39

Nó thực sự khá dễ dàng. Bạn cần lọc map_meta_capsvà ngăn các biên tập viên tạo / chỉnh sửa quản trị viên và xóa vai trò quản trị viên khỏi mảng 'vai trò có thể chỉnh sửa'. Lớp này, dưới dạng plugin hoặc trong tệp tin.php của chủ đề của bạn sẽ làm điều đó:

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

CHỈNH SỬA

Ok, vì vậy tôi đã xem xét lý do tại sao nó lại cho phép xóa người dùng. Có vẻ như xóa_user được xử lý hơi khác so với edit_user; Tôi đã sửa đổi phương thức map_meta_cap để khắc phục điều này. Tôi đã thử nghiệm trên 3.0.3 và điều này sẽ ngăn mọi người trừ quản trị viên thực sự xóa, chỉnh sửa hoặc tạo quản trị viên.

CHỈNH SỬA 2

Tôi đã cập nhật mã để phản ánh câu trả lời của @ bugnumber9 bên dưới. Hãy đi cho câu trả lời đó một upvote!


Ai đó có thể xác minh rằng mã này ngăn người khác xóa quản trị viên không? Tôi không thể tái tạo hành vi đó. Nó không ngăn họ chỉnh sửa, nhưng liên kết di chuột "xóa" vẫn xuất hiện và WP cho phép người dùng trải qua việc xóa ...
somatic

@somatic - bạn đã vào vị trí. Cảm ơn đã chỉ ra rằng. Vấn đề được khắc phục ngay bây giờ.
John P Bloch

tôi cũng cần phải làm điều này nhưng không chắc chắn nơi tôi đặt mã này! Trong các hàm.php? Nếu không làm thế nào nó có thể được thực hiện để làm việc từ hàm.php? tốt nhất, Dc
v3nt

@daniel đọc đoạn đầu tiên.
John P Bloch

1
Đã làm việc tuyệt vời trong 3.4.1, cảm ơn! Đảm bảo thêm các khả năng cho created_users, xóa_users, add_users, remove_users, edit_users, list_users và thăng_users
Jon Raasch

8

Mặc dù đã ~ 7 tuổi, chủ đề này có thể được tách ra dễ dàng và vẫn cung cấp một giải pháp làm việc. Ý tôi là mã được cung cấp bởi @John P Bloch.

Điều đó nói rằng, trong PHP 7, nó tạo ra một lỗi không nghiêm trọng (PHP không dùng nữa) như sau:

PHP không dùng nữa: Các phương thức có cùng tên với lớp của chúng sẽ không phải là các hàm tạo trong phiên bản tương lai của PHP; JPB_User_Caps có một hàm tạo không dùng nữa trong ...

Để khắc phục điều này chỉ cần thay thế phần này:

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

Với cái này:

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

Điều này sẽ khắc phục vấn đề.


1
Cảm ơn bạn, cảm ơn bạn, cảm ơn bạn. Tôi đánh giá cao sự cống hiến cho chất lượng mã và đã cập nhật câu trả lời của tôi để những người làm việc bình thường cũng sẽ có được bản ghi nhớ. Bạn đá!
John P Bloch

3

Tôi đang tìm kiếm một giải pháp trong đó Trình chỉnh sửa chỉ có thể chỉnh sửa các menu VÀ tạo / chỉnh sửa người dùng mà không cần plugin. Vì vậy, tôi đã kết thúc việc làm nó cho những người quan tâm.

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

1

@John P Giải pháp Blochs vẫn hoạt động tốt, nhưng tôi nghĩ rằng tôi cũng sẽ ném vào bộ lọc nhỏ của mình cho 'map_meta_cap'. Chỉ ngắn hơn một chút và sạch sẽ hơn, ít nhất là đối với mắt tôi;)

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 );
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.