WordPress.org

Make WordPress Core

Changeset 39108


Ignore:
Timestamp:
11/03/2016 03:15:28 AM (4 years ago)
Author:
rachelbaker
Message:

REST API: Return a WP_Error when a user does not have permission to create or update a post with the provided terms.

Add the 'assign_term' check for post create and update.

Props boonebgorges, johnbillion.
Fixes #38505.

Location:
trunk
Files:
2 edited

Legend:

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

    r39106 r39108  
    460460        }
    461461
     462        if ( ! $this->check_assign_terms_permission( $request ) ) {
     463            return new WP_Error( 'rest_cannot_assign_term', __( 'You do not have permission to assign the provided terms.' ), array( 'status' => rest_authorization_required_code() ) );
     464        }
     465
    462466        return true;
    463467    }
     
    591595        if ( ! empty( $request['sticky'] ) && ! current_user_can( $post_type->cap->edit_others_posts ) ) {
    592596            return new WP_Error( 'rest_cannot_assign_sticky', __( 'You do not have permission to make posts sticky.' ), array( 'status' => rest_authorization_required_code() ) );
     597        }
     598
     599        if ( ! $this->check_assign_terms_permission( $request ) ) {
     600            return new WP_Error( 'rest_cannot_assign_term', __( 'You do not have permission to assign the provided terms.' ), array( 'status' => rest_authorization_required_code() ) );
    593601        }
    594602
     
    12041212            }
    12051213        }
     1214    }
     1215
     1216    /**
     1217     * Checks whether current user can assign all terms sent with the current request.
     1218     *
     1219     * @since 4.7.0
     1220     *
     1221     * @param WP_REST_Request $request The request object with post and terms data.
     1222     * @return bool Whether the current user can assign the provided terms.
     1223     */
     1224    protected function check_assign_terms_permission( $request ) {
     1225        $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) );
     1226        foreach ( $taxonomies as $taxonomy ) {
     1227            $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
     1228
     1229            if ( ! isset( $request[ $base ] ) ) {
     1230                continue;
     1231            }
     1232
     1233            foreach ( $request[ $base ] as $term_id ) {
     1234                // Invalid terms will be rejected later.
     1235                if ( ! get_term( $term_id, $taxonomy->name ) ) {
     1236                    continue;
     1237                }
     1238
     1239                if ( ! current_user_can( 'assign_term', (int) $term_id ) ) {
     1240                    return false;
     1241                }
     1242            }
     1243        }
     1244
     1245        return true;
    12061246    }
    12071247
  • trunk/tests/phpunit/tests/rest-api/rest-posts-controller.php

    r39105 r39108  
    1818
    1919    protected static $supported_formats;
     20
     21    protected $forbidden_cat;
    2022
    2123    public static function wpSetUpBeforeClass( $factory ) {
     
    15051507    }
    15061508
     1509    /**
     1510     * @ticket 38505
     1511     */
     1512    public function test_create_post_with_categories_that_cannot_be_assigned_by_current_user() {
     1513        $cats = self::factory()->category->create_many( 2 );
     1514        $this->forbidden_cat = $cats[1];
     1515
     1516        wp_set_current_user( self::$editor_id );
     1517        $request = new WP_REST_Request( 'POST', '/wp/v2/posts' );
     1518        $params = $this->set_post_data( array(
     1519            'password'   => 'testing',
     1520            'categories' => $cats,
     1521        ) );
     1522        $request->set_body_params( $params );
     1523
     1524        add_filter( 'map_meta_cap', array( $this, 'revoke_assign_term' ), 10, 4 );
     1525        $response = $this->server->dispatch( $request );
     1526        remove_filter( 'map_meta_cap', array( $this, 'revoke_assign_term' ), 10, 4 );
     1527
     1528        $this->assertErrorResponse( 'rest_cannot_assign_term', $response, 403 );
     1529    }
     1530
     1531    public function revoke_assign_term( $caps, $cap, $user_id, $args ) {
     1532        if ( 'assign_term' === $cap && isset( $args[0] ) && $this->forbidden_cat == $args[0] ) {
     1533            $caps = array( 'do_not_allow' );
     1534        }
     1535        return $caps;
     1536    }
     1537
    15071538    public function test_update_item() {
    15081539        wp_set_current_user( self::$editor_id );
     
    19491980        $new_data = $response->get_data();
    19501981        $this->assertEquals( array(), $new_data['categories'] );
     1982    }
     1983
     1984    /**
     1985     * @ticket 38505
     1986     */
     1987    public function test_update_post_with_categories_that_cannot_be_assigned_by_current_user() {
     1988        $cats = self::factory()->category->create_many( 2 );
     1989        $this->forbidden_cat = $cats[1];
     1990
     1991        wp_set_current_user( self::$editor_id );
     1992        $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1993        $params = $this->set_post_data( array(
     1994            'password'   => 'testing',
     1995            'categories' => $cats,
     1996        ) );
     1997        $request->set_body_params( $params );
     1998
     1999        add_filter( 'map_meta_cap', array( $this, 'revoke_assign_term' ), 10, 4 );
     2000        $response = $this->server->dispatch( $request );
     2001        remove_filter( 'map_meta_cap', array( $this, 'revoke_assign_term' ), 10, 4 );
     2002
     2003        $this->assertErrorResponse( 'rest_cannot_assign_term', $response, 403 );
    19512004    }
    19522005
Note: See TracChangeset for help on using the changeset viewer.