WordPress.org

Make WordPress Core


Ignore:
Timestamp:
08/15/2019 10:00:49 PM (2 months ago)
Author:
kadamwhite
Message:

REST API: Prevent deletion of post revisions.

Allowing the client to delete revisions breaks the "audit trail" functionality. This is not allowed in WordPress and shouldn't be allowed through the API.
While not recommended, a plugin may opt-in to the previous behavior by setting a custom 'delete_post' capability for the revisions post type.

Props dlh, danielbachhuber, TimothyBlynJacobs, azaozz, kadamwhite.
Fixes #43709.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/rest-api/rest-revisions-controller.php

    r43647 r45812  
    7575        $this->revision_3      = array_pop( $revisions );
    7676        $this->revision_id3    = $this->revision_3->ID;
     77    }
     78
     79    public function tearDown() {
     80        parent::tearDown();
     81
     82        remove_filter( 'map_meta_cap', array( $this, '_filter_map_meta_cap_remove_no_allow_revisions' ) );
     83    }
     84
     85    public function _filter_map_meta_cap_remove_no_allow_revisions( $caps, $cap, $user_id, $args ) {
     86        if ( 'delete_post' !== $cap || empty( $args ) ) {
     87            return $caps;
     88        }
     89        $post = get_post( $args[0] );
     90        if ( ! $post || 'revision' !== $post->post_type ) {
     91            return $caps;
     92        }
     93        $key = array_search( 'do_not_allow', $caps, true );
     94        if ( false !== $key ) {
     95            unset( $caps[ $key ] );
     96        }
     97        return $caps;
    7798    }
    7899
     
    217238        $request->set_param( 'force', true );
    218239        $response = rest_get_server()->dispatch( $request );
     240        $this->assertErrorResponse( 'rest_cannot_delete', $response, 403 );
     241        $this->assertNotNull( get_post( $this->revision_id1 ) );
     242    }
     243
     244    public function test_delete_item_remove_do_not_allow() {
     245        wp_set_current_user( self::$editor_id );
     246        add_filter( 'map_meta_cap', array( $this, '_filter_map_meta_cap_remove_no_allow_revisions' ), 10, 4 );
     247        $request = new WP_REST_Request( 'DELETE', '/wp/v2/posts/' . self::$post_id . '/revisions/' . $this->revision_id1 );
     248        $request->set_param( 'force', true );
     249        $response = rest_get_server()->dispatch( $request );
    219250        $this->assertEquals( 200, $response->get_status() );
    220251        $this->assertNull( get_post( $this->revision_id1 ) );
    221252    }
    222253
     254    public function test_delete_item_cannot_delete_parent() {
     255        wp_set_current_user( self::$editor_id );
     256        $request = new WP_REST_Request( 'DELETE', '/wp/v2/posts/' . self::$post_id . '/revisions/' . $this->revision_id1 );
     257        $request->set_param( 'force', true );
     258        $response = rest_get_server()->dispatch( $request );
     259        $this->assertErrorResponse( 'rest_cannot_delete', $response, 403 );
     260        $this->assertNotNull( get_post( $this->revision_id1 ) );
     261    }
     262
    223263    public function test_delete_item_no_trash() {
    224264        wp_set_current_user( self::$editor_id );
    225 
     265        add_filter( 'map_meta_cap', array( $this, '_filter_map_meta_cap_remove_no_allow_revisions' ), 10, 4 );
    226266        $request  = new WP_REST_Request( 'DELETE', '/wp/v2/posts/' . self::$post_id . '/revisions/' . $this->revision_id1 );
    227267        $response = rest_get_server()->dispatch( $request );
Note: See TracChangeset for help on using the changeset viewer.