Skip to content

Commit 3fbc7e5

Browse files
committed
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
1 parent da03cf1 commit 3fbc7e5

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

src/wp-admin/includes/admin-filters.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
add_filter( 'heartbeat_received', 'heartbeat_autosave', 500, 2 );
8181

8282
add_filter( 'wp_refresh_nonces', 'wp_refresh_post_nonces', 10, 3 );
83+
add_filter( 'wp_refresh_nonces', 'wp_refresh_metabox_loader_nonces', 10, 2 );
8384
add_filter( 'wp_refresh_nonces', 'wp_refresh_heartbeat_nonces' );
8485

8586
add_filter( 'heartbeat_settings', 'wp_heartbeat_set_suspension' );

src/wp-admin/includes/misc.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,41 @@ function wp_refresh_post_nonces( $response, $data, $screen_id ) {
12551255
return $response;
12561256
}
12571257

1258+
/**
1259+
* Refresh nonces used with meta boxes in the block editor.
1260+
*
1261+
* @since 6.1.0
1262+
*
1263+
* @param array $response The Heartbeat response.
1264+
* @param array $data The $_POST data sent.
1265+
* @return array The Heartbeat response.
1266+
*/
1267+
function wp_refresh_metabox_loader_nonces( $response, $data ) {
1268+
if ( empty( $data['wp-refresh-metabox-loader-nonces'] ) ) {
1269+
return $response;
1270+
}
1271+
1272+
$received = $data['wp-refresh-metabox-loader-nonces'];
1273+
$post_id = (int) $received['post_id'];
1274+
1275+
if ( ! $post_id ) {
1276+
return $response;
1277+
}
1278+
1279+
if ( ! current_user_can( 'edit_post', $post_id ) ) {
1280+
return $response;
1281+
}
1282+
1283+
$response['wp-refresh-metabox-loader-nonces'] = array(
1284+
'replace' => array(
1285+
'metabox_loader_nonce' => wp_create_nonce( 'meta-box-loader' ),
1286+
'_wpnonce' => wp_create_nonce( 'update-post_' . $post_id ),
1287+
),
1288+
);
1289+
1290+
return $response;
1291+
}
1292+
12581293
/**
12591294
* Adds the latest Heartbeat and REST-API nonce to the Heartbeat response.
12601295
*

src/wp-admin/includes/post.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2334,6 +2334,50 @@ function the_block_editor_meta_boxes() {
23342334
wp_add_inline_script( 'wp-lists', $script );
23352335
}
23362336

2337+
/*
2338+
* Refresh nonces used by the meta box loader.
2339+
*
2340+
* The logic is very similar to that provided by post.js for the classic editor.
2341+
*/
2342+
$script = "( function( $ ) {
2343+
var check, timeout;
2344+
2345+
function schedule() {
2346+
check = false;
2347+
window.clearTimeout( timeout );
2348+
timeout = window.setTimeout( function() { check = true; }, 300000 );
2349+
}
2350+
2351+
$( document ).on( 'heartbeat-send.wp-refresh-nonces', function( e, data ) {
2352+
var post_id, \$authCheck = $( '#wp-auth-check-wrap' );
2353+
2354+
if ( check || ( \$authCheck.length && ! \$authCheck.hasClass( 'hidden' ) ) ) {
2355+
if ( ( post_id = $( '#post_ID' ).val() ) && $( '#_wpnonce' ).val() ) {
2356+
data['wp-refresh-metabox-loader-nonces'] = {
2357+
post_id: post_id
2358+
};
2359+
}
2360+
}
2361+
}).on( 'heartbeat-tick.wp-refresh-nonces', function( e, data ) {
2362+
var nonces = data['wp-refresh-metabox-loader-nonces'];
2363+
2364+
if ( nonces ) {
2365+
if ( nonces.replace ) {
2366+
if ( nonces.replace.metabox_loader_nonce && window._wpMetaBoxUrl && wp.url ) {
2367+
window._wpMetaBoxUrl= wp.url.addQueryArgs( window._wpMetaBoxUrl, { 'meta-box-loader-nonce': nonces.replace.metabox_loader_nonce } );
2368+
}
2369+
2370+
if ( nonces.replace._wpnonce ) {
2371+
$( '#_wpnonce' ).val( nonces.replace._wpnonce );
2372+
}
2373+
}
2374+
}
2375+
}).ready( function() {
2376+
schedule();
2377+
});
2378+
} )( jQuery );";
2379+
wp_add_inline_script( 'heartbeat', $script );
2380+
23372381
// Reset meta box data.
23382382
$wp_meta_boxes = $_original_meta_boxes;
23392383
}

tests/phpunit/tests/admin/includesPost.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,4 +1016,42 @@ public function test_post_exists_should_not_match_invalid_post_type_and_status_c
10161016
$this->assertSame( 0, post_exists( $title, null, null, $post_type, 'draft' ) );
10171017
$this->assertSame( 0, post_exists( $title, null, null, 'wp_tests', $post_status ) );
10181018
}
1019+
1020+
/**
1021+
* Test refreshed nonce for metabox loader.
1022+
*
1023+
* @return void
1024+
*/
1025+
public function test_user_get_refreshed_metabox_nonce() {
1026+
1027+
// Create a post by the current user.
1028+
wp_set_current_user( self::$editor_id );
1029+
1030+
$post_data = array(
1031+
'post_content' => 'Test post content',
1032+
'post_title' => 'Test post title',
1033+
'post_excerpt' => 'Test post excerpt',
1034+
'post_author' => self::$editor_id,
1035+
'post_status' => 'draft',
1036+
);
1037+
$post_id = wp_insert_post( $post_data );
1038+
1039+
// Simulate the $_POST data from the heartbeat.
1040+
$data = array(
1041+
'wp-refresh-metabox-loader-nonces' => array(
1042+
'post_id' => (string) $post_id,
1043+
),
1044+
'wp-refresh-post-lock' => array(
1045+
'lock' => '1658203298:1',
1046+
'post_id' => (string) $post_id,
1047+
),
1048+
);
1049+
1050+
// Call the function we're testing.
1051+
$response = wp_refresh_metabox_loader_nonces( array(), $data );
1052+
1053+
// Ensure that both nonces were created.
1054+
$this->assertNotEmpty( $response['wp-refresh-metabox-loader-nonces']['replace']['_wpnonce'] );
1055+
$this->assertNotEmpty( $response['wp-refresh-metabox-loader-nonces']['replace']['metabox_loader_nonce'] );
1056+
}
10191057
}

0 commit comments

Comments
 (0)