Make WordPress Core


Ignore:
Timestamp:
11/05/2021 02:14:07 AM (5 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.