diff --git a/wp-admin/includes/ajax-actions.php b/wp-admin/includes/ajax-actions.php index 1a52e3e0fb..6d2f3e650f 100644 --- a/wp-admin/includes/ajax-actions.php +++ b/wp-admin/includes/ajax-actions.php @@ -4344,7 +4344,7 @@ function wp_ajax_wp_privacy_export_personal_data() { wp_send_json_error( __( 'Invalid request ID.' ) ); } - if ( ! current_user_can( 'manage_options' ) ) { + if ( ! current_user_can( 'export_others_personal_data' ) ) { wp_send_json_error( __( 'Invalid request.' ) ); } @@ -4522,7 +4522,8 @@ function wp_ajax_wp_privacy_erase_personal_data() { wp_send_json_error( __( 'Invalid request ID.' ) ); } - if ( ! current_user_can( 'delete_users' ) ) { + // Both capabilities are required to avoid confusion, see `_wp_personal_data_removal_page()`. + if ( ! current_user_can( 'erase_others_personal_data' ) || ! current_user_can( 'delete_users' ) ) { wp_send_json_error( __( 'Invalid request.' ) ); } diff --git a/wp-admin/includes/user.php b/wp-admin/includes/user.php index e242322e35..939ad167bd 100644 --- a/wp-admin/includes/user.php +++ b/wp-admin/includes/user.php @@ -785,8 +785,8 @@ function _wp_personal_data_cleanup_requests() { * @access private */ function _wp_personal_data_export_page() { - if ( ! current_user_can( 'manage_options' ) ) { - wp_die( esc_html__( 'Sorry, you are not allowed to manage privacy on this site.' ) ); + if ( ! current_user_can( 'export_others_personal_data' ) ) { + wp_die( __( 'Sorry, you are not allowed to export personal data on this site.' ) ); } _wp_personal_data_handle_actions(); @@ -850,8 +850,14 @@ function _wp_personal_data_export_page() { * @access private */ function _wp_personal_data_removal_page() { - if ( ! current_user_can( 'delete_users' ) ) { - wp_die( esc_html__( 'Sorry, you are not allowed to manage privacy on this site.' ) ); + /* + * Require both caps in order to make it explicitly clear that delegating + * erasure from network admins to single-site admins will give them the + * ability to affect global users, rather than being limited to the site + * that they administer. + */ + if ( ! current_user_can( 'erase_others_personal_data' ) || ! current_user_can( 'delete_users' ) ) { + wp_die( __( 'Sorry, you are not allowed to erase data on this site.' ) ); } _wp_personal_data_handle_actions(); @@ -917,8 +923,8 @@ function _wp_personal_data_removal_page() { * @access private */ function _wp_privacy_hook_requests_page() { - add_submenu_page( 'tools.php', __( 'Export Personal Data' ), __( 'Export Personal Data' ), 'manage_options', 'export_personal_data', '_wp_personal_data_export_page' ); - add_submenu_page( 'tools.php', __( 'Remove Personal Data' ), __( 'Remove Personal Data' ), 'manage_options', 'remove_personal_data', '_wp_personal_data_removal_page' ); + add_submenu_page( 'tools.php', __( 'Export Personal Data' ), __( 'Export Personal Data' ), 'export_others_personal_data', 'export_personal_data', '_wp_personal_data_export_page' ); + add_submenu_page( 'tools.php', __( 'Remove Personal Data' ), __( 'Remove Personal Data' ), 'erase_others_personal_data', 'remove_personal_data', '_wp_personal_data_removal_page' ); } // TODO: move the following classes in new files. diff --git a/wp-includes/capabilities.php b/wp-includes/capabilities.php index a81761db15..efc3dd2e4c 100644 --- a/wp-includes/capabilities.php +++ b/wp-includes/capabilities.php @@ -555,6 +555,10 @@ function map_meta_cap( $cap, $user_id ) { $caps[] = 'update_core'; } break; + case 'export_others_personal_data': + case 'erase_others_personal_data': + $caps[] = is_multisite() ? 'manage_network' : 'manage_options'; + break; default: // Handle meta capabilities for custom post types. global $post_type_meta_caps; diff --git a/wp-includes/version.php b/wp-includes/version.php index 4f1981c2f1..fd4a4a4f38 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -4,7 +4,7 @@ * * @global string $wp_version */ -$wp_version = '5.0-alpha-43081'; +$wp_version = '5.0-alpha-43085'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.