WordPress.org

Make WordPress Core

Ticket #16860: 16860-with-tests.patch

File 16860-with-tests.patch, 5.2 KB (added by daniellandau, 5 years ago)

Incorporates @jeremyfelt's security improvement and unit tests

  • src/wp-admin/user-new.php

     
    6565        if ( ( $username != null && !is_super_admin( $user_id ) ) && ( array_key_exists($blog_id, get_blogs_of_user($user_id)) ) ) {
    6666                $redirect = add_query_arg( array('update' => 'addexisting'), 'user-new.php' );
    6767        } else {
    68                 if ( isset( $_POST[ 'noconfirmation' ] ) && is_super_admin() ) {
     68                if ( isset( $_POST[ 'noconfirmation' ] ) && current_user_can( 'manage_network_users' ) ) {
    6969                        add_existing_user_to_blog( array( 'user_id' => $user_id, 'role' => $_REQUEST[ 'role' ] ) );
    7070                        $redirect = add_query_arg( array('update' => 'addnoconfirmation'), 'user-new.php' );
    7171                } else {
     
    122122                         * @param string $user_login The sanitized username.
    123123                         */
    124124                        $new_user_login = apply_filters( 'pre_user_login', sanitize_user( wp_unslash( $_REQUEST['user_login'] ), true ) );
    125                         if ( isset( $_POST[ 'noconfirmation' ] ) && is_super_admin() ) {
     125                        if ( isset( $_POST[ 'noconfirmation' ] ) && current_user_can( 'manage_network_users' ) ) {
    126126                                add_filter( 'wpmu_signup_user_notification', '__return_false' ); // Disable confirmation email
    127127                                add_filter( 'wpmu_welcome_user_notification', '__return_false' ); // Disable welcome email
    128128                        }
    129129                        wpmu_signup_user( $new_user_login, $new_user_email, array( 'add_to_blog' => $wpdb->blogid, 'new_role' => $_REQUEST['role'] ) );
    130                         if ( isset( $_POST[ 'noconfirmation' ] ) && is_super_admin() ) {
     130                        if ( isset( $_POST[ 'noconfirmation' ] ) && current_user_can( 'manage_network_users' ) ) {
    131131                                $key = $wpdb->get_var( $wpdb->prepare( "SELECT activation_key FROM {$wpdb->signups} WHERE user_login = %s AND user_email = %s", $new_user_login, $new_user_email ) );
    132132                                wpmu_activate_signup( $key );
    133133                                $redirect = add_query_arg( array('update' => 'addnoconfirmation'), 'user-new.php' );
     
    303303                        </select>
    304304                </td>
    305305        </tr>
    306 <?php if ( is_super_admin() ) { ?>
     306<?php if ( current_user_can( 'manage_network_users' ) ) { ?>
    307307        <tr>
    308308                <th scope="row"><label for="adduser-noconfirmation"><?php _e('Skip Confirmation Email') ?></label></th>
    309309                <td><label for="adduser-noconfirmation"><input type="checkbox" name="noconfirmation" id="adduser-noconfirmation" value="1" /> <?php _e( 'Add the user without sending an email that requires their confirmation.' ); ?></label></td>
     
    418418                        </select>
    419419                </td>
    420420        </tr>
    421         <?php if ( is_multisite() && is_super_admin() ) { ?>
     421        <?php if ( is_multisite() && current_user_can( 'manage_network_users' ) ) { ?>
    422422        <tr>
    423423                <th scope="row"><label for="noconfirmation"><?php _e('Skip Confirmation Email') ?></label></th>
    424424                <td><label for="noconfirmation"><input type="checkbox" name="noconfirmation" id="noconfirmation" value="1" <?php checked( $new_user_ignore_pass ); ?> /> <?php _e( 'Add the user without sending an email that requires their confirmation.' ); ?></label></td>
  • src/wp-includes/capabilities.php

     
    10901090                if ( 'edit_user' == $cap && isset( $args[0] ) && $user_id == $args[0] )
    10911091                        break;
    10921092
    1093                 // If multisite these caps are allowed only for super admins.
    1094                 if ( is_multisite() && !is_super_admin( $user_id ) )
     1093                // In multisite the user must be a super admin, or must have manage_network_users caps and not be editing a super admin.
     1094                if ( is_multisite() && ( ( ! is_super_admin() && 'edit_user' === $cap && is_super_admin( $args[0] ) ) )
     1095                        || ! user_can( $user_id, 'manage_network_users' ) )
    10951096                        $caps[] = 'do_not_allow';
    10961097                else
    10971098                        $caps[] = 'edit_users'; // edit_user maps to edit_users.
  • tests/phpunit/tests/user/capabilities.php

     
    741741                $user->remove_cap( 'publish_pages' );
    742742                $this->assertFalse( $user->has_cap( 'publish_pages' ) );
    743743        }
     744
     745        /**
     746         * @ticket 16860
     747         */
     748        function test_multisite_edit_users_caps() {
     749                if ( ! is_multisite() ) {
     750                        $this->markTestSkipped( 'Test only runs in multisite' );
     751                        return;
     752                }
     753                $user = new WP_User( $this->factory->user->create() );
     754                $user->add_cap( 'manage_network_users' );
     755
     756                $other_user = new WP_User( $this->factory->user->create() );
     757
     758                $super_admin = new WP_User( $this->factory->user->create() );
     759                grant_super_admin( $super_admin->ID );
     760
     761                // Non super admin can never edit super admins
     762                $this->assertFalse( in_array( 'edit_users', map_meta_cap( 'edit_user', $user->ID, $super_admin->ID) ) );
     763                // With manage_network_users can edit normal users
     764                $this->assertTrue( in_array( 'edit_users', map_meta_cap( 'edit_user', $user->ID, $other_user->ID) ) );
     765
     766                // Without manage_network_users can not edit other users
     767                $user->remove_cap( 'manage_network_users' );
     768                $this->assertTrue( in_array( 'do_not_allow', map_meta_cap( 'edit_user', $user->ID, $other_user->ID) ) );
     769
     770                // Can always edit oneself
     771                $this->assertFalse( in_array( 'do_not_allow', map_meta_cap( 'edit_user', $user->ID, $user->ID) ) );
     772        }
    744773}