Make WordPress Core

Changeset 39349


Ignore:
Timestamp:
11/23/2016 04:14:08 PM (10 years ago)
Author:
joehoyle
Message:

REST API: Add support for comments of password-protected posts.

Core requires the post password to view and create comments on password protected posts, so we must support a “password” param on the comments endpoint when fetch comments for a specific post and creating a comment on a password protected post.

Props flixos90, jnylen0.
Fixes #38692.

Location:
trunk
Files:
3 edited

Legend:

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

    r39348 r39349  
    7070                                'args'     => array(
    7171                                        'context'          => $this->get_context_param( array( 'default' => 'view' ) ),
     72                                        'password' => array(
     73                                                'description' => __( 'The password for the post if it is password protected.' ),
     74                                                'type'        => 'string',
     75                                        ),
    7276                                ),
    7377                        ),
     
    8892                                                'description' => __( 'Whether to bypass trash and force deletion.' ),
    8993                                        ),
     94                                        'password' => array(
     95                                                'description' => __( 'The password for the post if it is password protected.' ),
     96                                                'type'        => 'string',
     97                                        ),
    9098                                ),
    9199                        ),
     
    109117                                $post = get_post( $post_id );
    110118
    111                                 if ( ! empty( $post_id ) && $post && ! $this->check_read_post_permission( $post ) ) {
     119                                if ( ! empty( $post_id ) && $post && ! $this->check_read_post_permission( $post, $request ) ) {
    112120                                        return new WP_Error( 'rest_cannot_read_post', __( 'Sorry, you are not allowed to read the post for this comment.' ), array( 'status' => rest_authorization_required_code() ) );
    113121                                } elseif ( 0 === $post_id && ! current_user_can( 'moderate_comments' ) ) {
     
    243251
    244252                foreach ( $query_result as $comment ) {
    245                         if ( ! $this->check_read_permission( $comment ) ) {
     253                        if ( ! $this->check_read_permission( $comment, $request ) ) {
    246254                                continue;
    247255                        }
     
    310318                }
    311319
    312                 if ( ! $this->check_read_permission( $comment ) ) {
    313                         return new WP_Error( 'rest_cannot_read', __( 'Sorry, you are not allowed to read this comment.' ), array( 'status' => rest_authorization_required_code() ) );
    314                 }
    315 
    316                 $post = get_post( $comment->comment_post_ID );
    317 
    318                 if ( $post && ! $this->check_read_post_permission( $post ) ) {
    319                         return new WP_Error( 'rest_cannot_read_post', __( 'Sorry, you are not allowed to read the post for this comment.' ), array( 'status' => rest_authorization_required_code() ) );
    320                 }
    321 
    322320                if ( ! empty( $request['context'] ) && 'edit' === $request['context'] && ! current_user_can( 'moderate_comments' ) ) {
    323321                        return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit comments.' ), array( 'status' => rest_authorization_required_code() ) );
     322                }
     323
     324                $post = get_post( $comment->comment_post_ID );
     325
     326                if ( ! $this->check_read_permission( $comment, $request ) ) {
     327                        return new WP_Error( 'rest_cannot_read', __( 'Sorry, you are not allowed to read this comment.' ), array( 'status' => rest_authorization_required_code() ) );
     328                }
     329
     330                if ( $post && ! $this->check_read_post_permission( $post, $request ) ) {
     331                        return new WP_Error( 'rest_cannot_read_post', __( 'Sorry, you are not allowed to read the post for this comment.' ), array( 'status' => rest_authorization_required_code() ) );
    324332                }
    325333
     
    434442                }
    435443
    436                 if ( ! $this->check_read_post_permission( $post ) ) {
     444                if ( ! $this->check_read_post_permission( $post, $request ) ) {
    437445                        return new WP_Error( 'rest_cannot_read_post', __( 'Sorry, you are not allowed to read the post for this comment.' ), array( 'status' => rest_authorization_required_code() ) );
    438446                }
     
    14111419                        'type'              => 'string',
    14121420                        'validate_callback' => 'rest_validate_request_arg',
     1421                );
     1422
     1423                $query_params['password'] = array(
     1424                        'description' => __( 'The password for the post if it is password protected.' ),
     1425                        'type'        => 'string',
    14131426                );
    14141427
     
    14821495         * @access protected
    14831496         *
    1484          * @param WP_Post $post Post Object.
     1497         * @param WP_Post         $post    Post object.
     1498         * @param WP_REST_Request $request Request data to check.
    14851499         * @return bool Whether post can be read.
    14861500         */
    1487         protected function check_read_post_permission( $post ) {
     1501        protected function check_read_post_permission( $post, $request ) {
    14881502                $posts_controller = new WP_REST_Posts_Controller( $post->post_type );
    14891503                $post_type = get_post_type_object( $post->post_type );
    14901504
     1505                $has_password_filter = false;
     1506
     1507                // Only check password if a specific post was queried for or a single comment
     1508                $requested_post = ! empty( $request['post'] ) && 1 === count( $request['post'] );
     1509                $requested_comment = ! empty( $request['id'] );
     1510                if ( ( $requested_post || $requested_comment ) && $posts_controller->can_access_password_content( $post, $request ) ) {
     1511                        add_filter( 'post_password_required', '__return_false' );
     1512
     1513                        $has_password_filter = true;
     1514                }
     1515
    14911516                if ( post_password_required( $post ) ) {
    1492                         return current_user_can( $post_type->cap->edit_post, $post->ID );
    1493                 }
    1494 
    1495                 return $posts_controller->check_read_permission( $post );
     1517                        $result = current_user_can( $post_type->cap->edit_post, $post->ID );
     1518                } else {
     1519                        $result = $posts_controller->check_read_permission( $post );
     1520                }
     1521
     1522                if ( $has_password_filter ) {
     1523                        remove_filter( 'post_password_required', '__return_false' );
     1524                }
     1525
     1526                return $result;
    14961527        }
    14971528
     
    15021533         * @access protected
    15031534         *
    1504          * @param WP_Comment $comment Comment object.
     1535         * @param WP_Comment      $comment Comment object.
     1536         * @param WP_REST_Request $request Request data to check.
    15051537         * @return bool Whether the comment can be read.
    15061538         */
    1507         protected function check_read_permission( $comment ) {
     1539        protected function check_read_permission( $comment, $request ) {
    15081540                if ( ! empty( $comment->comment_post_ID ) ) {
    15091541                        $post = get_post( $comment->comment_post_ID );
    15101542                        if ( $post ) {
    1511                                 if ( $this->check_read_post_permission( $post ) && 1 === (int) $comment->comment_approved ) {
     1543                                if ( $this->check_read_post_permission( $post, $request ) && 1 === (int) $comment->comment_approved ) {
    15121544                                        return true;
    15131545                                }
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

    r39348 r39349  
    384384         *
    385385         * @since 4.7.0
    386          * @access protected
     386         * @access public
    387387         *
    388388         * @param WP_Post         $post    Post to check against.
     
    390390         * @return bool True if the user can access password-protected content, otherwise false.
    391391         */
    392         protected function can_access_password_content( $post, $request ) {
     392        public function can_access_password_content( $post, $request ) {
    393393                if ( empty( $post->post_password ) ) {
    394394                        // No filter required.
  • trunk/tests/phpunit/tests/rest-api/rest-comments-controller.php

    r39337 r39349  
    147147                        'parent',
    148148                        'parent_exclude',
     149                        'password',
    149150                        'per_page',
    150151                        'post',
     
    166167                // We created 6 comments in this method, plus self::$approved_id.
    167168                $this->assertCount( 7, $comments );
     169        }
     170
     171        /**
     172         * @ticket 38692
     173         */
     174        public function test_get_items_with_password() {
     175                wp_set_current_user( 0 );
     176
     177                $args = array(
     178                        'comment_approved' => 1,
     179                        'comment_post_ID'  => self::$password_id,
     180                );
     181                $password_comment = $this->factory->comment->create( $args );
     182
     183                $request = new WP_REST_Request( 'GET', '/wp/v2/comments' );
     184                $request->set_param( 'password', 'toomanysecrets' );
     185                $request->set_param( 'post', self::$password_id );
     186
     187                $response = $this->server->dispatch( $request );
     188                $this->assertEquals( 200, $response->get_status() );
     189
     190                $collection_data = $response->get_data();
     191                $this->assertTrue( in_array( $password_comment, wp_list_pluck( $collection_data, 'id' ), true ) );
     192        }
     193
     194        /**
     195         * @ticket 38692
     196         */
     197        public function test_get_items_with_password_without_post() {
     198                wp_set_current_user( 0 );
     199                $args = array(
     200                        'comment_approved' => 1,
     201                        'comment_post_ID'  => self::$password_id,
     202                );
     203                $password_comment = $this->factory->comment->create( $args );
     204
     205                $request = new WP_REST_Request( 'GET', '/wp/v2/comments' );
     206                $request->set_param( 'password', 'toomanysecrets' );
     207
     208                $response = $this->server->dispatch( $request );
     209                $this->assertEquals( 200, $response->get_status() );
     210
     211                $collection_data = $response->get_data();
     212                $this->assertFalse( in_array( $password_comment, wp_list_pluck( $collection_data, 'id' ), true ) );
     213        }
     214
     215        /**
     216         * @ticket 38692
     217         */
     218        public function test_get_items_with_password_with_multiple_post() {
     219                wp_set_current_user( 0 );
     220                $args = array(
     221                        'comment_approved' => 1,
     222                        'comment_post_ID'  => self::$password_id,
     223                );
     224                $password_comment = $this->factory->comment->create( $args );
     225
     226                $request = new WP_REST_Request( 'GET', '/wp/v2/comments' );
     227                $request->set_param( 'password', 'toomanysecrets' );
     228                $request->set_param( 'post', array( self::$password_id, self::$post_id ) );
     229
     230                $response = $this->server->dispatch( $request );
     231                $this->assertErrorResponse( 'rest_cannot_read_post', $response, 401 );
    168232        }
    169233
     
    854918        }
    855919
     920        /**
     921         * @ticket 38692
     922         */
     923        public function test_get_comment_with_password_with_valid_password() {
     924                wp_set_current_user( self::$subscriber_id );
     925
     926                $args = array(
     927                        'comment_approved' => 1,
     928                        'comment_post_ID'  => self::$password_id,
     929                );
     930                $password_comment = $this->factory->comment->create( $args );
     931
     932                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/comments/%s', $password_comment ) );
     933                $request->set_param( 'password', 'toomanysecrets' );
     934
     935                $response = $this->server->dispatch( $request );
     936                $this->assertEquals( 200, $response->get_status() );
     937        }
     938
    856939        public function test_create_item() {
    857940                wp_set_current_user( self::$admin_id );
     
    17261809
    17271810                $this->assertErrorResponse( 'comment_content_column_length', $response, 400 );
     1811        }
     1812
     1813        public function test_create_comment_without_password() {
     1814                wp_set_current_user( self::$subscriber_id );
     1815
     1816                $params = array(
     1817                        'post'         => self::$password_id,
     1818                        'author_name'  => 'Bleeding Gums Murphy',
     1819                        'author_email' => 'murphy@gingivitis.com',
     1820                        'author_url'   => 'http://jazz.gingivitis.com',
     1821                        'content'      => 'This isn\'t a saxophone. It\'s an umbrella.',
     1822                );
     1823                $request = new WP_REST_Request( 'POST', '/wp/v2/comments' );
     1824
     1825                $request->add_header( 'content-type', 'application/json' );
     1826                $request->set_body( wp_json_encode( $params ) );
     1827                $response = $this->server->dispatch( $request );
     1828
     1829                $this->assertErrorResponse( 'rest_cannot_read_post', $response, 403 );
     1830        }
     1831
     1832        public function test_create_comment_with_password() {
     1833                add_filter( 'rest_allow_anonymous_comments', '__return_true' );
     1834
     1835                $params = array(
     1836                        'post'         => self::$password_id,
     1837                        'author_name'  => 'Bleeding Gums Murphy',
     1838                        'author_email' => 'murphy@gingivitis.com',
     1839                        'author_url'   => 'http://jazz.gingivitis.com',
     1840                        'content'      => 'This isn\'t a saxophone. It\'s an umbrella.',
     1841                        'password'     => 'toomanysecrets',
     1842                );
     1843                $request = new WP_REST_Request( 'POST', '/wp/v2/comments' );
     1844
     1845                $request->add_header( 'content-type', 'application/json' );
     1846                $request->set_body( wp_json_encode( $params ) );
     1847                $response = $this->server->dispatch( $request );
     1848                $this->assertEquals( 201, $response->get_status() );
    17281849        }
    17291850
Note: See TracChangeset for help on using the changeset viewer.