Make WordPress Core

Changeset 40111


Ignore:
Timestamp:
02/24/2017 08:45:52 PM (10 years ago)
Author:
SergeyBiryukov
Message:

REST API: Do not allow access to users from a different site in multisite.

It has been unintendedly possible to both view and edit users from a different site than the current site in multisite environments. Moreover, when passing roles to a user in an update request, that user would implicitly be added to the current site.

This changeset removes the incorrect behavior for now in order to be able to provide a proper REST API workflow for managing multisite users in the near future. Related unit tests have been adjusted as well.

Props jnylen0, jeremyfelt, johnjamesjacoby.
Merges [40106] to the 4.7 branch.
Fixes #39701.

Location:
branches/4.7
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/4.7

  • branches/4.7/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php

    r39957 r40111  
    351351                }
    352352
     353                if ( is_multisite() && ! is_user_member_of_blog( $user->ID ) ) {
     354                        return $error;
     355                }
     356
    353357                return $user;
    354358        }
     
    638642                /* This action is documented in lib/endpoints/class-wp-rest-users-controller.php */
    639643                do_action( 'rest_insert_user', $user, $request, false );
    640 
    641                 if ( is_multisite() && ! is_user_member_of_blog( $id ) ) {
    642                         add_user_to_blog( get_current_blog_id(), $id, '' );
    643                 }
    644644
    645645                if ( ! empty( $request['roles'] ) ) {
  • branches/4.7/tests/phpunit/tests/rest-api/rest-users-controller.php

    r39957 r40111  
    686686                $request->set_param( 'context', 'edit' );
    687687                $response = $this->server->dispatch( $request );
    688                 $data = $response->get_data();
    689 
    690                 $this->assertEquals( $data['capabilities'], new stdClass() );
    691                 $this->assertEquals( $data['extra_capabilities'], new stdClass() );
     688
     689                if ( is_multisite() ) {
     690                        $this->assertErrorResponse( 'rest_user_invalid_id', $response, 404 );
     691                } else {
     692                        $data = $response->get_data();
     693
     694                        $this->assertEquals( $data['capabilities'], new stdClass() );
     695                        $this->assertEquals( $data['extra_capabilities'], new stdClass() );
     696                }
    692697        }
    693698
     
    9971002                        }
    9981003                }
    999         }
    1000 
    1001         public function test_update_existing_network_user_on_sub_site_adds_user_to_site() {
    1002                 if ( ! is_multisite() ) {
    1003                         $this->markTestSkipped( 'Test requires multisite.' );
    1004                 }
    1005 
    1006                 $this->allow_user_to_manage_multisite();
    1007 
    1008                 $params = array(
    1009                         'username' => 'testuser123',
    1010                         'password' => 'testpassword',
    1011                         'email'    => 'test@example.com',
    1012                         'name'     => 'Test User 123',
    1013                         'roles'    => array( 'editor' ),
    1014                 );
    1015 
    1016                 $request = new WP_REST_Request( 'POST', '/wp/v2/users' );
    1017                 $request->add_header( 'content-type', 'application/x-www-form-urlencoded' );
    1018                 $request->set_body_params( $params );
    1019                 $response = $this->server->dispatch( $request );
    1020                 $data = $response->get_data();
    1021                 $user_id = $data['id'];
    1022 
    1023                 switch_to_blog( self::$site );
    1024 
    1025                 $request = new WP_REST_Request( 'PUT', '/wp/v2/users/' . $user_id );
    1026                 $request->add_header( 'content-type', 'application/x-www-form-urlencoded' );
    1027                 $request->set_body_params( $params );
    1028                 $this->server->dispatch( $request );
    1029 
    1030                 restore_current_blog();
    1031 
    1032                 $user_is_member = is_user_member_of_blog( $user_id, self::$site );
    1033 
    1034                 wpmu_delete_user( $user_id );
    1035 
    1036                 $this->assertTrue( $user_is_member );
    10371004        }
    10381005
     
    21522119        }
    21532120
     2121        /**
     2122         * @ticket 39701
     2123         */
     2124        public function test_get_item_from_different_site_as_site_administrator() {
     2125                if ( ! is_multisite() ) {
     2126                        $this->markTestSkipped( 'Test only runs in multisite' );
     2127                }
     2128
     2129                switch_to_blog( self::$site );
     2130                $user_id = $this->factory->user->create( array(
     2131                        'role' => 'author',
     2132                ) );
     2133                restore_current_blog();
     2134
     2135                wp_set_current_user( self::$user );
     2136                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', $user_id ) );
     2137
     2138                $response = $this->server->dispatch( $request );
     2139                $this->assertErrorResponse( 'rest_user_invalid_id', $response, 404 );
     2140        }
     2141
     2142        /**
     2143         * @ticket 39701
     2144         */
     2145        public function test_get_item_from_different_site_as_network_administrator() {
     2146                if ( ! is_multisite() ) {
     2147                        $this->markTestSkipped( 'Test only runs in multisite' );
     2148                }
     2149
     2150                switch_to_blog( self::$site );
     2151                $user_id = $this->factory->user->create( array(
     2152                        'role' => 'author',
     2153                ) );
     2154                restore_current_blog();
     2155
     2156                wp_set_current_user( self::$superadmin );
     2157                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', $user_id ) );
     2158
     2159                $response = $this->server->dispatch( $request );
     2160                $this->assertErrorResponse( 'rest_user_invalid_id', $response, 404 );
     2161        }
     2162
     2163        /**
     2164         * @ticket 39701
     2165         */
     2166        public function test_update_item_from_different_site_as_site_administrator() {
     2167                if ( ! is_multisite() ) {
     2168                        $this->markTestSkipped( 'Test only runs in multisite' );
     2169                }
     2170
     2171                switch_to_blog( self::$site );
     2172                $user_id = $this->factory->user->create( array(
     2173                        'role' => 'author',
     2174                ) );
     2175                restore_current_blog();
     2176
     2177                wp_set_current_user( self::$user );
     2178                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/users/%d', $user_id ) );
     2179                $request->add_header( 'content-type', 'application/x-www-form-urlencoded' );
     2180                $request->set_body_params( array( 'first_name' => 'New Name' ) );
     2181
     2182                $response = $this->server->dispatch( $request );
     2183                $this->assertErrorResponse( 'rest_user_invalid_id', $response, 404 );
     2184        }
     2185
     2186        /**
     2187         * @ticket 39701
     2188         */
     2189        public function test_update_item_from_different_site_as_network_administrator() {
     2190                if ( ! is_multisite() ) {
     2191                        $this->markTestSkipped( 'Test only runs in multisite' );
     2192                }
     2193
     2194                switch_to_blog( self::$site );
     2195                $user_id = $this->factory->user->create( array(
     2196                        'role' => 'author',
     2197                ) );
     2198                restore_current_blog();
     2199
     2200                wp_set_current_user( self::$superadmin );
     2201                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/users/%d', $user_id ) );
     2202                $request->add_header( 'content-type', 'application/x-www-form-urlencoded' );
     2203                $request->set_body_params( array( 'first_name' => 'New Name' ) );
     2204
     2205                $response = $this->server->dispatch( $request );
     2206                $this->assertErrorResponse( 'rest_user_invalid_id', $response, 404 );
     2207        }
     2208
     2209        /**
     2210         * @ticket 39701
     2211         */
     2212        public function test_delete_item_from_different_site_as_site_administrator() {
     2213                if ( ! is_multisite() ) {
     2214                        $this->markTestSkipped( 'Test only runs in multisite' );
     2215                }
     2216
     2217                switch_to_blog( self::$site );
     2218                $user_id = $this->factory->user->create( array(
     2219                        'role' => 'author',
     2220                ) );
     2221                restore_current_blog();
     2222
     2223                wp_set_current_user( self::$user );
     2224                $request = new WP_REST_Request( 'DELETE', sprintf( '/wp/v2/users/%d', $user_id ) );
     2225                $request->set_param( 'force', true );
     2226                $request->set_param( 'reassign', false );
     2227
     2228                $response = $this->server->dispatch( $request );
     2229                $this->assertErrorResponse( 'rest_user_invalid_id', $response, 404 );
     2230        }
     2231
     2232        /**
     2233         * @ticket 39701
     2234         */
     2235        public function test_delete_item_from_different_site_as_network_administrator() {
     2236                if ( ! is_multisite() ) {
     2237                        $this->markTestSkipped( 'Test only runs in multisite' );
     2238                }
     2239
     2240                switch_to_blog( self::$site );
     2241                $user_id = $this->factory->user->create( array(
     2242                        'role' => 'author',
     2243                ) );
     2244                restore_current_blog();
     2245
     2246                wp_set_current_user( self::$superadmin );
     2247                $request = new WP_REST_Request( 'DELETE', sprintf( '/wp/v2/users/%d', $user_id ) );
     2248                $request->set_param( 'force', true );
     2249                $request->set_param( 'reassign', false );
     2250
     2251                $response = $this->server->dispatch( $request );
     2252                $this->assertErrorResponse( 'rest_user_invalid_id', $response, 404 );
     2253        }
     2254
    21542255        public function additional_field_get_callback( $object ) {
    21552256                return get_user_meta( $object['id'], 'my_custom_int', true );
Note: See TracChangeset for help on using the changeset viewer.