Skip to content

Commit 68f7673

Browse files
Merge branch 'trunk' into skip-page-builder-dip
2 parents d43e835 + cb8e9db commit 68f7673

File tree

3 files changed

+109
-8
lines changed

3 files changed

+109
-8
lines changed

src/wp-includes/collaboration/class-wp-http-polling-sync-server.php

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,25 @@ public function check_permissions( WP_REST_Request $request ) {
181181
);
182182
}
183183

184-
$rooms = $request['rooms'];
184+
$rooms = $request['rooms'];
185+
$wp_user_id = get_current_user_id();
185186

186187
foreach ( $rooms as $room ) {
187-
$room = $room['room'];
188+
$client_id = $room['client_id'];
189+
$room = $room['room'];
190+
191+
// Check that the client_id is not already owned by another user.
192+
$existing_awareness = $this->storage->get_awareness_state( $room );
193+
foreach ( $existing_awareness as $entry ) {
194+
if ( $client_id === $entry['client_id'] && $wp_user_id !== $entry['wp_user_id'] ) {
195+
return new WP_Error(
196+
'rest_cannot_edit',
197+
__( 'Client ID is already in use by another user.' ),
198+
array( 'status' => rest_authorization_required_code() )
199+
);
200+
}
201+
}
202+
188203
$type_parts = explode( '/', $room, 2 );
189204
$object_parts = explode( ':', $type_parts[1] ?? '', 2 );
190205

@@ -346,6 +361,7 @@ private function process_awareness_update( string $room, int $client_id, ?array
346361
'client_id' => $client_id,
347362
'state' => $awareness_update,
348363
'updated_at' => $current_time,
364+
'wp_user_id' => get_current_user_id(),
349365
);
350366
}
351367

@@ -407,7 +423,10 @@ private function process_sync_update( string $room, int $client_id, int $cursor,
407423

408424
return $this->add_update( $room, $client_id, $type, $data );
409425
}
410-
break;
426+
427+
// Reaching this point means there's a newer compaction, so we can
428+
// silently ignore this one.
429+
return true;
411430

412431
case self::UPDATE_TYPE_SYNC_STEP1:
413432
case self::UPDATE_TYPE_SYNC_STEP2:

src/wp-includes/css/buttons.css

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,8 @@ TABLE OF CONTENTS:
208208
.wp-core-ui .button-secondary:disabled,
209209
.wp-core-ui .button-secondary.disabled,
210210
.wp-core-ui .button-disabled {
211-
color: #949494 !important;
212-
border-color: #dddddd !important;
211+
color: #8a8a8a !important;
212+
border-color: #d8d8d8 !important;
213213
background: transparent !important;
214214
box-shadow: none !important;
215215
cursor: default;
@@ -312,9 +312,9 @@ TABLE OF CONTENTS:
312312
.wp-core-ui .button-primary:disabled,
313313
.wp-core-ui .button-primary-disabled,
314314
.wp-core-ui .button-primary.disabled {
315-
color: #949494 !important;
316-
background: #f0f0f0 !important;
317-
border-color: #f0f0f0 !important;
315+
color: #8a8a8a !important;
316+
background: #e2e2e2 !important;
317+
border-color: #e2e2e2 !important;
318318
box-shadow: none !important;
319319
text-shadow: none !important;
320320
cursor: default;

tests/phpunit/tests/rest-api/rest-sync-server.php

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,63 @@ public function test_sync_should_compact_is_false_for_non_compactor() {
623623
$this->assertFalse( $data['rooms'][0]['should_compact'] );
624624
}
625625

626+
public function test_sync_stale_compaction_succeeds_when_newer_compaction_exists() {
627+
wp_set_current_user( self::$editor_id );
628+
629+
$room = $this->get_post_room();
630+
$update = array(
631+
'type' => 'update',
632+
'data' => 'dGVzdA==',
633+
);
634+
635+
// Client 1 sends an update to seed the room.
636+
$response = $this->dispatch_sync(
637+
array(
638+
$this->build_room( $room, 1, 0, array( 'user' => 'c1' ), array( $update ) ),
639+
)
640+
);
641+
642+
$end_cursor = $response->get_data()['rooms'][0]['end_cursor'];
643+
644+
// Client 2 sends a compaction at the current cursor.
645+
$compaction = array(
646+
'type' => 'compaction',
647+
'data' => 'Y29tcGFjdGVk',
648+
);
649+
650+
$this->dispatch_sync(
651+
array(
652+
$this->build_room( $room, 2, $end_cursor, array( 'user' => 'c2' ), array( $compaction ) ),
653+
)
654+
);
655+
656+
// Client 3 sends a stale compaction at cursor 0. The server should find
657+
// client 2's compaction in the updates after cursor 0 and silently discard
658+
// this one.
659+
$stale_compaction = array(
660+
'type' => 'compaction',
661+
'data' => 'c3RhbGU=',
662+
);
663+
$response = $this->dispatch_sync(
664+
array(
665+
$this->build_room( $room, 3, 0, array( 'user' => 'c3' ), array( $stale_compaction ) ),
666+
)
667+
);
668+
669+
$this->assertSame( 200, $response->get_status() );
670+
671+
// Verify the newer compaction is preserved and the stale one was not stored.
672+
$response = $this->dispatch_sync(
673+
array(
674+
$this->build_room( $room, 4, 0, array( 'user' => 'c4' ) ),
675+
)
676+
);
677+
$update_data = wp_list_pluck( $response->get_data()['rooms'][0]['updates'], 'data' );
678+
679+
$this->assertContains( 'Y29tcGFjdGVk', $update_data, 'The newer compaction should be preserved.' );
680+
$this->assertNotContains( 'c3RhbGU=', $update_data, 'The stale compaction should not be stored.' );
681+
}
682+
626683
/*
627684
* Awareness tests.
628685
*/
@@ -697,6 +754,31 @@ public function test_sync_awareness_updates_existing_client() {
697754
$this->assertSame( array( 'cursor' => 'updated' ), $awareness[1] );
698755
}
699756

757+
public function test_sync_awareness_client_id_cannot_be_used_by_another_user() {
758+
wp_set_current_user( self::$editor_id );
759+
760+
$room = $this->get_post_room();
761+
762+
// Editor establishes awareness with client_id 1.
763+
$this->dispatch_sync(
764+
array(
765+
$this->build_room( $room, 1, 0, array( 'name' => 'Editor' ) ),
766+
)
767+
);
768+
769+
// A different user tries to use the same client_id.
770+
$editor_id_2 = self::factory()->user->create( array( 'role' => 'editor' ) );
771+
wp_set_current_user( $editor_id_2 );
772+
773+
$response = $this->dispatch_sync(
774+
array(
775+
$this->build_room( $room, 1, 0, array( 'name' => 'Impostor' ) ),
776+
)
777+
);
778+
779+
$this->assertErrorResponse( 'rest_cannot_edit', $response, 403 );
780+
}
781+
700782
/*
701783
* Multiple rooms tests.
702784
*/

0 commit comments

Comments
 (0)