Make WordPress Core


Ignore:
Timestamp:
12/07/2021 08:56:18 PM (2 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/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php

    r52332 r52342  
    1212 */
    1313class WP_REST_Global_Styles_Controller extends WP_REST_Controller {
     14
     15    /**
     16     * Post type.
     17     *
     18     * @since 5.9.0
     19     * @var string
     20     */
     21    protected $post_type;
     22
    1423    /**
    1524     * Constructor.
     
    1928        $this->namespace = 'wp/v2';
    2029        $this->rest_base = 'global-styles';
     30        $this->post_type = 'wp_global_styles';
    2131    }
    2232
     
    7686
    7787    /**
    78      * Checks if the user has permissions to make the request.
    79      *
    80      * @since 5.9.0
    81      *
     88     * Checks if a given request has access to read a single global style.
     89     *
     90     * @since 5.9.0
     91     *
     92     * @param WP_REST_Request $request Full details about the request.
    8293     * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
    8394     */
    84     protected function permissions_check() {
    85         // Verify if the current user has edit_theme_options capability.
    86         // This capability is required to edit/view/delete templates.
    87         if ( ! current_user_can( 'edit_theme_options' ) ) {
     95    public function get_item_permissions_check( $request ) {
     96        $post = $this->get_post( $request['id'] );
     97        if ( is_wp_error( $post ) ) {
     98            return $post;
     99        }
     100
     101        if ( 'edit' === $request['context'] && $post && ! $this->check_update_permission( $post ) ) {
    88102            return new WP_Error(
    89                 'rest_cannot_manage_global_styles',
    90                 __( 'Sorry, you are not allowed to access the global styles on this site.' ),
    91                 array(
    92                     'status' => rest_authorization_required_code(),
    93                 )
     103                'rest_forbidden_context',
     104                __( 'Sorry, you are not allowed to edit this global style.' ),
     105                array( 'status' => rest_authorization_required_code() )
    94106            );
    95107        }
    96108
     109        if ( ! $this->check_read_permission( $post ) ) {
     110            return new WP_Error(
     111                'rest_cannot_view',
     112                __( 'Sorry, you are not allowed to view this global style.' ),
     113                array( 'status' => rest_authorization_required_code() )
     114            );
     115        }
     116
    97117        return true;
    98118    }
    99119
    100120    /**
    101      * Checks if a given request has access to read a single global styles config.
    102      *
    103      * @param WP_REST_Request $request Full details about the request.
    104      * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise.
    105      */
    106     public function get_item_permissions_check( $request ) {
    107         return $this->permissions_check( $request );
     121     * Checks if a global style can be read.
     122     *
     123     * @since 5.9.0
     124     *
     125     * @param WP_Post $post Post object.
     126     * @return bool Whether the post can be read.
     127     */
     128    protected function check_read_permission( $post ) {
     129        return current_user_can( 'read_post', $post->ID );
    108130    }
    109131
     
    118140     */
    119141    public function get_item( $request ) {
    120         $post = get_post( $request['id'] );
    121         if ( ! $post || 'wp_global_styles' !== $post->post_type ) {
    122             return new WP_Error( 'rest_global_styles_not_found', __( 'No global styles config exist with that id.' ), array( 'status' => 404 ) );
     142        $post = $this->get_post( $request['id'] );
     143        if ( is_wp_error( $post ) ) {
     144            return $post;
    123145        }
    124146
     
    135157     */
    136158    public function update_item_permissions_check( $request ) {
    137         return $this->permissions_check( $request );
     159        $post = $this->get_post( $request['id'] );
     160        if ( is_wp_error( $post ) ) {
     161            return $post;
     162        }
     163
     164        if ( $post && ! $this->check_update_permission( $post ) ) {
     165            return new WP_Error(
     166                'rest_cannot_edit',
     167                __( 'Sorry, you are not allowed to edit this global style.' ),
     168                array( 'status' => rest_authorization_required_code() )
     169            );
     170        }
     171
     172        return true;
     173    }
     174
     175    /**
     176     * Checks if a global style can be edited.
     177     *
     178     * @since 5.9.0
     179     *
     180     * @param WP_Post $post Post object.
     181     * @return bool Whether the post can be edited.
     182     */
     183    protected function check_update_permission( $post ) {
     184        return current_user_can( 'edit_post', $post->ID );
    138185    }
    139186
     
    147194     */
    148195    public function update_item( $request ) {
    149         $post_before = get_post( $request['id'] );
    150         if ( ! $post_before || 'wp_global_styles' !== $post_before->post_type ) {
    151             return new WP_Error( 'rest_global_styles_not_found', __( 'No global styles config exist with that id.' ), array( 'status' => 404 ) );
     196        $post_before = $this->get_post( $request['id'] );
     197        if ( is_wp_error( $post_before ) ) {
     198            return $post_before;
    152199        }
    153200
     
    290337    }
    291338
     339    /**
     340     * Get the post, if the ID is valid.
     341     *
     342     * @since 5.9.0
     343     *
     344     * @param int $id Supplied ID.
     345     * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise.
     346     */
     347    protected function get_post( $id ) {
     348        $error = new WP_Error(
     349            'rest_global_styles_not_found',
     350            __( 'No global styles config exist with that id.' ),
     351            array( 'status' => 404 )
     352        );
     353
     354        $id = (int) $id;
     355        if ( $id <= 0 ) {
     356            return $error;
     357        }
     358
     359        $post = get_post( $id );
     360        if ( empty( $post ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
     361            return $error;
     362        }
     363
     364        return $post;
     365    }
     366
    292367
    293368    /**
     
    324399        $rels = array();
    325400
    326         $post_type = get_post_type_object( 'wp_global_styles' );
     401        $post_type = get_post_type_object( $this->post_type );
    327402        if ( current_user_can( $post_type->cap->publish_posts ) ) {
    328403            $rels[] = 'https://api.w.org/action-publish';
     
    372447        $schema = array(
    373448            '$schema'    => 'http://json-schema.org/draft-04/schema#',
    374             'title'      => 'wp_global_styles',
     449            'title'      => $this->post_type,
    375450            'type'       => 'object',
    376451            'properties' => array(
     
    427502     */
    428503    public function get_theme_item_permissions_check( $request ) {
    429         return $this->permissions_check( $request );
     504        // Verify if the current user has edit_theme_options capability.
     505        // This capability is required to edit/view/delete templates.
     506        if ( ! current_user_can( 'edit_theme_options' ) ) {
     507            return new WP_Error(
     508                'rest_cannot_manage_global_styles',
     509                __( 'Sorry, you are not allowed to access the global styles on this site.' ),
     510                array(
     511                    'status' => rest_authorization_required_code(),
     512                )
     513            );
     514        }
     515
     516        return true;
    430517    }
    431518
Note: See TracChangeset for help on using the changeset viewer.