[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