Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Global Styles: allow read access to users with edit_posts capabilities #7336

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/wp-includes/post.php
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ function create_initial_post_types() {
'revisions_rest_controller_class' => 'WP_REST_Global_Styles_Revisions_Controller',
'late_route_registration' => true,
'capabilities' => array(
'read' => 'edit_theme_options',
'read' => 'edit_posts',
'create_posts' => 'edit_theme_options',
'edit_posts' => 'edit_theme_options',
'edit_published_posts' => 'edit_theme_options',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -509,26 +509,40 @@ public function get_item_schema() {
* Checks if a given request has access to read a single theme global styles config.
*
* @since 5.9.0
* @since 6.7.0 Allow users with edit post capabilities to view theme global styles.
*
* @param WP_REST_Request $request Full details about the request.
* @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise.
*/
public function get_theme_item_permissions_check( $request ) {
/*
* Verify if the current user has edit_posts capability.
* This capability is required to view global styles.
*/
if ( current_user_can( 'edit_posts' ) ) {
return true;
}

foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) {
if ( current_user_can( $post_type->cap->edit_posts ) ) {
return true;
}
}

/*
* Verify if the current user has edit_theme_options capability.
* This capability is required to edit/view/delete global styles.
*/
if ( ! current_user_can( 'edit_theme_options' ) ) {
return new WP_Error(
'rest_cannot_manage_global_styles',
__( 'Sorry, you are not allowed to access the global styles on this site.' ),
array(
'status' => rest_authorization_required_code(),
)
);
if ( current_user_can( 'edit_theme_options' ) ) {
return true;
}

return true;
return new WP_Error(
'rest_cannot_read_global_styles',
__( 'Sorry, you are not allowed to access the global styles on this site.' ),
array(
'status' => rest_authorization_required_code(),
)
);
}

/**
Expand Down Expand Up @@ -589,26 +603,13 @@ public function get_theme_item( $request ) {
* Checks if a given request has access to read a single theme global styles config.
*
* @since 6.0.0
* @since 6.7.0 Allow users with edit post capabilities to view theme global styles.
*
* @param WP_REST_Request $request Full details about the request.
* @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise.
*/
public function get_theme_items_permissions_check( $request ) {
peterwilsoncc marked this conversation as resolved.
Show resolved Hide resolved
/*
* Verify if the current user has edit_theme_options capability.
* This capability is required to edit/view/delete global styles.
*/
if ( ! current_user_can( 'edit_theme_options' ) ) {
return new WP_Error(
'rest_cannot_manage_global_styles',
__( 'Sorry, you are not allowed to access the global styles on this site.' ),
array(
'status' => rest_authorization_required_code(),
)
);
}

return true;
return $this->get_theme_item_permissions_check( $request );
}

/**
Expand All @@ -632,7 +633,7 @@ public function get_theme_items( $request ) {
);
}

$response = array();
$response = array();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Random space removed.


// Register theme-defined variations e.g. from block style variation partials under `/styles`.
$partials = WP_Theme_JSON_Resolver::get_style_variations( 'block' );
Expand Down
74 changes: 69 additions & 5 deletions tests/phpunit/tests/rest-api/rest-global-styles-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,21 @@ class WP_REST_Global_Styles_Controller_Test extends WP_Test_REST_Controller_Test
*/
protected static $admin_id;

/**
* @var int
*/
protected static $editor_id;

/**
* @var int
*/
protected static $subscriber_id;

/**
* @var int
*/
protected static $theme_manager_id;

/**
* @var int
*/
Expand Down Expand Up @@ -54,12 +64,30 @@ public static function wpSetupBeforeClass( $factory ) {
)
);

self::$editor_id = $factory->user->create(
array(
'role' => 'editor',
)
);

self::$subscriber_id = $factory->user->create(
array(
'role' => 'subscriber',
)
);

self::$theme_manager_id = $factory->user->create(
array(
'role' => 'subscriber',
)
);

// Add the 'edit_theme_options' capability to the theme manager (subscriber).
$theme_manager_id = get_user_by( 'id', self::$theme_manager_id );
if ( $theme_manager_id instanceof WP_User ) {
$theme_manager_id->add_cap( 'edit_theme_options' );
}

// This creates the global styles for the current theme.
self::$global_styles_id = $factory->post->create(
array(
Expand All @@ -78,11 +106,13 @@ public static function wpSetupBeforeClass( $factory ) {
}

/**
*
* Clean up after our tests run.
*/
public static function wpTearDownAfterClass() {
self::delete_user( self::$admin_id );
self::delete_user( self::$editor_id );
self::delete_user( self::$subscriber_id );
self::delete_user( self::$theme_manager_id );
}

/*
Expand Down Expand Up @@ -264,18 +294,52 @@ public function test_get_theme_item_no_user() {
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/themes/tt1-blocks' );
$response = rest_get_server()->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_manage_global_styles', $response, 401 );
$this->assertErrorResponse( 'rest_cannot_read_global_styles', $response, 401 );
}

/**
* @covers WP_REST_Global_Styles_Controller::get_theme_item
* @ticket 54516
* @ticket 62042
*/
public function test_get_theme_item_permission_check() {
public function test_get_theme_item_subscriber_permission_check() {
wp_set_current_user( self::$subscriber_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/themes/tt1-blocks' );
$response = rest_get_server()->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_manage_global_styles', $response, 403 );
$this->assertErrorResponse( 'rest_cannot_read_global_styles', $response, 403 );
}

/**
* @covers WP_REST_Global_Styles_Controller::get_theme_item
* @ticket 62042
*/
public function test_get_theme_item_editor_permission_check() {
wp_set_current_user( self::$editor_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/themes/tt1-blocks' );
$response = rest_get_server()->dispatch( $request );
// Checks that the response has the expected keys.
$data = $response->get_data();
$links = $response->get_links();
$this->assertArrayHasKey( 'settings', $data, 'Data does not have "settings" key' );
$this->assertArrayHasKey( 'styles', $data, 'Data does not have "styles" key' );
$this->assertArrayHasKey( 'self', $links, 'Links do not have a "self" key' );
}

/**
* @covers WP_REST_Global_Styles_Controller_Gutenberg::get_theme_item
* @ticket 62042
*/
public function test_get_theme_item_theme_options_manager_permission_check() {
wp_set_current_user( self::$theme_manager_id );
switch_theme( 'emptytheme' );
$request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/themes/emptytheme' );
$response = rest_get_server()->dispatch( $request );
// Checks that the response has the expected keys.
$data = $response->get_data();
$links = $response->get_links();
$this->assertArrayHasKey( 'settings', $data, 'Data does not have "settings" key' );
$this->assertArrayHasKey( 'styles', $data, 'Data does not have "styles" key' );
$this->assertArrayHasKey( 'self', $links, 'Links do not have a "self" key' );
}

/**
Expand Down Expand Up @@ -607,7 +671,7 @@ public function test_update_item_invalid_styles_css() {
* within a theme style variation and wouldn't be registered at the time
* of saving via the API.
*
* @covers WP_REST_Global_Styles_Controller_Gutenberg::update_item
* @covers WP_REST_Global_Styles_Controller::update_item
* @ticket 61312
* @ticket 61451
*/
Expand Down
Loading