Repository navigation
Native Users window: profile settings plugins add through core's profile hooks are missing #1020
Description
Summary
With the native Users window turned on (Preferences, Features, nativeUsersEnabled), the profile in OpenStation leaves out everything plugins add to the profile screen through core's hooks:
show_user_profile/edit_user_profile: sections after Application Passwords;personal_options: rows inside the Personal Options table;profile_personal_options: the block right after that table, on your own profile.
Their save hooks, personal_options_update and edit_user_profile_update, never run either. This affects any plugin that adds profile settings this way, for example sign-in security options, author fields or per-user preferences. There is no way to view or change those settings from inside OpenStation. The same profile in classic admin shows them.
The User Edit window and the Users window's Profile tab both render <os-user-profile>, which loads and saves the core fields through wp/v2/users/<id>.
With the native Users window turned off (the default), profile.php opens in an iframe window and everything works.
Environment
- WordPress 7.1.3, PHP 8.3
- OpenStation 1.1.15 (trunk at the v1.1.15 tag)
- Chromium-based browser
- Local site run with WordPress Playground CLI 3.1.58 (Docker was not available for wp-env on this machine)
Steps to reproduce
- Add this mu-plugin. It uses only core hooks:
<?php
add_action( 'show_user_profile', 'repro_profile_field' );
add_action( 'edit_user_profile', 'repro_profile_field' );
function repro_profile_field( $user ) {
echo '<h2>Repro section</h2><table class="form-table"><tr><th><label for="repro_field">Repro field</label></th><td><input type="text" name="repro_field" id="repro_field" value="' . esc_attr( get_user_meta( $user->ID, 'repro_field', true ) ) . '" /></td></tr></table>';
}
add_action( 'personal_options', function ( $user ) {
echo '<tr><th><label for="repro_row">Repro row</label></th><td><input type="text" name="repro_row" id="repro_row" value="' . esc_attr( get_user_meta( $user->ID, 'repro_row', true ) ) . '" /></td></tr>';
} );
add_action( 'profile_personal_options', function () {
echo '<h2>Repro block</h2><p>Printed on profile_personal_options.</p>';
} );
add_action( 'personal_options_update', 'repro_profile_field_save' );
add_action( 'edit_user_profile_update', 'repro_profile_field_save' );
function repro_profile_field_save( $user_id ) {
if ( ! current_user_can( 'edit_user', $user_id ) ) {
return;
}
foreach ( array( 'repro_field', 'repro_row' ) as $key ) {
if ( isset( $_POST[ $key ] ) ) {
update_user_meta( $user_id, $key, sanitize_text_field( wp_unslash( $_POST[ $key ] ) ) );
}
}
}- Open OpenStation and turn on the native Users window in Preferences, Features.
- Open Profile from the dock (Users, Profile), or load
/wp-admin/profile.phpdirectly.
Expected
The profile shows "Repro row", "Repro block" and "Repro section", and saving them works, as on the classic profile.php.
Actual
The native Edit user window (and the Users window's Profile tab) shows only the core fields. None of the three is present. Loading /wp-admin/profile.php directly opens the same native window. Editing another user in the native window is affected the same way (edit_user_profile).
What I checked
| Case | Result |
|---|---|
Classic admin (profile.php?desktop_mode_classic=1) |
All plugin output renders; saving persists |
| OpenStation, native Users off, Profile from the dock | profile.php in an iframe window; all plugin output renders; saving persists |
OpenStation, native Users off, /wp-admin/profile.php directly |
Same as above |
| OpenStation, native Users on, Profile from the dock | Native Edit user window; no plugin output |
OpenStation, native Users on, /wp-admin/profile.php directly |
Native Edit user window; no plugin output |
I also checked a plugin section that sends the user through wp-login.php to re-authenticate and back to profile.php#anchor before its options can be changed. That round trip works in classic admin and in an iframe window. In the native window it cannot be reached because the section is not there.
Returning false from openstation_user_edit_window_user_can_register does not bring the classic screen back for profile.php: the Users window still claims profile.php through its Profile tab, which renders the same element.
I did not find a security impact. The native form only saves core fields through core's REST controller, and a plugin's own checks still apply to its settings.
Cause
apps/users/profile/ (<os-user-profile>) builds a fixed form and saves through PUT wp/v2/users/<id> (apps/users/profile/client.ts). None of show_user_profile, edit_user_profile, personal_options, profile_personal_options, personal_options_update or edit_user_profile_update is called anywhere in OpenStation. The plugins' output also depends on scripts they enqueue for profile.php and on core's form post, so it cannot be rebuilt from REST data.
Activity
[-]Native Users window: profile sections added by other plugins (show_user_profile / edit_user_profile) are missing[/-][+]Native Users window: profile settings plugins add through core's profile hooks are missing[/+]