[wp-trac] [WordPress Trac] #40922: Use finer-grained capabilities with `customize_changeset` post type

WordPress Trac noreply at wordpress.org
Fri Jul 28 02:21:28 UTC 2017


#40922: Use finer-grained capabilities with `customize_changeset` post type
----------------------------------------+------------------
 Reporter:  dlh                         |       Owner:
     Type:  enhancement                 |      Status:  new
 Priority:  normal                      |   Milestone:  4.9
Component:  Customize                   |     Version:  4.7
 Severity:  normal                      |  Resolution:
 Keywords:  has-patch needs-unit-tests  |     Focuses:
----------------------------------------+------------------

Comment (by dlh):

 [attachment:40922.4.diff] would move the mapping to a `'map_meta_cap'`
 filter, which would ensure it applies when either
 `'(delete|edit|read)_post'` or `'(delete|edit|read)_customize_changeset'`
 is used with `current_user_can()`.

 We discussed this question in our earlier Slack chat, but after some
 further digging, I'm back to having the impression that `current_user_can(
 'edit_post', $changeset_post_id )` is at least technically incorrect
 because it bypasses the post type's `map_meta_cap` setting.

 I'll outline the explanation as I understand it, but I would be eager for
 additional guidance or corrections:

 If a `book` post type sets `'capability_type' => 'book'` and
 `'map_meta_cap' => false`, then the expectation is that `current_user_can(
 $book->cap->edit_post, $post_id )` (or `'edit_book'`) would fall all the
 way to the bottom of the `switch` statement in `map_meta_cap()`:
 https://github.com/WordPress/WordPress/blob/master/wp-
 includes/capabilities.php#L499.

 The logic in the `default` case that can call `map_meta_cap()` again
 wouldn't fire because `'edit_book'` wouldn't be present in the
 `$post_type_meta_caps` global. Developers would have to apply custom
 mapping through the `'map_meta_cap'` filter.

 Core defends against someone calling `current_user_can( 'edit_post',
 $post_id )` on a `book` by checking the post type's `map_meta_cap`
 property before applying the default mapping.

 If it's `false`, then the `$cap` and `$caps` are changed to what they
 would have been with `current_user_can( $book->cap->edit_post )`, and we
 `break` straight to the `'map_meta_cap'` filter:
 https://github.com/WordPress/WordPress/blob/master/wp-
 includes/capabilities.php#L149.

 That defensive logic ensures the expected `$cap` and `$caps` are passed to
 the `'map_meta_cap'` filter, so plugins and themes don't notice the
 difference if someone calls `current_user_can( 'edit_post' )`.

 But it becomes a problem for core in [attachment:40922.3.diff] because the
 `break` would prevent us from reaching the new `case` statements, whereas
 `current_user_can( $changeset->cap->edit_post )` would reach them.

 For core, unlike the `book` example, the default post types (except
 `custom_css`) either use the `'post'` capability type or have
 `'map_meta_cap' => true`, so I don't think there are `case`s in
 `map_meta_cap()` being missed. But that would no longer be true with
 [attachment:40922.3.diff].

 Even if this description is accurate, though, I agree that
 `current_user_can( 'edit_post', $changeset_post_id )` shouldn't break.

--
Ticket URL: <https://core.trac.wordpress.org/ticket/40922#comment:16>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list