Skip to content

Commit

Permalink
REST API: Switch away from using parent as the path argument name (#…
Browse files Browse the repository at this point in the history
…11914)

When `parent` is set as the path argument name, it gets passed down
through to the `create_item()` method and can erroneously reset the
`parent` value on the post itself.

Also ensures revision query params aren't exposed as the query params
for autosaves.

Originally https://core.trac.wordpress.org/attachment/ticket/43316/43316.24.diff
  • Loading branch information
danielbachhuber committed Nov 15, 2018
1 parent 5f44a42 commit ad70868
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 7 deletions.
45 changes: 40 additions & 5 deletions lib/class-wp-rest-autosaves-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public function __construct( $parent_post_type ) {
public function register_routes() {
register_rest_route(
$this->rest_namespace,
'/' . $this->parent_base . '/(?P<parent>[\d]+)/' . $this->rest_base,
'/' . $this->parent_base . '/(?P<id>[\d]+)/' . $this->rest_base,
array(
'args' => array(
'parent' => array(
Expand All @@ -90,14 +90,14 @@ public function register_routes() {
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_items' ),
'permission_callback' => array( $this->revisions_controller, 'get_items_permissions_check' ),
'permission_callback' => array( $this, 'get_items_permissions_check' ),
'args' => $this->get_collection_params(),
),
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array( $this, 'create_item' ),
'permission_callback' => array( $this, 'create_item_permissions_check' ),
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
'args' => $this->parent_controller->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
),
'schema' => array( $this, 'get_public_item_schema' ),
)
Expand Down Expand Up @@ -143,6 +143,28 @@ protected function get_parent( $parent_id ) {
return $this->revisions_controller->get_parent( $parent_id );
}

/**
* Checks if a given request has access to get autosaves.
*
* @since 5.0.0
*
* @param WP_REST_Request $request Full data about the request.
* @return true|WP_Error True if the request has read access, WP_Error object otherwise.
*/
public function get_items_permissions_check( $request ) {
$parent = $this->get_parent( $request['id'] );
if ( is_wp_error( $parent ) ) {
return $parent;
}

$parent_post_type_obj = get_post_type_object( $parent->post_type );
if ( ! current_user_can( $parent_post_type_obj->cap->edit_post, $parent->ID ) ) {
return new WP_Error( 'rest_cannot_read', __( 'Sorry, you are not allowed to view revisions of this post.', 'gutenberg' ), array( 'status' => rest_authorization_required_code() ) );
}

return true;
}

/**
* Checks if a given request has access to create an autosave revision.
*
Expand Down Expand Up @@ -177,7 +199,7 @@ public function create_item( $request ) {
define( 'DOING_AUTOSAVE', true );
}

$post = get_post( $request->get_param( 'id' ) );
$post = get_post( $request['id'] );

if ( is_wp_error( $post ) ) {
return $post;
Expand Down Expand Up @@ -245,7 +267,7 @@ public function get_item( $request ) {
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
public function get_items( $request ) {
$parent = $this->get_parent( $request->get_param( 'parent' ) );
$parent = $this->get_parent( $request['id'] );
if ( is_wp_error( $parent ) ) {
return $parent;
}
Expand Down Expand Up @@ -388,4 +410,17 @@ public function prepare_item_for_response( $post, $request ) {
*/
return apply_filters( 'rest_prepare_autosave', $response, $post, $request );
}

/**
* Retrieves the query params for the autosaves collection.
*
* @since 5.0.0
*
* @return array Collection parameters.
*/
public function get_collection_params() {
return array(
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
);
}
}
89 changes: 87 additions & 2 deletions phpunit/class-rest-autosaves-controller-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@
class WP_Test_REST_Autosaves_Controller extends WP_Test_REST_Post_Type_Controller_Testcase {
protected static $post_id;
protected static $page_id;
protected static $draft_page_id;

protected static $autosave_post_id;
protected static $autosave_page_id;

protected static $editor_id;
protected static $contributor_id;

protected static $parent_page_id;
protected static $child_page_id;
protected static $child_draft_page_id;

protected function set_post_data( $args = array() ) {
$defaults = array(
'title' => 'Post Title',
Expand Down Expand Up @@ -76,6 +81,33 @@ public static function wpSetUpBeforeClass( $factory ) {
)
);

self::$draft_page_id = $factory->post->create(
array(
'post_type' => 'page',
'post_status' => 'draft',
)
);
self::$parent_page_id = $factory->post->create(
array(
'post_type' => 'page',
)
);
self::$child_page_id = $factory->post->create(
array(
'post_type' => 'page',
'post_parent' => self::$parent_page_id,
)
);
self::$child_draft_page_id = $factory->post->create(
array(
'post_type' => 'page',
'post_parent' => self::$parent_page_id,
// The "update post" behavior of the autosave endpoint only occurs
// when saving a draft/auto-draft authored by the current user.
'post_status' => 'draft',
'post_author' => self::$editor_id,
)
);
}

public static function wpTearDownAfterClass() {
Expand All @@ -96,9 +128,9 @@ public function setUp() {

public function test_register_routes() {
$routes = rest_get_server()->get_routes();
$this->assertArrayHasKey( '/wp/v2/posts/(?P<parent>[\d]+)/autosaves', $routes );
$this->assertArrayHasKey( '/wp/v2/posts/(?P<id>[\d]+)/autosaves', $routes );
$this->assertArrayHasKey( '/wp/v2/posts/(?P<parent>[\d]+)/autosaves/(?P<id>[\d]+)', $routes );
$this->assertArrayHasKey( '/wp/v2/pages/(?P<parent>[\d]+)/autosaves', $routes );
$this->assertArrayHasKey( '/wp/v2/pages/(?P<id>[\d]+)/autosaves', $routes );
$this->assertArrayHasKey( '/wp/v2/pages/(?P<parent>[\d]+)/autosaves/(?P<id>[\d]+)', $routes );
}

Expand All @@ -119,6 +151,21 @@ public function test_context_param() {
$this->assertEqualSets( array( 'view', 'edit', 'embed' ), $data['endpoints'][0]['args']['context']['enum'] );
}

public function test_registered_query_params() {
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/posts/' . self::$post_id . '/autosaves' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$keys = array_keys( $data['endpoints'][0]['args'] );
sort( $keys );
$this->assertEquals(
array(
'context',
'parent',
),
$keys
);
}

public function test_get_items() {
wp_set_current_user( self::$editor_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves' );
Expand Down Expand Up @@ -517,4 +564,42 @@ public function test_get_item_sets_up_postdata() {
$this->assertEquals( $parent_post_id, self::$post_id );
}

public function test_update_item_draft_page_with_parent() {
wp_set_current_user( self::$editor_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/pages/' . self::$child_draft_page_id . '/autosaves' );
$request->add_header( 'content-type', 'application/x-www-form-urlencoded' );

$params = $this->set_post_data(
array(
'id' => self::$child_draft_page_id,
'author' => self::$editor_id,
)
);

$request->set_body_params( $params );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();

$this->assertEquals( self::$child_draft_page_id, $data['id'] );
$this->assertEquals( self::$parent_page_id, $data['parent'] );
}

public function test_schema_validation_is_applied() {
wp_set_current_user( self::$editor_id );

$request = new WP_REST_Request( 'POST', '/wp/v2/pages/' . self::$draft_page_id . '/autosaves' );
$request->add_header( 'content-type', 'application/x-www-form-urlencoded' );

$params = $this->set_post_data(
array(
'id' => self::$draft_page_id,
'comment_status' => 'garbage',
)
);

$request->set_body_params( $params );

$response = rest_get_server()->dispatch( $request );
$this->assertNotEquals( 'garbage', get_post( self::$draft_page_id )->comment_status );
}
}

0 comments on commit ad70868

Please sign in to comment.