WordPress.org

Make WordPress Core

Opened 20 months ago

Closed 11 months ago

Last modified 11 months ago

#43701 closed defect (bug) (fixed)

Make the "read_private” cap accessible over the REST API

Reported by: twoelevenjay Owned by: danielbachhuber
Milestone: 5.0 Priority: normal
Severity: normal Version: 4.9.5
Component: REST API Keywords: has-patch has-unit-tests
Focuses: rest-api Cc:
PR Number:

Description

When it comes to the "private" status of a post type, WordPress has a separate capability for editing post types and reading private post types. It so happens that default user roles and capabilities do not include one user who can only read a private post type without also having the ability to edit the post type.

When adding the "status" parameter to a rest route, the WP_REST_Posts_Controller checks to see if the current user can edit the private post type. If s user role is set to view a private post type but not edit the post type then a rest route intended to return a private post type on GET for read only purposes will fail.

I propose amending /wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php line 2286.

Changing:

if ( current_user_can( $post_type_obj->cap->edit_posts ) ) {

to:

if ( current_user_can( $post_type_obj->cap->edit_posts ) || current_user_can( $post_type_obj->cap->read_private_posts ) ) {

Attachments (4)

0001-Make-the-read_private-cap-accessible-over-the-REST-A.patch (1.3 KB) - added by twoelevenjay 20 months ago.
Amends /wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php line 2286 to allow reading of private post types when current user caps only allow reading the private post type but not editing it.
43701.diff (2.2 KB) - added by soulseekah 20 months ago.
tests + fix
43701.2.diff (5.2 KB) - added by rachelbaker 15 months ago.
Only allow users with the read_private_posts cap to view private posts, not drafts or other non-public statuses. Adds more tests.
43701.3.diff (5.9 KB) - added by danielbachhuber 13 months ago.
Refreshes 43701.2.diff against the 5.0 branch

Download all attachments as: .zip

Change History (15)

#1 @twoelevenjay
20 months ago

  • Summary changed from Make the "read_only" cap truly accessible over the REST API to Make the "read_private” cap accessible over the REST API

@twoelevenjay
20 months ago

Amends /wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php line 2286 to allow reading of private post types when current user caps only allow reading the private post type but not editing it.

@soulseekah
20 months ago

tests + fix

#2 @soulseekah
20 months ago

  • Keywords has-patch has-unit-tests added

Hey, Leon! Welcome to Trac! :)

This does seem to be a valid bug. I was able to reproduce this in the following theoretical use-case:

  1. Create a user role, called Paid Subscriber, inherits all capabilities from Subscriber, but also gets read_private_posts cap.
  2. Try to access a private post on the frontend. Works.
  3. Try to access a private post via the REST API. Works.
  4. Try to get a list of private posts via the REST API. Doesn't work.

0001-Make-the-read_private-cap-accessible-over-the-REST-A.patch, although formatted incorrectly, solves the issue.

43701.diff includes a test for the scenario, and the 0001-Make-the-read_private-cap-accessible-over-the-REST-A.patch fix.

#3 @SergeyBiryukov
19 months ago

  • Milestone changed from Awaiting Review to 5.0

@rachelbaker
15 months ago

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

#4 @rachelbaker
15 months ago

  • Keywords commit added

43701.2.diff is a refresh of @soulseekah's earlier patch. It limits allowing users with the edit_private_posts to viewing only 'private' posts.
If possible, I would like to get another set of eyes since this is dealing with user capabilities. I did add more tests though so I am feeling fairly good about this as is.

#5 @rachelbaker
13 months ago

@danielbachhuber want to take a look at this before I commit it?

#6 @danielbachhuber
13 months ago

+1 to 43701.2.diff although I think it needs a refresh.

I grepped core to see if there was prior art for this exact conditional, but I wasn't able to find an example. However, with this being said, the visibility of a Post is also asserted with WP_REST_Posts_Controller->check_read_permission(), so I feel reasonably confident in this change.

This ticket was mentioned in Slack in #core-committers by danielbachhuber. View the logs.


13 months ago

@danielbachhuber
13 months ago

Refreshes 43701.2.diff against the 5.0 branch

#8 @danielbachhuber
13 months ago

  • Owner set to danielbachhuber
  • Resolution set to fixed
  • Status changed from new to closed

In 43694:

REST API: Enable users with read_private_posts to query for them.

An authorized request with the read_private_posts capability for a post type should be able to GET /wp/v2/posts for posts of status=private. This query is further sanity-checked by WP_REST_Posts_Controller->check_read_permission(), which is unchanged.

Props rachelbaker, soulseekah, twoelevenjay.
Fixes #43701.

#9 @SergeyBiryukov
13 months ago

  • Keywords fixed-5.0 added
  • Resolution fixed deleted
  • Status changed from closed to reopened

Reopening for merging to trunk.

#10 @desrosj
11 months ago

  • Resolution set to fixed
  • Status changed from reopened to closed

In 43979:

REST API: Enable users with read_private_posts to query for them.

An authorized request with the read_private_posts capability for a post type should be able to GET /wp/v2/posts for posts of status=private. This query is further sanity-checked by WP_REST_Posts_Controller->check_read_permission(), which is unchanged.

Props rachelbaker, soulseekah, twoelevenjay.

Moves [43694] from the 5.0 branch to trunk.

Fixes #43701.

#11 @desrosj
11 months ago

  • Keywords commit fixed-5.0 removed
Note: See TracTickets for help on using tickets.