diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php index 1c2a7697c4ec0..949e485fc6c09 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php @@ -236,12 +236,28 @@ public function _sanitize_template_id( $id ) { * Checks if a given request has access to read templates. * * @since 5.8.0 + * @since 6.6.0 Allow users with edit_posts capability to read templates. * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has read access, WP_Error object otherwise. */ public function get_items_permissions_check( $request ) { - return $this->permissions_check( $request ); + 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; + } + } + + return new WP_Error( + 'rest_cannot_manage_templates', + __( 'Sorry, you are not allowed to access the templates on this site.', 'default' ), + array( + 'status' => rest_authorization_required_code(), + ) + ); } /** @@ -277,12 +293,28 @@ public function get_items( $request ) { * Checks if a given request has access to read a single template. * * @since 5.8.0 + * @since 6.6.0 Allow users with edit_posts capability to read individual templates. * * @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_item_permissions_check( $request ) { - return $this->permissions_check( $request ); + 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; + } + } + + return new WP_Error( + 'rest_cannot_manage_templates', + __( 'Sorry, you are not allowed to access the templates on this site.', 'default' ), + array( + 'status' => rest_authorization_required_code(), + ) + ); } /** diff --git a/tests/phpunit/tests/rest-api/wpRestTemplatesController.php b/tests/phpunit/tests/rest-api/wpRestTemplatesController.php index 376daffee2989..d06295a1bbcc6 100644 --- a/tests/phpunit/tests/rest-api/wpRestTemplatesController.php +++ b/tests/phpunit/tests/rest-api/wpRestTemplatesController.php @@ -14,6 +14,8 @@ class Tests_REST_WpRestTemplatesController extends WP_Test_REST_Controller_Testc * @var int */ protected static $admin_id; + protected static $editor_id; + protected static $subscriber_id; private static $template_post; private static $template_part_post; @@ -23,11 +25,21 @@ class Tests_REST_WpRestTemplatesController extends WP_Test_REST_Controller_Testc * @param WP_UnitTest_Factory $factory Helper that lets us create fake data. */ public static function wpSetupBeforeClass( $factory ) { - self::$admin_id = $factory->user->create( + self::$admin_id = $factory->user->create( array( 'role' => 'administrator', ) ); + self::$editor_id = $factory->user->create( + array( + 'role' => 'editor', + ) + ); + self::$subscriber_id = $factory->user->create( + array( + 'role' => 'subscriber', + ) + ); // Set up template post. $args = array( @@ -163,6 +175,51 @@ public function test_get_items() { ); } + /** + * @covers WP_REST_Templates_Controller::get_items + */ + public function test_get_items_editor() { + wp_set_current_user( self::$editor_id ); + $request = new WP_REST_Request( 'GET', '/wp/v2/templates' ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + + $this->assertSame( + array( + 'id' => 'default//my_template', + 'theme' => 'default', + 'slug' => 'my_template', + 'source' => 'custom', + 'origin' => null, + 'type' => 'wp_template', + 'description' => 'Description of my template.', + 'title' => array( + 'raw' => 'My Template', + 'rendered' => 'My Template', + ), + 'status' => 'publish', + 'wp_id' => self::$template_post->ID, + 'has_theme_file' => false, + 'is_custom' => true, + 'author' => 0, + 'modified' => mysql_to_rfc3339( self::$template_post->post_modified ), + 'author_text' => 'Test Blog', + 'original_source' => 'site', + ), + $this->find_and_normalize_template_by_id( $data, 'default//my_template' ) + ); + } + + /** + * @covers WP_REST_Templates_Controller::get_items + */ + public function test_get_items_no_permission_subscriber() { + wp_set_current_user( self::$subscriber_id ); + $request = new WP_REST_Request( 'GET', '/wp/v2/templates' ); + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_cannot_manage_templates', $response, 403 ); + } + /** * @covers WP_REST_Templates_Controller::get_items */ @@ -210,6 +267,54 @@ public function test_get_item() { ); } + /** + * @covers WP_REST_Templates_Controller::get_item + */ + public function test_get_item_editor() { + wp_set_current_user( self::$editor_id ); + $request = new WP_REST_Request( 'GET', '/wp/v2/templates/default//my_template' ); + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + unset( $data['content'] ); + unset( $data['_links'] ); + + $this->assertSame( + array( + 'id' => 'default//my_template', + 'theme' => 'default', + 'slug' => 'my_template', + 'source' => 'custom', + 'origin' => null, + 'type' => 'wp_template', + 'description' => 'Description of my template.', + 'title' => array( + 'raw' => 'My Template', + 'rendered' => 'My Template', + ), + 'status' => 'publish', + 'wp_id' => self::$template_post->ID, + 'has_theme_file' => false, + 'is_custom' => true, + 'author' => 0, + 'modified' => mysql_to_rfc3339( self::$template_post->post_modified ), + 'author_text' => 'Test Blog', + 'original_source' => 'site', + ), + $data + ); + } + + /** + * @covers WP_REST_Templates_Controller::get_item + */ + public function test_get_item_subscriber() { + wp_set_current_user( self::$subscriber_id ); + $request = new WP_REST_Request( 'GET', '/wp/v2/templates/default//my_template' ); + $response = rest_get_server()->dispatch( $request ); + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_cannot_manage_templates', $response, 403 ); + } + /** * @ticket 54507 * @dataProvider data_get_item_works_with_a_single_slash