Make WordPress Core


Ignore:
Timestamp:
11/05/2021 02:14:07 AM (3 years ago)
Author:
TimothyBlynJacobs
Message:

REST API: Allow sidebars and their widgets to be public.

By default, only users with the edit_theme_options capability can access the sidebars and widgets REST API endpoints. In this commit, A new show_in_rest parameter is added to the register_sidebar function. When enabled, all users will be able to access that sidebar and any widgets belonging to that sidebar.

This commit reduces the context for a widget's instance information to only edit. This is to ensure that internal widget data is not inadvertently exposed to the public. A future ticket may expose additional APIs to allow widget authors to indicate that their instance data can be safely exposed. REST API consumers intending to access this instance information should take care to explicitly set the context parameter to edit.

Props spacedmonkey, zieladam.
Fixes #53915.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-widgets-controller.php

    r51791 r52016  
    1616 */
    1717class WP_REST_Widgets_Controller extends WP_REST_Controller {
     18
     19    /**
     20     * Tracks whether {@see retrieve_widgets()} has been called in the current request.
     21     *
     22     * @since 5.9.0
     23     * @var bool
     24     */
     25    protected $widgets_retrieved = false;
    1826
    1927    /**
     
    98106     */
    99107    public function get_items_permissions_check( $request ) {
     108        $this->retrieve_widgets();
     109        if ( isset( $request['sidebar'] ) && $this->check_read_sidebar_permission( $request['sidebar'] ) ) {
     110            return true;
     111        }
     112
     113        foreach ( wp_get_sidebars_widgets() as $sidebar_id => $widget_ids ) {
     114            if ( $this->check_read_sidebar_permission( $sidebar_id ) ) {
     115                return true;
     116            }
     117        }
     118
    100119        return $this->permissions_check( $request );
    101120    }
     
    110129     */
    111130    public function get_items( $request ) {
    112         retrieve_widgets();
    113 
    114         $prepared = array();
     131        $this->retrieve_widgets();
     132
     133        $prepared          = array();
     134        $permissions_check = $this->permissions_check( $request );
    115135
    116136        foreach ( wp_get_sidebars_widgets() as $sidebar_id => $widget_ids ) {
     
    119139            }
    120140
     141            if ( is_wp_error( $permissions_check ) && ! $this->check_read_sidebar_permission( $sidebar_id ) ) {
     142                continue;
     143            }
     144
    121145            foreach ( $widget_ids as $widget_id ) {
    122146                $response = $this->prepare_item_for_response( compact( 'sidebar_id', 'widget_id' ), $request );
     
    140164     */
    141165    public function get_item_permissions_check( $request ) {
     166        $this->retrieve_widgets();
     167
     168        $widget_id  = $request['id'];
     169        $sidebar_id = wp_find_widgets_sidebar( $widget_id );
     170
     171        if ( $sidebar_id && $this->check_read_sidebar_permission( $sidebar_id ) ) {
     172            return true;
     173        }
     174
    142175        return $this->permissions_check( $request );
    143176    }
    144177
    145178    /**
     179     * Checks if a sidebar can be read publicly.
     180     *
     181     * @since 5.9.0
     182     *
     183     * @param string $sidebar_id The sidebar id.
     184     * @return bool Whether the sidebar can be read.
     185     */
     186    protected function check_read_sidebar_permission( $sidebar_id ) {
     187        $sidebar = wp_get_sidebar( $sidebar_id );
     188
     189        return ! empty( $sidebar['show_in_rest'] );
     190    }
     191
     192    /**
    146193     * Gets an individual widget.
    147194     *
     
    152199     */
    153200    public function get_item( $request ) {
    154         retrieve_widgets();
     201        $this->retrieve_widgets();
    155202
    156203        $widget_id  = $request['id'];
     
    248295         */
    249296        wp_get_sidebars_widgets();
    250 
    251         retrieve_widgets();
     297        $this->retrieve_widgets();
    252298
    253299        $widget_id  = $request['id'];
     
    324370         */
    325371        wp_get_sidebars_widgets();
    326 
    327         retrieve_widgets();
     372        $this->retrieve_widgets();
    328373
    329374        $widget_id  = $request['id'];
     
    438483
    439484        return true;
     485    }
     486
     487    /**
     488     * Looks for "lost" widgets once per request.
     489     *
     490     * @since 5.9.0
     491     *
     492     * @see retrieve_widgets()
     493     */
     494    protected function retrieve_widgets() {
     495        if ( ! $this->widgets_retrieved ) {
     496            retrieve_widgets();
     497            $this->widgets_retrieved = true;
     498        }
    440499    }
    441500
     
    768827                    'description' => __( 'Instance settings of the widget, if supported.' ),
    769828                    'type'        => 'object',
    770                     'context'     => array( 'view', 'edit', 'embed' ),
     829                    'context'     => array( 'edit' ),
    771830                    'default'     => null,
    772831                    'properties'  => array(
     
    774833                            'description' => __( 'Base64 encoded representation of the instance settings.' ),
    775834                            'type'        => 'string',
    776                             'context'     => array( 'view', 'edit', 'embed' ),
     835                            'context'     => array( 'edit' ),
    777836                        ),
    778837                        'hash'    => array(
    779838                            'description' => __( 'Cryptographic hash of the instance settings.' ),
    780839                            'type'        => 'string',
    781                             'context'     => array( 'view', 'edit', 'embed' ),
     840                            'context'     => array( 'edit' ),
    782841                        ),
    783842                        'raw'     => array(
    784843                            'description' => __( 'Unencoded instance settings, if supported.' ),
    785844                            'type'        => 'object',
    786                             'context'     => array( 'view', 'edit', 'embed' ),
     845                            'context'     => array( 'edit' ),
    787846                        ),
    788847                    ),
Note: See TracChangeset for help on using the changeset viewer.