From cad2f8cff97dbc7b592d0e9dd0e6a4d371be73e4 Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Sun, 2 Mar 2025 23:33:56 +0000 Subject: [PATCH] Users: Use `editable_roles` filter for multisite sub-sites. Adds a check of the `editable_roles` filter when adding users to a multisite sub-site to ensure the role is permitted to be used on the network. If the role is blocked by the filter, attempting to add the role will trigger a `wp_die()` similar to attempting to add a user with the role on a single site install. Props eartboard, hareesh-pillai, ideag, sukhendu2002, spacedmonkey, thomaswm. Fixes #43251. git-svn-id: https://develop.svn.wordpress.org/trunk@59901 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-admin/includes/ms.php | 14 ++++++ src/wp-admin/user-new.php | 5 ++ .../multisite/wpmuValidateUserSignup.php | 48 +++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/src/wp-admin/includes/ms.php b/src/wp-admin/includes/ms.php index 6814d1198e..fc5f54a7f4 100644 --- a/src/wp-admin/includes/ms.php +++ b/src/wp-admin/includes/ms.php @@ -1172,3 +1172,17 @@ function get_site_screen_help_sidebar_content() { '

' . __( 'Documentation on Site Management' ) . '

' . '

' . __( 'Support forums' ) . '

'; } + +/** + * Stop execution if the role can not be assigned by the current user. + * + * @since 6.8.0 + * + * @param string $role Role the user is attempting to assign. + */ +function wp_ensure_editable_role( $role ) { + $roles = get_editable_roles(); + if ( ! isset( $roles[ $role ] ) ) { + wp_die( __( 'Sorry, you are not allowed to give users that role.' ), 403 ); + } +} diff --git a/src/wp-admin/user-new.php b/src/wp-admin/user-new.php index aed07ff1c3..cdc1dfef1e 100644 --- a/src/wp-admin/user-new.php +++ b/src/wp-admin/user-new.php @@ -69,6 +69,9 @@ if ( isset( $_REQUEST['action'] ) && 'adduser' === $_REQUEST['action'] ) { $redirect = add_query_arg( array( 'update' => 'addexisting' ), 'user-new.php' ); } else { if ( isset( $_POST['noconfirmation'] ) && current_user_can( 'manage_network_users' ) ) { + + wp_ensure_editable_role( $_REQUEST['role'] ); + $result = add_existing_user_to_blog( array( 'user_id' => $user_id, @@ -225,6 +228,8 @@ Please click the following link to confirm the invite: add_filter( 'wpmu_welcome_user_notification', '__return_false' ); // Disable welcome email. } + wp_ensure_editable_role( $_REQUEST['role'] ); + wpmu_signup_user( $new_user_login, $new_user_email, diff --git a/tests/phpunit/tests/multisite/wpmuValidateUserSignup.php b/tests/phpunit/tests/multisite/wpmuValidateUserSignup.php index f88ed0ff78..a3409a54a8 100644 --- a/tests/phpunit/tests/multisite/wpmuValidateUserSignup.php +++ b/tests/phpunit/tests/multisite/wpmuValidateUserSignup.php @@ -220,6 +220,54 @@ if ( is_multisite() ) : $this->assertContains( 'invalid_nonce', $valid['errors']->get_error_codes() ); } + + /** + * Ensure that wp_ensure_editable_role does not throw an exception when the role is editable. + * + * @ticket 43251 + * + * @covers ::wp_ensure_editable_role + */ + public function test_wp_ensure_editable_role_allows_editable_roles() { + $role = get_role( 'editor' ); + $this->assertInstanceOf( 'WP_Role', $role, 'The editor role should exist.' ); + $this->assertNull( wp_ensure_editable_role( 'editor' ), 'The editor role should be editable.' ); + } + + /** + * Ensure that wp_ensure_editable_role throws an exception for non-existent roles. + * + * @ticket 43251 + * + * @covers ::wp_ensure_editable_role + */ + public function test_wp_ensure_editable_role_does_not_allow_non_existent_role() { + $this->expectException( 'WPDieException' ); + $role = get_role( 'non-existent-role' ); + $this->assertNotInstanceOf( 'WP_Role', $role, 'The non-existent-role role should not exist.' ); + wp_ensure_editable_role( 'non-existent-role' ); + } + + /** + * Ensure that wp_ensure_editable_role throws an exception for roles that are not editable. + * + * @ticket 43251 + * + * @covers ::wp_ensure_editable_role + */ + public function test_wp_ensure_editable_role_does_not_allow_uneditable_roles() { + add_filter( + 'editable_roles', + function ( $roles ) { + unset( $roles['editor'] ); + return $roles; + } + ); + $this->expectException( 'WPDieException' ); + $role = get_role( 'editor' ); + $this->assertInstanceOf( 'WP_Role', $role, 'The editor role should exist.' ); + wp_ensure_editable_role( 'editor' ); + } } endif;