diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php index 6540c52fdf..1d4f9c6817 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php @@ -451,8 +451,7 @@ class WP_REST_Terms_Controller extends WP_REST_Controller { return new WP_Error( 'rest_term_invalid', __( "Resource doesn't exist." ), array( 'status' => 404 ) ); } - $taxonomy_obj = get_taxonomy( $this->taxonomy ); - if ( ! current_user_can( $taxonomy_obj->cap->edit_terms ) ) { + if ( ! current_user_can( 'edit_term', $term->term_id ) ) { return new WP_Error( 'rest_cannot_update', __( 'Sorry, you cannot update resource.' ), array( 'status' => rest_authorization_required_code() ) ); } @@ -527,8 +526,8 @@ class WP_REST_Terms_Controller extends WP_REST_Controller { if ( ! $term ) { return new WP_Error( 'rest_term_invalid', __( "Resource doesn't exist." ), array( 'status' => 404 ) ); } - $taxonomy_obj = get_taxonomy( $this->taxonomy ); - if ( ! current_user_can( $taxonomy_obj->cap->delete_terms ) ) { + + if ( ! current_user_can( 'delete_term', $term->term_id ) ) { return new WP_Error( 'rest_cannot_delete', __( 'Sorry, you cannot delete resource.' ), array( 'status' => rest_authorization_required_code() ) ); } return true; diff --git a/tests/phpunit/tests/rest-api/rest-tags-controller.php b/tests/phpunit/tests/rest-api/rest-tags-controller.php index fd0e1d5604..f5296c057f 100644 --- a/tests/phpunit/tests/rest-api/rest-tags-controller.php +++ b/tests/phpunit/tests/rest-api/rest-tags-controller.php @@ -533,6 +533,54 @@ class WP_Test_REST_Tags_Controller extends WP_Test_REST_Controller_Testcase { $this->assertErrorResponse( 'rest_cannot_update', $response, 403 ); } + /** + * @ticket 38505 + */ + public function test_update_item_with_edit_term_cap_granted() { + wp_set_current_user( self::$subscriber ); + $term = $this->factory->tag->create_and_get(); + $request = new WP_REST_Request( 'POST', '/wp/v2/tags/' . $term->term_id ); + $request->set_param( 'name', 'New Name' ); + + add_filter( 'map_meta_cap', array( $this, 'grant_edit_term' ), 10, 2 ); + $response = $this->server->dispatch( $request ); + remove_filter( 'user_has_cap', array( $this, 'grant_edit_term' ), 10, 2 ); + + $this->assertEquals( 200, $response->get_status() ); + $data = $response->get_data(); + $this->assertEquals( 'New Name', $data['name'] ); + } + + public function grant_edit_term( $caps, $cap ) { + if ( 'edit_term' === $cap ) { + $caps = array( 'read' ); + } + return $caps; + } + + /** + * @ticket 38505 + */ + public function test_update_item_with_edit_term_cap_revoked() { + wp_set_current_user( self::$administrator ); + $term = $this->factory->tag->create_and_get(); + $request = new WP_REST_Request( 'POST', '/wp/v2/tags/' . $term->term_id ); + $request->set_param( 'name', 'New Name' ); + + add_filter( 'map_meta_cap', array( $this, 'revoke_edit_term' ), 10, 2 ); + $response = $this->server->dispatch( $request ); + remove_filter( 'user_has_cap', array( $this, 'revoke_edit_term' ), 10, 2 ); + + $this->assertErrorResponse( 'rest_cannot_update', $response, 403 ); + } + + public function revoke_edit_term( $caps, $cap ) { + if ( 'edit_term' === $cap ) { + $caps = array( 'do_not_allow' ); + } + return $caps; + } + public function test_update_item_parent_non_hierarchical_taxonomy() { wp_set_current_user( self::$administrator ); $term = get_term_by( 'id', $this->factory->tag->create(), 'post_tag' ); @@ -578,6 +626,54 @@ class WP_Test_REST_Tags_Controller extends WP_Test_REST_Controller_Testcase { $this->assertErrorResponse( 'rest_cannot_delete', $response, 403 ); } + /** + * @ticket 38505 + */ + public function test_delete_item_with_delete_term_cap_granted() { + wp_set_current_user( self::$subscriber ); + $term = get_term_by( 'id', $this->factory->tag->create( array( 'name' => 'Deleted Tag' ) ), 'post_tag' ); + $request = new WP_REST_Request( 'DELETE', '/wp/v2/tags/' . $term->term_id ); + $request->set_param( 'force', true ); + + add_filter( 'map_meta_cap', array( $this, 'grant_delete_term' ), 10, 2 ); + $response = $this->server->dispatch( $request ); + remove_filter( 'map_meta_cap', array( $this, 'grant_delete_term' ), 10, 2 ); + + $this->assertEquals( 200, $response->get_status() ); + $data = $response->get_data(); + $this->assertEquals( 'Deleted Tag', $data['name'] ); + } + + public function grant_delete_term( $caps, $cap ) { + if ( 'delete_term' === $cap ) { + $caps = array( 'read' ); + } + return $caps; + } + + /** + * @ticket 38505 + */ + public function test_delete_item_with_delete_term_cap_revoked() { + wp_set_current_user( self::$administrator ); + $term = get_term_by( 'id', $this->factory->tag->create( array( 'name' => 'Deleted Tag' ) ), 'post_tag' ); + $request = new WP_REST_Request( 'DELETE', '/wp/v2/tags/' . $term->term_id ); + $request->set_param( 'force', true ); + + add_filter( 'map_meta_cap', array( $this, 'revoke_delete_term' ), 10, 2 ); + $response = $this->server->dispatch( $request ); + remove_filter( 'map_meta_cap', array( $this, 'revoke_delete_term' ), 10, 2 ); + + $this->assertErrorResponse( 'rest_cannot_delete', $response, 403 ); + } + + public function revoke_delete_term( $caps, $cap ) { + if ( 'delete_term' === $cap ) { + $caps = array( 'do_not_allow' ); + } + return $caps; + } + public function test_prepare_item() { $term = get_term_by( 'id', $this->factory->tag->create(), 'post_tag' ); $request = new WP_REST_Request( 'GET', '/wp/v2/tags/' . $term->term_id );