[wp-trac] [WordPress Trac] #48426: All registered meta require the same caps on 5.3-RC2-46575

WordPress Trac noreply at wordpress.org
Thu Oct 24 18:20:56 UTC 2019


#48426: All registered meta require the same caps on 5.3-RC2-46575
----------------------------+-----------------------------
 Reporter:  johnstonphilip  |      Owner:  (none)
     Type:  defect (bug)    |     Status:  new
 Priority:  normal          |  Milestone:  Awaiting Review
Component:  General         |    Version:  trunk
 Severity:  normal          |   Keywords:
  Focuses:                  |
----------------------------+-----------------------------
 On WP 5.3-RC2-46575, if you update any meta via the REST API via
 Gutenberg, all meta gets updated. If any of those meta update attempts
 fail because of user cap requirements, all meta updates fail because of
 that user cap requirement. Thus, all registered meta require the same user
 caps.

 This happens because all passed-in meta values are iterated through here:
 https://github.com/WordPress/WordPress/blob/master/wp-includes/rest-
 api/fields/class-wp-rest-meta-fields.php#L135

 And then updated here:
 https://github.com/WordPress/WordPress/blob/master/wp-includes/rest-
 api/fields/class-wp-rest-meta-fields.php#L187-L191

 From Gutenberg, those update calls fire regardless of whether the value is
 being changed. I believe this is because the entire Redux store is passed
 in and iterated over.

 This causes the issue I mentioned in regards to capability checking with
 protected meta. Because you can require a user capability for protected
 meta through the auth_callback when running register_meta, any unrelated
 meta could prevent another unrelated piece of meta from being updated.

 For example, if User A has cap_a, and tries to update _custom_meta_a, but
 _custom_meta_b requires cap_b, that user cannot update _custom_meta_a
 without getting a WP_Error here:

 https://github.com/WordPress/WordPress/blob/master/wp-includes/rest-
 api/fields/class-wp-rest-meta-fields.php#L258

 If we only update meta that has been changed, this should help here.

 **To replicate the problem follow these steps (props @modernnerd):**

 1. Install WP 5.3-RC1 via the WP beta tester plugin by choosing “bleeding
 edge nightlies” at Tools → Beta Testing.
 2. Activate the Twenty Twenty theme (these steps will work with any theme,
 though).
 3. Add this PHP code to the Twenty Twenty theme's functions.php file to
 add custom post meta exposed to the REST API:

 {{{
 function custom_register_post_meta() {
         $args = [
                 'auth_callback' => 'custom_prefix_require_update_plugins',
                 'type'          => 'boolean',
                 'single'        => true,
                 'show_in_rest'  => true,
         ];
         register_meta( 'post', '_custom_post_meta_one', $args );

         $args = [
                 'auth_callback' =>
 'custom_prefix_require_non_existing_cap',
                 'type'          => 'boolean',
                 'single'        => true,
                 'show_in_rest'  => true,
         ];
         register_meta( 'post', '_custom_post_meta_two', $args );

 }
 add_action( 'init', 'custom_register_post_meta' );

 function custom_prefix_require_update_plugins() {
         if ( current_user_can( 'update_plugins' ) ) {
                 return true;
         } else {
                 return false;
         }
 }

 function custom_prefix_require_non_existing_cap() {
         if ( current_user_can( 'this_cap_does_not_exist' ) ) {
                 return true;
         } else {
                 return false;
         }
 }
 }}}


 4. Edit a post or page. Make a change to the post content and click
 “Publish” or “Update” to confirm that changes work as expected.

 5. In the browser console, display the post meta exposed to the REST API
 by pasting this command and typing enter:

 {{{
 wp.data.select( 'core/editor' ).getEditedPostAttribute( 'meta' );
 }}}


 You should see an object that includes your new custom meta:

 {_custom_post_meta_one: false, _custom_post_meta_two: false}

 6. Update _custom_post_meta_one to 'true' with this command (this persists
 the data to the Redux store, but not the database):

 {{{
 wp.data.dispatch( 'core/editor' ).editPost( { meta: {
 _custom_post_meta_one :  true } } );
 }}}


 Note that this is just a simplified test case. It emulates a plugin or
 theme updating meta via the WP API, without having to install a plugin or
 theme that uses custom post meta and Gutenberg.

 7. Click Update in the post editor to save your post meta changes to the
 database.
 You'll see **“Updating failed. Error message: Sorry, you are not allowed
 to edit the _custom_post_meta_two custom field.”.**

 The thing is, _custom_post_meta_two wasn't actually updated or changed by
 the user, yet their lack of permissions for _custom_post_meta_two is
 preventing them from updating _custom_post_meta_one.

 I looked at doing a comparison check prior to saving for the saved value
 vs the new value, but because the saved value is always a string when
 coming from the database, you can't do strict checking, which could be
 problematic. So I am not sure what the fix needs to be here.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/48426>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list