WordPress.org

Make WordPress Core

Changeset 39349


Ignore:
Timestamp:
11/23/2016 04:14:08 PM (18 months 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.