Editor: Refresh nones for metaboxes after reauthentication.

This fixes an issue where metaboxes fail to save after a session expires and a user logs in again via the heartbeat API.

Props LinSoftware.
Fixes #52584.


git-svn-id: https://develop.svn.wordpress.org/trunk@54122 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Joe McGill 2022-09-11 20:44:50 +00:00
parent da03cf1c6b
commit 3fbc7e5aea
4 changed files with 118 additions and 0 deletions

View File

@ -80,6 +80,7 @@ add_filter( 'heartbeat_received', 'wp_refresh_post_lock', 10, 3 );
add_filter( 'heartbeat_received', 'heartbeat_autosave', 500, 2 );
add_filter( 'wp_refresh_nonces', 'wp_refresh_post_nonces', 10, 3 );
add_filter( 'wp_refresh_nonces', 'wp_refresh_metabox_loader_nonces', 10, 2 );
add_filter( 'wp_refresh_nonces', 'wp_refresh_heartbeat_nonces' );
add_filter( 'heartbeat_settings', 'wp_heartbeat_set_suspension' );

View File

@ -1255,6 +1255,41 @@ function wp_refresh_post_nonces( $response, $data, $screen_id ) {
return $response;
}
/**
* Refresh nonces used with meta boxes in the block editor.
*
* @since 6.1.0
*
* @param array $response The Heartbeat response.
* @param array $data The $_POST data sent.
* @return array The Heartbeat response.
*/
function wp_refresh_metabox_loader_nonces( $response, $data ) {
if ( empty( $data['wp-refresh-metabox-loader-nonces'] ) ) {
return $response;
}
$received = $data['wp-refresh-metabox-loader-nonces'];
$post_id = (int) $received['post_id'];
if ( ! $post_id ) {
return $response;
}
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $response;
}
$response['wp-refresh-metabox-loader-nonces'] = array(
'replace' => array(
'metabox_loader_nonce' => wp_create_nonce( 'meta-box-loader' ),
'_wpnonce' => wp_create_nonce( 'update-post_' . $post_id ),
),
);
return $response;
}
/**
* Adds the latest Heartbeat and REST-API nonce to the Heartbeat response.
*

View File

@ -2334,6 +2334,50 @@ function the_block_editor_meta_boxes() {
wp_add_inline_script( 'wp-lists', $script );
}
/*
* Refresh nonces used by the meta box loader.
*
* The logic is very similar to that provided by post.js for the classic editor.
*/
$script = "( function( $ ) {
var check, timeout;
function schedule() {
check = false;
window.clearTimeout( timeout );
timeout = window.setTimeout( function() { check = true; }, 300000 );
}
$( document ).on( 'heartbeat-send.wp-refresh-nonces', function( e, data ) {
var post_id, \$authCheck = $( '#wp-auth-check-wrap' );
if ( check || ( \$authCheck.length && ! \$authCheck.hasClass( 'hidden' ) ) ) {
if ( ( post_id = $( '#post_ID' ).val() ) && $( '#_wpnonce' ).val() ) {
data['wp-refresh-metabox-loader-nonces'] = {
post_id: post_id
};
}
}
}).on( 'heartbeat-tick.wp-refresh-nonces', function( e, data ) {
var nonces = data['wp-refresh-metabox-loader-nonces'];
if ( nonces ) {
if ( nonces.replace ) {
if ( nonces.replace.metabox_loader_nonce && window._wpMetaBoxUrl && wp.url ) {
window._wpMetaBoxUrl= wp.url.addQueryArgs( window._wpMetaBoxUrl, { 'meta-box-loader-nonce': nonces.replace.metabox_loader_nonce } );
}
if ( nonces.replace._wpnonce ) {
$( '#_wpnonce' ).val( nonces.replace._wpnonce );
}
}
}
}).ready( function() {
schedule();
});
} )( jQuery );";
wp_add_inline_script( 'heartbeat', $script );
// Reset meta box data.
$wp_meta_boxes = $_original_meta_boxes;
}

View File

@ -1016,4 +1016,42 @@ class Tests_Admin_IncludesPost extends WP_UnitTestCase {
$this->assertSame( 0, post_exists( $title, null, null, $post_type, 'draft' ) );
$this->assertSame( 0, post_exists( $title, null, null, 'wp_tests', $post_status ) );
}
/**
* Test refreshed nonce for metabox loader.
*
* @return void
*/
public function test_user_get_refreshed_metabox_nonce() {
// Create a post by the current user.
wp_set_current_user( self::$editor_id );
$post_data = array(
'post_content' => 'Test post content',
'post_title' => 'Test post title',
'post_excerpt' => 'Test post excerpt',
'post_author' => self::$editor_id,
'post_status' => 'draft',
);
$post_id = wp_insert_post( $post_data );
// Simulate the $_POST data from the heartbeat.
$data = array(
'wp-refresh-metabox-loader-nonces' => array(
'post_id' => (string) $post_id,
),
'wp-refresh-post-lock' => array(
'lock' => '1658203298:1',
'post_id' => (string) $post_id,
),
);
// Call the function we're testing.
$response = wp_refresh_metabox_loader_nonces( array(), $data );
// Ensure that both nonces were created.
$this->assertNotEmpty( $response['wp-refresh-metabox-loader-nonces']['replace']['_wpnonce'] );
$this->assertNotEmpty( $response['wp-refresh-metabox-loader-nonces']['replace']['metabox_loader_nonce'] );
}
}