Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REST API: Add action-delete flag to declare delete_post capability for post objects #335

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1981,10 +1981,14 @@ protected function get_available_actions( $post, $request ) {

$post_type = get_post_type_object( $post->post_type );

if ( 'attachment' !== $this->post_type && current_user_can( $post_type->cap->publish_posts ) ) {
if ( 'attachment' !== $this->post_type && current_user_can( 'publish_post', $post->ID ) ) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is an action for the specific post we should use the meta cap and pass the post ID to the check. By default this just falls back to publish_posts.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$rels[] = 'https://api.w.org/action-publish';
}

if ( current_user_can( 'delete_post', $post->ID ) ) {
$rels[] = 'https://api.w.org/action-delete';
}

if ( current_user_can( 'unfiltered_html' ) ) {
$rels[] = 'https://api.w.org/action-unfiltered-html';
}
Expand Down Expand Up @@ -2462,6 +2466,20 @@ protected function get_schema_links() {
);
}

$links[] = array(
'rel' => 'https://api.w.org/action-delete',
'title' => __( 'The current user can delete this post.' ),
'href' => $href,
'targetSchema' => array(
'type' => 'object',
'properties' => array(
'delete' => array(
'type' => 'boolean',
),
),
Comment on lines +2475 to +2479
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably needs to be something else?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea of the targetSchema is so that a developer can programmatically determine that changing the resource such that it would successfully validate against the targetSchema would require a specific set of capabilities beyond PUT being available in the Allow header. The developer can then verify that the resource includes this link in the response.

Since a post is deleted by making a DELETE request instead of a PUT, the targetSchema can't actually be used and the link relation solely communicates the semantics.

So we could drop the targetSchema entirely.

),
);

$links[] = array(
'rel' => 'https://api.w.org/action-unfiltered-html',
'title' => __( 'The current user can post unfiltered HTML markup and JavaScript.' ),
Expand Down
41 changes: 41 additions & 0 deletions tests/phpunit/tests/rest-api/rest-posts-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
protected static $author_id;
protected static $contributor_id;
protected static $private_reader_id;
protected static $custom_author_id;

protected static $supported_formats;
protected static $post_ids = array();
Expand Down Expand Up @@ -57,6 +58,12 @@ public static function wpSetUpBeforeClass( $factory ) {
)
);

self::$custom_author_id = $factory->user->create(
array(
'role' => 'custom_author',
)
);

if ( is_multisite() ) {
update_site_option( 'site_admins', array( 'superadmin' ) );
}
Expand Down Expand Up @@ -111,6 +118,11 @@ public function setUp() {
$role = get_role( 'private_reader' );
$role->add_cap( 'read_private_posts' );

add_role( 'custom_author', 'Custom Author' );
$role = get_role( 'custom_author' );
$role->add_cap( 'edit_posts' );
$role->add_cap( 'edit_published_posts' );

add_filter( 'rest_pre_dispatch', array( $this, 'wpSetUpBeforeRequest' ), 10, 3 );
add_filter( 'posts_clauses', array( $this, 'save_posts_clauses' ), 10, 2 );
}
Expand Down Expand Up @@ -4384,6 +4396,35 @@ public function test_sticky_action_does_not_exist_for_non_post_posts() {
$this->assertArrayNotHasKey( 'https://api.w.org/action-sticky', $links );
}

public function test_delete_action_link_exists_for_author() {
wp_set_current_user( self::$author_id );

$post = self::factory()->post->create( array( 'post_author' => self::$author_id ) );
$this->assertGreaterThan( 0, $post );

$request = new WP_REST_Request( 'GET', "/wp/v2/posts/{$post}" );
$request->set_query_params( array( 'context' => 'edit' ) );

$response = rest_get_server()->dispatch( $request );
$links = $response->get_links();

$this->assertArrayHasKey( 'https://api.w.org/action-delete', $links );
}

public function test_delete_action_link_does_not_exist_for_custom_author() {
wp_set_current_user( self::$custom_author_id );

$post = self::factory()->post->create( array( 'post_author' => self::$custom_author_id ) );
$this->assertGreaterThan( 0, $post );

$request = new WP_REST_Request( 'GET', "/wp/v2/posts/{$post}" );
$request->set_query_params( array( 'context' => 'edit' ) );

$response = rest_get_server()->dispatch( $request );
$links = $response->get_links();

$this->assertArrayNotHasKey( 'https://api.w.org/action-delete', $links );
}

public function test_assign_author_action_exists_for_editor() {
wp_set_current_user( self::$editor_id );
Expand Down