[wp-trac] [WordPress Trac] #55659: User without post lock can overwrite changes of user with lock via autosave

WordPress Trac noreply at wordpress.org
Mon Jul 18 22:22:46 UTC 2022


#55659: User without post lock can overwrite changes of user with lock via autosave
--------------------------------------+------------------------------
 Reporter:  jhart35                   |       Owner:  adamsilverstein
     Type:  defect (bug)              |      Status:  assigned
 Priority:  normal                    |   Milestone:  6.1
Component:  Autosave                  |     Version:  5.9.3
 Severity:  normal                    |  Resolution:
 Keywords:  has-patch has-unit-tests  |     Focuses:  rest-api
--------------------------------------+------------------------------

Comment (by primetimejas):

 I was able to replicate the issue and verify that the fix works. The PR
 was created to add onto what @sathyapulse contributed. I the meantime we
 are using a fix like this:

 {{{#!php
 <?php
 /**
  * Fix autosave updates issue.
  *
  * @see https://core.trac.wordpress.org/ticket/55659
  *
  *
  * @param WP_REST_Response|WP_HTTP_Response|WP_Error|mixed $response
 Result to send to the client.
  *
 Usually a WP_REST_Response or WP_Error.
  * @param array                                            $handler  Route
 handler used for the request.
  * @param WP_REST_Request                                  $request
 Request used to generate the response.
  *
  * @return mixed|\WP_Error
  */
 function fix_autosave_post_updates( $response, $handler, $request ) {

         // Check for the response ID.
         if ( empty( $request['id'] ) ) {
                 return $response;
         }

         // Ensure we have a valid post.
         $post = get_post( $request['id'] );
         if ( is_wp_error( $post ) ) {
                         return $response;
         }

         // Check that we are in the correct context.
         if ( 'POST' !== $request->get_method() ) {
                         return $response;
         }

         // Ensure this request is coming from the autosaves route.
         $autosave_route = '/wp/v2/' . get_post_type( $post ) . '/' .
 $post->ID . '/autosaves';
         if ( $autosave_route !== $request->get_route() ) {
                 return $response;
         }

         // The wp_check_post_lock function does not exist until we include
 it.
         if ( ! function_exists( 'wp_check_post_lock' ) ) {
                         require_once( ABSPATH . 'wp-
 admin/includes/post.php' );
         }

         $user_id = get_current_user_id();

         /**
          * If this is draft, the post author is the current user and the
 post is locked then return an error, stopping autosave.
          * Note: Only the original author can autosave, this is defined in
 class-wp-rest-autosaves.controller.php
          *
          * wp_check_post_lock() will return false if the post is locked to
 the current user, so if it is locked to the current user we can continue
 with autosaving.
          *
          * So in a scenario where the post has been taken over by another
 user "User B" but the original author left their browser tab open:
          *      wp_check_post_lock() would return false for "User B" that
 has taken over the post since the post is not locked for them.
          *      wp_check_post_lock() would return the user ID of "User B"
 for the original author since the post is locked to "User B".
          *
          * Our issue happens because core does not check post lock and the
 original author's browser tab initiates an autosave, overwriting changes
 from "User B".
         */
         if ( ( 'draft' === $post->post_status || 'auto-draft' ===
 $post->post_status ) && (int) $post->post_author === (int) $user_id &&
 false !== wp_check_post_lock( $post->ID ) ) {
                         return new WP_Error(
                                         'rest_forbidden',
                                         'Sorry, you are not allowed to
 update the post with autosave since it is locked by another user.',
                                         array( 'status' => 400 )
                         );
         }

         return $response;
 }
 add_filter( 'rest_request_before_callbacks', 'fix_autosave_post_updates',
 10, 3 );

 }}}

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


More information about the wp-trac mailing list