Make WordPress Core

Changeset 39843


Ignore:
Timestamp:
01/11/2017 02:13:48 PM (8 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.