REST API: Add `who=authors` as a query parameter for `GET wp/v2/users`.

Any WordPress user who can `edit_posts` of a post type with `show_in_rest=true` can query for authors. This maps to current WordPress behavior where a WordPress user who can view the Manage Posts view for a post type can see any WordPress user assigned to a post (whether published or draft).

This implementation, over restricting `who=authors` to users with `list_users`, gives us future flexibility in displaying lists of posts. It still respects more restrictive permissions for `context=edit`.

Props danielbachhuber.
Fixes #42202.



git-svn-id: https://develop.svn.wordpress.org/trunk@43001 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Gary Pendergast 2018-04-25 13:05:48 +00:00
parent 6bee78edcf
commit 50e9639f22
3 changed files with 87 additions and 10 deletions

View File

@ -192,6 +192,19 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
return new WP_Error( 'rest_forbidden_orderby', __( 'Sorry, you are not allowed to order users by this parameter.' ), array( 'status' => rest_authorization_required_code() ) );
}
if ( 'authors' === $request['who'] ) {
$can_view = false;
$types = get_post_types( array( 'show_in_rest' => true ), 'objects' );
foreach ( $types as $type ) {
if ( current_user_can( $type->cap->edit_posts ) ) {
$can_view = true;
}
}
if ( ! $can_view ) {
return new WP_Error( 'rest_forbidden_who', __( 'Sorry, you are not allowed to query users by this parameter.' ), array( 'status' => rest_authorization_required_code() ) );
}
}
return true;
}
@ -256,7 +269,9 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
$prepared_args['orderby'] = $orderby_possibles[ $request['orderby'] ];
}
if ( ! current_user_can( 'list_users' ) ) {
if ( isset( $registered['who'] ) && ! empty( $request['who'] ) && 'authors' === $request['who'] ) {
$prepared_args['who'] = 'authors';
} elseif ( ! current_user_can( 'list_users' ) ) {
$prepared_args['has_published_posts'] = get_post_types( array( 'show_in_rest' => true ), 'names' );
}
@ -1372,6 +1387,14 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
),
);
$query_params['who'] = array(
'description' => __( 'Limit result set to users who are considered authors.' ),
'type' => 'string',
'enum' => array(
'authors',
),
);
/**
* Filter collection parameters for the users controller.
*

View File

@ -14,6 +14,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
protected static $user;
protected static $editor;
protected static $draft_editor;
protected static $subscriber;
protected static $authors = array();
protected static $posts = array();
protected static $site;
@ -42,6 +43,13 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
'user_email' => 'draft-editor@example.com',
)
);
self::$subscriber = $factory->user->create(
array(
'role' => 'subscriber',
'display_name' => 'subscriber',
'user_email' => 'subscriber@example.com',
)
);
foreach ( array( true, false ) as $show_in_rest ) {
foreach ( array( true, false ) as $public ) {
@ -166,6 +174,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
'roles',
'search',
'slug',
'who',
), $keys
);
}
@ -280,7 +289,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
$response = rest_get_server()->dispatch( $request );
$headers = $response->get_headers();
$this->assertEquals( 53, $headers['X-WP-Total'] );
$this->assertEquals( 54, $headers['X-WP-Total'] );
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
$next_link = add_query_arg(
array(
@ -299,7 +308,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
$request->set_param( 'page', 3 );
$response = rest_get_server()->dispatch( $request );
$headers = $response->get_headers();
$this->assertEquals( 54, $headers['X-WP-Total'] );
$this->assertEquals( 55, $headers['X-WP-Total'] );
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
$prev_link = add_query_arg(
array(
@ -318,7 +327,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
$request->set_param( 'page', 6 );
$response = rest_get_server()->dispatch( $request );
$headers = $response->get_headers();
$this->assertEquals( 54, $headers['X-WP-Total'] );
$this->assertEquals( 55, $headers['X-WP-Total'] );
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
$prev_link = add_query_arg(
array(
@ -332,7 +341,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
$request->set_param( 'page', 8 );
$response = rest_get_server()->dispatch( $request );
$headers = $response->get_headers();
$this->assertEquals( 54, $headers['X-WP-Total'] );
$this->assertEquals( 55, $headers['X-WP-Total'] );
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
$prev_link = add_query_arg(
array(
@ -525,12 +534,12 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
public function test_get_items_offset() {
wp_set_current_user( self::$user );
// 7 users created in wpSetUpBeforeClass(), plus default user.
// 9 users created in wpSetUpBeforeClass(), plus default user.
$this->factory->user->create();
$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
$request->set_param( 'offset', 1 );
$response = rest_get_server()->dispatch( $request );
$this->assertCount( 9, $response->get_data() );
$this->assertCount( 10, $response->get_data() );
// 'offset' works with 'per_page'
$request->set_param( 'per_page', 2 );
$response = rest_get_server()->dispatch( $request );
@ -744,9 +753,9 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
$request->set_param( 'roles', 'author,subscriber' );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 2, count( $data ) );
$this->assertEquals( $tango, $data[0]['id'] );
$this->assertEquals( $yolo, $data[1]['id'] );
$this->assertEquals( 3, count( $data ) );
$this->assertEquals( $tango, $data[1]['id'] );
$this->assertEquals( $yolo, $data[2]['id'] );
$request->set_param( 'roles', 'author' );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
@ -784,6 +793,43 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase {
$this->assertEquals( array(), $data );
}
public function test_get_items_who_author_query() {
wp_set_current_user( self::$superadmin );
// First request should include subscriber in the set.
$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
$request->set_param( 'search', 'subscriber' );
$response = rest_get_server()->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$this->assertCount( 1, $response->get_data() );
// Second request should exclude subscriber.
$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
$request->set_param( 'who', 'authors' );
$request->set_param( 'search', 'subscriber' );
$response = rest_get_server()->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$this->assertCount( 0, $response->get_data() );
}
public function test_get_items_who_invalid_query() {
wp_set_current_user( self::$user );
$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
$request->set_param( 'who', 'editor' );
$response = rest_get_server()->dispatch( $request );
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
}
/**
* Any user with 'edit_posts' on a show_in_rest post type
* can view authors. Others (e.g. subscribers) cannot.
*/
public function test_get_items_who_unauthorized_query() {
wp_set_current_user( self::$subscriber );
$request = new WP_REST_Request( 'GET', '/wp/v2/users' );
$request->set_param( 'who', 'authors' );
$response = rest_get_server()->dispatch( $request );
$this->assertErrorResponse( 'rest_forbidden_who', $response, 403 );
}
public function test_get_item() {
$user_id = $this->factory->user->create();
wp_set_current_user( self::$user );

View File

@ -2512,6 +2512,14 @@ mockedApiResponse.Schema = {
"items": {
"type": "string"
}
},
"who": {
"required": false,
"enum": [
"authors"
],
"description": "Limit result set to users who are considered authors.",
"type": "string"
}
}
},