Make WordPress Core

Changeset 43067


Ignore:
Timestamp:
05/01/2018 10:17:26 PM (8 years ago)
Author:
SergeyBiryukov
Message:

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.
Merges [43001] to the 4.9 branch.
Fixes #42202.

Location:
branches/4.9
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/4.9

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

    r41760 r43067  
    187187                }
    188188
     189                if ( 'authors' === $request['who'] ) {
     190                        $can_view = false;
     191                        $types = get_post_types( array( 'show_in_rest' => true ), 'objects' );
     192                        foreach ( $types as $type ) {
     193                                if ( current_user_can( $type->cap->edit_posts ) ) {
     194                                        $can_view = true;
     195                                }
     196                        }
     197                        if ( ! $can_view ) {
     198                                return new WP_Error( 'rest_forbidden_who', __( 'Sorry, you are not allowed to query users by this parameter.' ), array( 'status' => rest_authorization_required_code() ) );
     199                        }
     200                }
     201
    189202                return true;
    190203        }
     
    251264                }
    252265
    253                 if ( ! current_user_can( 'list_users' ) ) {
     266                if ( isset( $registered['who'] ) && ! empty( $request['who'] ) && 'authors' === $request['who'] ) {
     267                        $prepared_args['who'] = 'authors';
     268                } elseif ( ! current_user_can( 'list_users' ) ) {
    254269                        $prepared_args['has_published_posts'] = get_post_types( array( 'show_in_rest' => true ), 'names' );
    255270                }
     
    13631378                );
    13641379
     1380                $query_params['who'] = array(
     1381                        'description' => __( 'Limit result set to users who are considered authors.' ),
     1382                        'type'        => 'string',
     1383                        'enum'        => array(
     1384                                'authors',
     1385                        ),
     1386                );
     1387
    13651388                /**
    13661389                 * Filter collection parameters for the users controller.
  • branches/4.9/tests/phpunit/tests/rest-api/rest-users-controller.php

    r41760 r43067  
    1515        protected static $editor;
    1616        protected static $draft_editor;
     17        protected static $subscriber;
    1718        protected static $authors = array();
    1819        protected static $posts = array();
     
    3536                        'user_email' => 'draft-editor@example.com',
    3637                ) );
     38                self::$subscriber    = $factory->user->create(
     39                        array(
     40                                'role'         => 'subscriber',
     41                                'display_name' => 'subscriber',
     42                                'user_email'   => 'subscriber@example.com',
     43                        )
     44                );
    3745
    3846                foreach ( array( true, false ) as $show_in_rest ) {
     
    143151                        'search',
    144152                        'slug',
     153                        'who',
    145154                        ), $keys );
    146155        }
     
    254263                $response = $this->server->dispatch( $request );
    255264                $headers = $response->get_headers();
    256                 $this->assertEquals( 53, $headers['X-WP-Total'] );
     265                $this->assertEquals( 54, $headers['X-WP-Total'] );
    257266                $this->assertEquals( 6, $headers['X-WP-TotalPages'] );
    258267                $next_link = add_query_arg( array(
     
    269278                $response = $this->server->dispatch( $request );
    270279                $headers = $response->get_headers();
    271                 $this->assertEquals( 54, $headers['X-WP-Total'] );
     280                $this->assertEquals( 55, $headers['X-WP-Total'] );
    272281                $this->assertEquals( 6, $headers['X-WP-TotalPages'] );
    273282                $prev_link = add_query_arg( array(
     
    284293                $response = $this->server->dispatch( $request );
    285294                $headers = $response->get_headers();
    286                 $this->assertEquals( 54, $headers['X-WP-Total'] );
     295                $this->assertEquals( 55, $headers['X-WP-Total'] );
    287296                $this->assertEquals( 6, $headers['X-WP-TotalPages'] );
    288297                $prev_link = add_query_arg( array(
     
    296305                $response = $this->server->dispatch( $request );
    297306                $headers = $response->get_headers();
    298                 $this->assertEquals( 54, $headers['X-WP-Total'] );
     307                $this->assertEquals( 55, $headers['X-WP-Total'] );
    299308                $this->assertEquals( 6, $headers['X-WP-TotalPages'] );
    300309                $prev_link = add_query_arg( array(
     
    485494        public function test_get_items_offset() {
    486495                wp_set_current_user( self::$user );
    487                 // 7 users created in wpSetUpBeforeClass(), plus default user.
     496                // 9 users created in wpSetUpBeforeClass(), plus default user.
    488497                $this->factory->user->create();
    489498                $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
    490499                $request->set_param( 'offset', 1 );
    491500                $response = $this->server->dispatch( $request );
    492                 $this->assertCount( 9, $response->get_data() );
     501                $this->assertCount( 10, $response->get_data() );
    493502                // 'offset' works with 'per_page'
    494503                $request->set_param( 'per_page', 2 );
     
    664673                $response = $this->server->dispatch( $request );
    665674                $data = $response->get_data();
    666                 $this->assertEquals( 2, count( $data ) );
    667                 $this->assertEquals( $tango, $data[0]['id'] );
    668                 $this->assertEquals( $yolo, $data[1]['id'] );
     675                $this->assertEquals( 3, count( $data ) );
     676                $this->assertEquals( $tango, $data[1]['id'] );
     677                $this->assertEquals( $yolo, $data[2]['id'] );
    669678                $request->set_param( 'roles', 'author' );
    670679                $response = $this->server->dispatch( $request );
     
    697706                $this->assertEquals( 0, count( $data ) );
    698707                $this->assertEquals( array(), $data );
     708        }
     709
     710        public function test_get_items_who_author_query() {
     711                wp_set_current_user( self::$superadmin );
     712                // First request should include subscriber in the set.
     713                $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
     714                $request->set_param( 'search', 'subscriber' );
     715                $response = rest_get_server()->dispatch( $request );
     716                $this->assertEquals( 200, $response->get_status() );
     717                $this->assertCount( 1, $response->get_data() );
     718                // Second request should exclude subscriber.
     719                $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
     720                $request->set_param( 'who', 'authors' );
     721                $request->set_param( 'search', 'subscriber' );
     722                $response = rest_get_server()->dispatch( $request );
     723                $this->assertEquals( 200, $response->get_status() );
     724                $this->assertCount( 0, $response->get_data() );
     725        }
     726
     727        public function test_get_items_who_invalid_query() {
     728                wp_set_current_user( self::$user );
     729                $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
     730                $request->set_param( 'who', 'editor' );
     731                $response = rest_get_server()->dispatch( $request );
     732                $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
     733        }
     734
     735        /**
     736         * Any user with 'edit_posts' on a show_in_rest post type
     737         * can view authors. Others (e.g. subscribers) cannot.
     738         */
     739        public function test_get_items_who_unauthorized_query() {
     740                wp_set_current_user( self::$subscriber );
     741                $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
     742                $request->set_param( 'who', 'authors' );
     743                $response = rest_get_server()->dispatch( $request );
     744                $this->assertErrorResponse( 'rest_forbidden_who', $response, 403 );
    699745        }
    700746
  • branches/4.9/tests/qunit/fixtures/wp-api-generated.js

    r42032 r43067  
    25052505                                "type": "string"
    25062506                            }
     2507                        },
     2508                        "who": {
     2509                            "required": false,
     2510                            "enum": [
     2511                                "authors"
     2512                            ],
     2513                            "description": "Limit result set to users who are considered authors.",
     2514                            "type": "string"
    25072515                        }
    25082516                    }
Note: See TracChangeset for help on using the changeset viewer.