REST API: Allow site administrators to edit user roles in multisite.

While site administrators cannot generally edit users in multisite, they have always been able to change the roles of users on their site. In the REST API however, this has not been possible so far. This changeset brings parity with how it is handled in the administration panel: A REST request to edit only a user's roles succeeds correctly, while a REST request to edit any further details of a user fails.

Props jnylen0.
Fixes #40263.


git-svn-id: https://develop.svn.wordpress.org/trunk@41226 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Felix Arntz 2017-08-03 21:58:50 +00:00
parent 0dc1e0633b
commit 1e9777c220
2 changed files with 76 additions and 4 deletions

View File

@ -561,12 +561,22 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
return $user;
}
if ( ! current_user_can( 'edit_user', $user->ID ) ) {
return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this user.' ), array( 'status' => rest_authorization_required_code() ) );
if ( ! empty( $request['roles'] ) ) {
if ( ! current_user_can( 'promote_user', $user->ID ) ) {
return new WP_Error( 'rest_cannot_edit_roles', __( 'Sorry, you are not allowed to edit roles of this user.' ), array( 'status' => rest_authorization_required_code() ) );
}
$request_params = array_keys( $request->get_params() );
sort( $request_params );
// If only 'id' and 'roles' are specified (we are only trying to
// edit roles), then only the 'promote_user' cap is required.
if ( $request_params === array( 'id', 'roles' ) ) {
return true;
}
}
if ( ! empty( $request['roles'] ) && ! current_user_can( 'edit_users' ) ) {
return new WP_Error( 'rest_cannot_edit_roles', __( 'Sorry, you are not allowed to edit roles of this user.' ), array( 'status' => rest_authorization_required_code() ) );
if ( ! current_user_can( 'edit_user', $user->ID ) ) {
return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this user.' ), array( 'status' => rest_authorization_required_code() ) );
}
return true;

View File

@ -1593,6 +1593,68 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
$this->assertErrorResponse( 'rest_user_invalid_id', $response, 404 );
}
/**
* @ticket 40263
*/
public function test_update_item_only_roles_as_editor() {
$user_id = $this->factory->user->create( array(
'role' => 'author',
) );
wp_set_current_user( self::$editor );
$request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/users/%d', $user_id ) );
$request->set_param( 'roles', array( 'editor' ) );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_edit_roles', $response, 403 );
}
/**
* @ticket 40263
*/
public function test_update_item_only_roles_as_site_administrator() {
$user_id = $this->factory->user->create( array(
'role' => 'author',
) );
wp_set_current_user( self::$user );
$request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/users/%d', $user_id ) );
$request->set_param( 'roles', array( 'editor' ) );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$new_data = $response->get_data();
$this->assertEquals( 'editor', $new_data['roles'][0] );
}
/**
* @ticket 40263
*/
public function test_update_item_including_roles_and_other_params() {
$user_id = $this->factory->user->create( array(
'role' => 'author',
) );
wp_set_current_user( self::$user );
$request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/users/%d', $user_id ) );
$request->set_param( 'roles', array( 'editor' ) );
$request->set_param( 'name', 'Short-Lived User' );
$response = $this->server->dispatch( $request );
if ( is_multisite() ) {
// Site administrators can promote users, as verified by the
// previous test, but they cannot perform other user-editing
// operations. This also tests the branch of logic that verifies
// that no parameters other than 'id' and 'roles' are specified for
// a roles update.
$this->assertErrorResponse( 'rest_cannot_edit', $response, 403 );
} else {
$this->assertEquals( 200, $response->get_status() );
$new_data = $response->get_data();
$this->assertEquals( 'editor', $new_data['roles'][0] );
}
}
public function test_update_item_invalid_password() {
$this->allow_user_to_manage_multisite();
wp_set_current_user( self::$user );