Make WordPress Core

Opened 4 years ago

Last modified 2 years ago

#50754 new defect (bug)

REST updating a post without author support updates the author to the current user

Reported by: jadpm's profile jadpm Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 5.0
Component: Editor Keywords:
Focuses: rest-api Cc:


When updaing a post using the REST API, if the post belongs to a post type that does not support post author, then the database entry for the post gets updated and the current user is set as author.

Steps to reproduce, using the Blocks editor as REST API cover:

  • Register a post type and make sure you do not declare support for post author.
  • Create a new post for that type using the blocks editor, and notice that the databse entry for it sets the author to be the current user.
  • Switch to another user with proper editing capabilities, and edit the post again also using the post editor.
  • Upong saving, confirm that the database entry for the post states that th author is this second user.

This does not happen when updating a post manually using the legacy classic editor: in this case, the author set when first creating the post is respected on following edits.

Although this might be considered a minor thing (the post type should not be supporting author logic, right?), the implications reach deeper. Users set as the post author in the database get notifications on new comments, for eample, despite the author support for their post type. Having them modified inconsistently based on the editor used to adjust the content copy introduces a major editorial flow nightmare in sites maintained by multiple users.

Probably related: #47041

Change History (7)

#2 @jadpm
4 years ago

Some more information after debugging this slightly.

It is not enough to preserve the author when collecting the data that the REST API gets posted when saving a post. That would mostly keep the post author, but not in all cases.

Given the nature of the legacy metaboxes support, after REST saving a post with the (blocks) editor, an AJAX call is fired as to save metabox data, pretending to fire a POST request against the edit.php page, hence firing again an wp_update_post. Following the legacy editor logic, in that request we do not include post author data because there is no author selector, hence the current user ID is set.

This triggers some extra and probably interesting questions: why are we saving the entire post once form the REST API and then again when saving the legacy metabox data? May this introduce some other glitches who manifest in a number of other tickets related to wrong author being set, for example?

To the topic in this ticket, as I said above, a summary: preserving the current post author when saving a post with no declared support for this field is not enough if the post editor contains a legacy metabox.

Version 1, edited 4 years ago by jadpm (previous) (next) (diff)

#3 @TimothyBlynJacobs
4 years ago

  • Component changed from REST API to Editor
  • Focuses rest-api added
  • Version changed from 5.5 to 5.0

Digging into this a bit. In `wp_insert_post()` if the post author is not set, it is set to the current user.

The Classic Editor doesn't run into this issue because the post_author is always populated, even if the current post type does not support title.. And edit_post() through _wp_translate_post_data() looks for post_author_override.

But it looks like the REST API doesn't run into this either. When updating an item, it uses wp_update_post which merges the currently saved post with the given updates. A unit test demonstrating this:

public function test_updating_post_does_not_change_author() {
        $post = self::factory()->post->create( array( 'post_author' => self::$author_id ) );

        wp_set_current_user( self::$editor_id );
        $request = new WP_REST_Request( 'PUT', '/wp/v2/posts/' . $post );
        $request->set_body_params( array( 'title' => 'My New Title' ) );
        $response = rest_do_request( $request );

        $this->assertEquals( self::$author_id, $response->get_data()['author'] );
        $this->assertEquals( self::$author_id, get_post( $post )->post_author );

It looks like indeed this is because of the classic metabox saving. Specifically Gutenberg only adds the post_author field if the current post has an author. If the current post type doesn't support an author, then it won't be included in the initial REST API response and thus won't be included in the update to edit.php.

I think this can be fixed by adding the post_author field to the_block_editor_meta_box_post_form_hidden_fields() which has its form data merged with the metabox update.

#4 @TimothyBlynJacobs
4 years ago

#49269 was marked as a duplicate.

#5 @TimothyBlynJacobs
4 years ago

#51790 was marked as a duplicate.

#6 @SergeyBiryukov
4 years ago

#51480 was marked as a duplicate.

This ticket was mentioned in Slack in #meta-wordcamp by iandunn. View the logs.

2 years ago

Note: See TracTickets for help on using tickets.