Make WordPress Core


Ignore:
Timestamp:
12/07/2021 08:56:18 PM (3 years ago)
Author:
spacedmonkey
Message:

REST API: Improve permission handling in global style endpoint.

The new wp_global_styles post type is registered to use edit_theme_options in the capability settings. The WP_REST_Global_Styles_Controller class's permission checks methods use the capability in a hard coded form rather than looking up the capability via the post type object. Changing the permission callbacks to lookup capabilities via the post type object, allows theme and plugin developers to modify the capability used for editing global styles via a filter and these values to be respected via the Global Styles REST API.

Props Spacedmonkey, peterwilsoncc, hellofromTonya , antonvlasenko, TimothyBlynJacobs, costdev, zieladam.
Fixes #54516.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/rest-api/rest-global-styles-controller.php

    r52282 r52342  
    88
    99/**
     10 * @covers WP_REST_Global_Styles_Controller
    1011 * @group restapi-global-styles
    1112 * @group restapi
     
    2021     * @var int
    2122     */
     23    protected static $subscriber_id;
     24
     25    /**
     26     * @var int
     27     */
    2228    protected static $global_styles_id;
     29
     30    /**
     31     * @var int
     32     */
     33    protected static $post_id;
    2334
    2435    private function find_and_normalize_global_styles_by_id( $global_styles, $id ) {
     
    4960            )
    5061        );
     62
     63        self::$subscriber_id = $factory->user->create(
     64            array(
     65                'role' => 'subscriber',
     66            )
     67        );
     68
    5169        // This creates the global styles for the current theme.
    52         self::$global_styles_id = wp_insert_post(
     70        self::$global_styles_id = $factory->post->create(
    5371            array(
    5472                'post_content' => '{"version": ' . WP_Theme_JSON::LATEST_SCHEMA . ', "isGlobalStylesUserThemeJSON": true }',
     
    6078                    'wp_theme' => 'tt1-blocks',
    6179                ),
    62             ),
    63             true
    64         );
    65     }
    66 
     80            )
     81        );
     82
     83        self::$post_id = $factory->post->create();
     84    }
     85
     86    /**
     87     *
     88     */
     89    public static function wpTearDownAfterClass() {
     90        self::delete_user( self::$admin_id );
     91        self::delete_user( self::$subscriber_id );
     92    }
     93
     94    /**
     95     * @covers WP_REST_Global_Styles_Controller::register_routes
     96     */
    6797    public function test_register_routes() {
    6898        $routes = rest_get_server()->get_routes();
    6999        $this->assertArrayHasKey( '/wp/v2/global-styles/(?P<id>[\/\w-]+)', $routes );
     100        $this->assertCount( 2, $routes['/wp/v2/global-styles/(?P<id>[\/\w-]+)'] );
     101        $this->assertArrayHasKey( '/wp/v2/global-styles/themes/(?P<stylesheet>[^.\/]+(?:\/[^.\/]+)?)', $routes );
     102        $this->assertCount( 1, $routes['/wp/v2/global-styles/themes/(?P<stylesheet>[^.\/]+(?:\/[^.\/]+)?)'] );
    70103    }
    71104
    72105    public function test_context_param() {
    73         // TODO: Implement test_context_param() method.
    74         $this->markTestIncomplete();
     106        $this->markTestSkipped( 'Controller does not implement context_param().' );
    75107    }
    76108
    77109    public function test_get_items() {
    78         $this->markTestIncomplete();
    79     }
    80 
     110        $this->markTestSkipped( 'Controller does not implement get_items().' );
     111    }
     112
     113    /**
     114     * @covers WP_REST_Global_Styles_Controller::get_theme_item
     115     * @ticket 54516
     116     */
     117    public function test_get_theme_item_no_user() {
     118        wp_set_current_user( 0 );
     119        $request  = new WP_REST_Request( 'GET', '/wp/v2/global-styles/themes/tt1-blocks' );
     120        $response = rest_get_server()->dispatch( $request );
     121        $this->assertErrorResponse( 'rest_cannot_manage_global_styles', $response, 401 );
     122    }
     123
     124    /**
     125     * @covers WP_REST_Global_Styles_Controller::get_theme_item
     126     * @ticket 54516
     127     */
     128    public function test_get_theme_item_permission_check() {
     129        wp_set_current_user( self::$subscriber_id );
     130        $request  = new WP_REST_Request( 'GET', '/wp/v2/global-styles/themes/tt1-blocks' );
     131        $response = rest_get_server()->dispatch( $request );
     132        $this->assertErrorResponse( 'rest_cannot_manage_global_styles', $response, 403 );
     133    }
     134
     135
     136    /**
     137     * @covers WP_REST_Global_Styles_Controller::get_theme_item
     138     * @ticket 54516
     139     */
     140    public function test_get_theme_item_invalid() {
     141        wp_set_current_user( self::$admin_id );
     142        $request  = new WP_REST_Request( 'GET', '/wp/v2/global-styles/themes/invalid' );
     143        $response = rest_get_server()->dispatch( $request );
     144        $this->assertErrorResponse( 'rest_theme_not_found', $response, 404 );
     145    }
     146
     147    /**
     148     * @covers WP_REST_Global_Styles_Controller::get_theme_item
     149     */
     150    public function test_get_theme_item() {
     151        wp_set_current_user( self::$admin_id );
     152        $request  = new WP_REST_Request( 'GET', '/wp/v2/global-styles/themes/tt1-blocks' );
     153        $response = rest_get_server()->dispatch( $request );
     154        $data     = $response->get_data();
     155        unset( $data['_links'] );
     156
     157        $this->assertArrayHasKey( 'settings', $data );
     158        $this->assertArrayHasKey( 'styles', $data );
     159    }
     160
     161    /**
     162     * @covers WP_REST_Global_Styles_Controller::get_item
     163     * @ticket 54516
     164     */
     165    public function test_get_item_no_user() {
     166        wp_set_current_user( 0 );
     167        $request  = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id );
     168        $response = rest_get_server()->dispatch( $request );
     169        $this->assertErrorResponse( 'rest_cannot_view', $response, 401 );
     170    }
     171
     172    /**
     173     * @covers WP_REST_Global_Styles_Controller::get_item
     174     * @ticket 54516
     175     */
     176    public function test_get_item_invalid_post() {
     177        wp_set_current_user( self::$admin_id );
     178        $request  = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$post_id );
     179        $response = rest_get_server()->dispatch( $request );
     180        $this->assertErrorResponse( 'rest_global_styles_not_found', $response, 404 );
     181    }
     182
     183    /**
     184     * @covers WP_REST_Global_Styles_Controller::get_item
     185     * @ticket 54516
     186     */
     187    public function test_get_item_permission_check() {
     188        wp_set_current_user( self::$subscriber_id );
     189        $request  = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id );
     190        $response = rest_get_server()->dispatch( $request );
     191        $this->assertErrorResponse( 'rest_cannot_view', $response, 403 );
     192    }
     193
     194    /**
     195     * @covers WP_REST_Global_Styles_Controller::get_item
     196     * @ticket 54516
     197     */
     198    public function test_get_item_no_user_edit() {
     199        wp_set_current_user( 0 );
     200        $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id );
     201        $request->set_param( 'context', 'edit' );
     202        $response = rest_get_server()->dispatch( $request );
     203        $this->assertErrorResponse( 'rest_forbidden_context', $response, 401 );
     204    }
     205
     206    /**
     207     * @covers WP_REST_Global_Styles_Controller::get_item
     208     * @ticket 54516
     209     */
     210    public function test_get_item_permission_check_edit() {
     211        wp_set_current_user( self::$subscriber_id );
     212        $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id );
     213        $request->set_param( 'context', 'edit' );
     214        $response = rest_get_server()->dispatch( $request );
     215        $this->assertErrorResponse( 'rest_forbidden_context', $response, 403 );
     216    }
     217
     218    /**
     219     * @covers WP_REST_Global_Styles_Controller::get_item
     220     */
    81221    public function test_get_item() {
    82222        wp_set_current_user( self::$admin_id );
     
    101241
    102242    public function test_create_item() {
    103         $this->markTestIncomplete();
    104     }
    105 
     243        $this->markTestSkipped( 'Controller does not implement create_item().' );
     244    }
     245
     246    /**
     247     * @covers WP_REST_Global_Styles_Controller::update_item
     248     * @ticket 54516
     249     */
    106250    public function test_update_item() {
    107251        wp_set_current_user( self::$admin_id );
     
    117261    }
    118262
     263
     264    /**
     265     * @covers WP_REST_Global_Styles_Controller::update_item
     266     * @ticket 54516
     267     */
     268    public function test_update_item_no_user() {
     269        wp_set_current_user( 0 );
     270        $request  = new WP_REST_Request( 'PUT', '/wp/v2/global-styles/' . self::$global_styles_id );
     271        $response = rest_get_server()->dispatch( $request );
     272        $this->assertErrorResponse( 'rest_cannot_edit', $response, 401 );
     273    }
     274
     275    /**
     276     * @covers WP_REST_Global_Styles_Controller::update_item
     277     * @ticket 54516
     278     */
     279    public function test_update_item_invalid_post() {
     280        wp_set_current_user( self::$admin_id );
     281        $request  = new WP_REST_Request( 'PUT', '/wp/v2/global-styles/' . self::$post_id );
     282        $response = rest_get_server()->dispatch( $request );
     283        $this->assertErrorResponse( 'rest_global_styles_not_found', $response, 404 );
     284    }
     285
     286    /**
     287     * @covers WP_REST_Global_Styles_Controller::update_item
     288     * @ticket 54516
     289     */
     290    public function test_update_item_permission_check() {
     291        wp_set_current_user( self::$subscriber_id );
     292        $request  = new WP_REST_Request( 'PUT', '/wp/v2/global-styles/' . self::$global_styles_id );
     293        $response = rest_get_server()->dispatch( $request );
     294        $this->assertErrorResponse( 'rest_cannot_edit', $response, 403 );
     295    }
     296
    119297    public function test_delete_item() {
    120         $this->markTestIncomplete();
     298        $this->markTestSkipped( 'Controller does not implement delete_item().' );
    121299    }
    122300
    123301    public function test_prepare_item() {
    124         // TODO: Implement test_prepare_item() method.
    125         $this->markTestIncomplete();
    126     }
    127 
     302        $this->markTestSkipped( 'Controller does not implement prepare_item().' );
     303    }
     304
     305    /**
     306     * @covers WP_REST_Global_Styles_Controller::get_item_schema
     307     * @ticket 54516
     308     */
    128309    public function test_get_item_schema() {
    129         // TODO: Implement test_get_item_schema() method.
    130         $this->markTestIncomplete();
     310        $request    = new WP_REST_Request( 'OPTIONS', '/wp/v2/global-styles/' . self::$global_styles_id );
     311        $response   = rest_get_server()->dispatch( $request );
     312        $data       = $response->get_data();
     313        $properties = $data['schema']['properties'];
     314        $this->assertCount( 4, $properties, 'Schema properties array does not have exactly 4 elements' );
     315        $this->assertArrayHasKey( 'id', $properties, 'Schema properties array does not have "id" key' );
     316        $this->assertArrayHasKey( 'styles', $properties, 'Schema properties array does not have "styles" key' );
     317        $this->assertArrayHasKey( 'settings', $properties, 'Schema properties array does not have "settings" key' );
     318        $this->assertArrayHasKey( 'title', $properties, 'Schema properties array does not have "title" key' );
    131319    }
    132320}
Note: See TracChangeset for help on using the changeset viewer.