Make WordPress Core

Changeset 39843


Ignore:
Timestamp:
01/11/2017 02:13:48 PM (10 years ago)
Author:
aaroncampbell
Message:

REST API: Change which users are shown in the users endpoint.

Only show users that have authored a post of a post type that has show_in_rest set to true.

Props rachelbaker, jnylen0.
See #38878.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php

    r39671 r39843  
    250250
    251251                if ( ! current_user_can( 'list_users' ) ) {
    252                         $prepared_args['has_published_posts'] = true;
     252                        $prepared_args['has_published_posts'] = get_post_types( array( 'show_in_rest' => true ), 'names' );
    253253                }
    254254
  • trunk/tests/phpunit/tests/rest-api/rest-users-controller.php

    r39660 r39843  
    1414        protected static $user;
    1515        protected static $editor;
     16        protected static $editor2;
     17        protected static $secret_editor;
     18        protected static $secret_editor2;
    1619        protected static $site;
    1720
     
    2831                        'user_email' => 'editor@example.com',
    2932                ) );
     33                self::$editor2 = $factory->user->create( array(
     34                        'role'       => 'editor',
     35                        'user_email' => 'editor2@example.com',
     36                ) );
     37                self::$secret_editor = $factory->user->create( array(
     38                        'role'       => 'editor',
     39                        'user_email' => 'secret_editor@example.com',
     40                ) );
     41                self::$secret_editor2 = $factory->user->create( array(
     42                        'role'       => 'editor',
     43                        'user_email' => 'secret_editor2@example.com',
     44                ) );
    3045
    3146                if ( is_multisite() ) {
     
    3853                self::delete_user( self::$user );
    3954                self::delete_user( self::$editor );
     55                self::delete_user( self::$editor2 );
     56                self::delete_user( self::$secret_editor );
     57                self::delete_user( self::$secret_editor2 );
    4058
    4159                if ( is_multisite() ) {
     
    4967        public function setUp() {
    5068                parent::setUp();
     69
     70                register_post_type( 'rest_public', array( 'public' => true, 'show_in_rest' => true ) );
     71                register_post_type( 'secret_public', array( 'public' => true, 'show_in_rest' => false ) );
     72                register_post_type( 'secret_hidden', array( 'public' => false, 'show_in_rest' => false ) );
     73                register_post_type( 'rest_hidden', array( 'public' => false, 'show_in_rest' => true ) );
     74
    5175                $this->endpoint = new WP_REST_Users_Controller();
    5276        }
     
    145169        }
    146170
    147         public function test_get_items_unauthenticated_only_shows_public_users() {
    148                 $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
    149                 $response = $this->server->dispatch( $request );
    150 
    151                 $this->assertEquals( array(), $response->get_data() );
    152 
    153                 $this->factory->post->create( array( 'post_author' => self::$editor ) );
    154                 $this->factory->post->create( array( 'post_author' => self::$user, 'post_status' => 'draft' ) );
     171        public function test_get_items_unauthenticated_includes_authors_of_post_types_shown_in_rest() {
     172                $created_posts = array();
     173                $created_posts[] = $this->factory->post->create( array(
     174                        'post_author' => self::$user,
     175                        'post_status' => 'publish',
     176                ) );
     177                // Expose authors if show_in_rest is true, even if the post_type is not public.
     178                $created_posts[] = $this->factory->post->create( array(
     179                        'post_type' => 'rest_hidden',
     180                        'post_author' => self::$editor,
     181                        'post_status' => 'publish',
     182                ) );
     183                $created_posts[] = $this->factory->post->create( array(
     184                        'post_type' => 'rest_public',
     185                        'post_author' => self::$editor2,
     186                        'post_status' => 'publish',
     187                ) );
     188                $created_posts[] = $this->factory->post->create( array(
     189                        'post_type' => 'rest_public',
     190                        'post_author' => self::$secret_editor,
     191                        'post_status' => 'draft',
     192                ) );
    155193
    156194                $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
     
    158196                $users = $response->get_data();
    159197
     198                $public_post_types = array_values( get_post_types( array( 'show_in_rest' => true ), 'names' ) );
     199
    160200                foreach ( $users as $user ) {
    161                         $this->assertTrue( count_user_posts( $user['id'] ) > 0 );
    162 
    163                         // Ensure we don't expose non-public data
     201                        $this->assertTrue( count_user_posts( $user['id'], $public_post_types ) > 0 );
     202
     203                        // Ensure we don't expose non-public data.
    164204                        $this->assertArrayNotHasKey( 'capabilities', $user );
     205                        $this->assertArrayNotHasKey( 'registered_date', $user );
     206                        $this->assertArrayNotHasKey( 'first_name', $user );
     207                        $this->assertArrayNotHasKey( 'last_name', $user );
     208                        $this->assertArrayNotHasKey( 'nickname', $user );
     209                        $this->assertArrayNotHasKey( 'extra_capabilities', $user );
     210                        $this->assertArrayNotHasKey( 'username', $user );
    165211                        $this->assertArrayNotHasKey( 'email', $user );
    166212                        $this->assertArrayNotHasKey( 'roles', $user );
     213                        $this->assertArrayNotHasKey( 'locale', $user );
     214                }
     215
     216                $this->assertTrue( in_array( self::$user, wp_list_pluck( $users, 'id' ), true ) );
     217                $this->assertTrue( in_array( self::$editor, wp_list_pluck( $users, 'id' ), true ) );
     218                $this->assertTrue( in_array( self::$editor2, wp_list_pluck( $users, 'id' ), true ) );
     219
     220                // Do not include authors of unpublished posts.
     221                $this->assertFalse( in_array( self::$secret_editor, wp_list_pluck( $users, 'id' ), true ) );
     222
     223                foreach ( $created_posts as $post_id ) {
     224                        wp_delete_post( $post_id, true );
     225                }
     226        }
     227
     228        public function test_get_items_unauthenticated_does_not_include_authors_of_post_types_not_shown_in_rest() {
     229                $created_posts = array();
     230                $created_posts[] = $this->factory->post->create( array(
     231                        'post_type' => 'secret_hidden',
     232                        'post_author' => self::$secret_editor,
     233                        'post_status' => 'publish',
     234                ) );
     235                $created_posts[] = $this->factory->post->create( array(
     236                        'post_type' => 'secret_public',
     237                        'post_author' => self::$secret_editor2,
     238                        'post_status' => 'publish',
     239                ) );
     240
     241                $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
     242                $response = $this->server->dispatch( $request );
     243                $data = $response->get_data();
     244
     245                $this->assertFalse( in_array( self::$secret_editor, wp_list_pluck( $data, 'id' ), true ) );
     246                $this->assertFalse( in_array( self::$secret_editor2, wp_list_pluck( $data, 'id' ), true ) );
     247
     248                foreach ( $created_posts as $post_id ) {
     249                        wp_delete_post( $post_id, true );
    167250                }
    168251        }
     
    170253        public function test_get_items_pagination_headers() {
    171254                wp_set_current_user( self::$user );
    172                 // Start of the index, including the three existing users
    173                 for ( $i = 0; $i < 47; $i++ ) {
     255                // Start of the index, including the six existing users.
     256                for ( $i = 0; $i < 44; $i++ ) {
    174257                        $this->factory->user->create( array(
    175258                                'name'   => "User {$i}",
     
    392475        public function test_get_items_offset() {
    393476                wp_set_current_user( self::$user );
    394                 // 2 users created in __construct(), plus default user
     477                // 5 users created in __construct(), plus default user.
    395478                $this->factory->user->create();
    396479                $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
    397480                $request->set_param( 'offset', 1 );
    398481                $response = $this->server->dispatch( $request );
    399                 $this->assertCount( 4, $response->get_data() );
     482                $this->assertCount( 7, $response->get_data() );
    400483                // 'offset' works with 'per_page'
    401484                $request->set_param( 'per_page', 2 );
     
    20842167
    20852168        public function tearDown() {
     2169                _unregister_post_type( 'rest_public' );
     2170                _unregister_post_type( 'secret_public' );
     2171                _unregister_post_type( 'secret_hidden' );
     2172                _unregister_post_type( 'rest_hidden' );
     2173
    20862174                parent::tearDown();
    20872175        }
Note: See TracChangeset for help on using the changeset viewer.