Make WordPress Core

Ticket #43701: 43701.2.diff

File 43701.2.diff, 5.2 KB (added by rachelbaker, 6 years ago)

Only allow users with the read_private_posts cap to view private posts, not drafts or other non-public statuses. Adds more tests.

  • src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

     
    24892489
    24902490                        $post_type_obj = get_post_type_object( $this->post_type );
    24912491
    2492                         if ( current_user_can( $post_type_obj->cap->edit_posts ) ) {
     2492                        if ( current_user_can( $post_type_obj->cap->edit_posts ) || 'private' === $status && current_user_can( $post_type_obj->cap->read_private_posts ) ) {
    24932493                                $result = rest_validate_request_arg( $status, $request, $parameter );
    24942494                                if ( is_wp_error( $result ) ) {
    24952495                                        return $result;
  • tests/phpunit/tests/rest-api/rest-posts-controller.php

     
    1616        protected static $editor_id;
    1717        protected static $author_id;
    1818        protected static $contributor_id;
     19        protected static $private_reader_id;
    1920
    2021        protected static $supported_formats;
    2122
     
    4748                        )
    4849                );
    4950
     51                self::$private_reader_id = $factory->user->create(
     52                        array(
     53                                'role' => 'private_reader',
     54                        )
     55                );
     56
    5057                if ( is_multisite() ) {
    5158                        update_site_option( 'site_admins', array( 'superadmin' ) );
    5259                }
     
    7077                self::delete_user( self::$editor_id );
    7178                self::delete_user( self::$author_id );
    7279                self::delete_user( self::$contributor_id );
     80                self::delete_user( self::$private_reader_id );
    7381        }
    7482
    7583        public function setUp() {
     
    8189                                'show_in_rest' => true,
    8290                        )
    8391                );
     92
     93                add_role( 'private_reader', 'Private Reader' );
     94                $role = get_role( 'private_reader' );
     95                $role->add_cap( 'read_private_posts' );
     96
    8497                add_filter( 'rest_pre_dispatch', array( $this, 'wpSetUpBeforeRequest' ), 10, 3 );
    8598                add_filter( 'posts_clauses', array( $this, 'save_posts_clauses' ), 10, 2 );
    8699        }
     
    592605                $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
    593606        }
    594607
     608        /**
     609         * @ticket 43701
     610         */
     611        public function test_get_items_multiple_statuses_custom_role_one_invalid_query() {
     612                $private_post_id = $this->factory->post->create( array( 'post_status' => 'private' ) );
     613
     614                wp_set_current_user( self::$private_reader_id );
     615                $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
     616                $request->set_param( 'status', array( 'private', 'future' ) );
     617
     618                $response = rest_get_server()->dispatch( $request );
     619                $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
     620        }
     621
    595622        public function test_get_items_invalid_status_query() {
    596623                wp_set_current_user( 0 );
    597624                $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
     
    11941221                $this->assertContains( '<' . $next_link . '>; rel="next"', $headers['Link'] );
    11951222        }
    11961223
    1197         public function test_get_items_private_status_query_var() {
    1198                 // Private query vars inaccessible to unauthorized users
     1224        public function test_get_items_status_draft_permissions() {
     1225                $draft_id = $this->factory->post->create( array( 'post_status' => 'draft' ) );
     1226
     1227                // Drafts status query var inaccessible to unauthorized users.
    11991228                wp_set_current_user( 0 );
    1200                 $draft_id = $this->factory->post->create( array( 'post_status' => 'draft' ) );
    12011229                $request  = new WP_REST_Request( 'GET', '/wp/v2/posts' );
    12021230                $request->set_param( 'status', 'draft' );
    12031231                $response = rest_get_server()->dispatch( $request );
    12041232                $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
    12051233
    1206                 // But they are accessible to authorized users
     1234                // Users with 'read_private_posts' cap shouldn't also be able to view drafts.
     1235                wp_set_current_user( self::$private_reader_id );
     1236                $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
     1237                $request->set_param( 'status', 'draft' );
     1238                $response = rest_get_server()->dispatch( $request );
     1239                $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
     1240
     1241                // But drafts are accessible to authorized users.
    12071242                wp_set_current_user( self::$editor_id );
    12081243                $response = rest_get_server()->dispatch( $request );
    12091244                $data     = $response->get_data();
     
    12111246                $this->assertEquals( $draft_id, $data[0]['id'] );
    12121247        }
    12131248
     1249        /**
     1250         * @ticket 43701
     1251         */
     1252        public function test_get_items_status_private_permissions() {
     1253                $private_post_id = $this->factory->post->create( array( 'post_status' => 'private' ) );
     1254
     1255                wp_set_current_user( 0 );
     1256                $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
     1257                $request->set_param( 'status', 'private' );
     1258                $response = rest_get_server()->dispatch( $request );
     1259                $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
     1260
     1261                wp_set_current_user( self::$private_reader_id );
     1262                $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
     1263                $request->set_param( 'status', 'private' );
     1264
     1265                $response = rest_get_server()->dispatch( $request );
     1266                $data     = $response->get_data();
     1267                $this->assertEquals( 200, $response->get_status() );
     1268                $this->assertCount( 1, $data );
     1269                $this->assertEquals( $private_post_id, $data[0]['id'] );
     1270        }
     1271
    12141272        public function test_get_items_invalid_per_page() {
    12151273                $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
    12161274                $request->set_query_params( array( 'per_page' => -1 ) );