REST API: Prevent attachment ID/image source mismatch when editing an image.

Fixes #50565.

git-svn-id: https://develop.svn.wordpress.org/trunk@48498 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Andrew Ozz 2020-07-16 21:54:37 +00:00
parent 082cb0ab20
commit 0aab2584a0
3 changed files with 74 additions and 6 deletions

View File

@ -421,7 +421,11 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
$image_file = wp_get_original_image_path( $attachment_id );
$image_meta = wp_get_attachment_metadata( $attachment_id );
if ( ! $image_meta || ! $image_file ) {
if (
! $image_meta ||
! $image_file ||
! wp_image_file_matches_image_meta( $request['src'], $image_meta )
) {
return new WP_Error(
'rest_unknown_attachment',
__( 'Unable to get meta information for file.' ),
@ -1289,6 +1293,12 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
'minimum' => 0,
'maximum' => 100,
),
'src' => array(
'description' => __( 'URL to the edited image file.' ),
'type' => 'string',
'format' => 'uri',
'required' => true,
),
);
}

View File

@ -1798,9 +1798,10 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
* @ticket 44405
*/
public function test_edit_image_returns_error_if_logged_out() {
$attachment = self::factory()->attachment->create();
$attachment = self::factory()->attachment->create_upload_object( $this->test_file );
$request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment}/edit" );
$request->set_body_params( array( 'src' => wp_get_attachment_image_url( $attachment, 'full' ) ) );
$response = rest_do_request( $request );
$this->assertErrorResponse( 'rest_cannot_edit_image', $response, 401 );
}
@ -1813,9 +1814,10 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
$user->add_cap( 'upload_files', false );
wp_set_current_user( $user->ID );
$attachment = self::factory()->attachment->create( array( 'post_author' => $user->ID ) );
$attachment = self::factory()->attachment->create_upload_object( $this->test_file );
$request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment}/edit" );
$request->set_body_params( array( 'src' => wp_get_attachment_image_url( $attachment, 'full' ) ) );
$response = rest_do_request( $request );
$this->assertErrorResponse( 'rest_cannot_edit_image', $response, 403 );
}
@ -1825,9 +1827,10 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
*/
public function test_edit_image_returns_error_if_cannot_edit() {
wp_set_current_user( self::$uploader_id );
$attachment = self::factory()->attachment->create();
$attachment = self::factory()->attachment->create_upload_object( $this->test_file );
$request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment}/edit" );
$request->set_body_params( array( 'src' => wp_get_attachment_image_url( $attachment, 'full' ) ) );
$response = rest_do_request( $request );
$this->assertErrorResponse( 'rest_cannot_edit', $response, 403 );
}
@ -1840,6 +1843,7 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
$attachment = self::factory()->attachment->create();
$request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment}/edit" );
$request->set_body_params( array( 'src' => '/wp-content/uploads/2020/07/canola.jpg' ) );
$response = rest_do_request( $request );
$this->assertErrorResponse( 'rest_unknown_attachment', $response, 404 );
}
@ -1858,6 +1862,7 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
);
$request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment}/edit" );
$request->set_body_params( array( 'src' => wp_get_attachment_image_url( $attachment, 'full' ) ) );
$response = rest_do_request( $request );
$this->assertErrorResponse( 'rest_cannot_edit_file_type', $response, 400 );
}
@ -1870,6 +1875,7 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
$attachment = self::factory()->attachment->create_upload_object( $this->test_file );
$request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment}/edit" );
$request->set_body_params( array( 'src' => wp_get_attachment_image_url( $attachment, 'full' ) ) );
$response = rest_do_request( $request );
$this->assertErrorResponse( 'rest_image_not_edited', $response, 400 );
}
@ -1884,8 +1890,13 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
$this->setup_mock_editor();
WP_Image_Editor_Mock::$edit_return['rotate'] = new WP_Error();
$params = array(
'rotation' => 60,
'src' => wp_get_attachment_image_url( $attachment, 'full' ),
);
$request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment}/edit" );
$request->set_body_params( array( 'rotation' => 60 ) );
$request->set_body_params( $params );
$response = rest_do_request( $request );
$this->assertErrorResponse( 'rest_image_rotation_failed', $response, 500 );
@ -1915,6 +1926,8 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
'y' => 10,
'width' => 10,
'height' => 5,
'src' => wp_get_attachment_image_url( $attachment, 'full' ),
)
);
$response = rest_do_request( $request );
@ -1934,8 +1947,13 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
wp_set_current_user( self::$superadmin_id );
$attachment = self::factory()->attachment->create_upload_object( $this->test_file );
$params = array(
'rotation' => 60,
'src' => wp_get_attachment_image_url( $attachment, 'full' ),
);
$request = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment}/edit" );
$request->set_body_params( array( 'rotation' => 60 ) );
$request->set_body_params( $params );
$response = rest_do_request( $request );
$item = $response->get_data();
@ -1948,6 +1966,41 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
$this->assertContains( 'canola', $item['media_details']['parent_image']['file'] );
}
/**
* @ticket 50565
*/
public function test_edit_image_returns_error_if_mismatched_src() {
wp_set_current_user( self::$superadmin_id );
$attachment_id_image1 = self::factory()->attachment->create_upload_object( $this->test_file );
$attachment_id_image2 = self::factory()->attachment->create_upload_object( $this->test_file2 );
$attachment_id_file = self::factory()->attachment->create();
// URL to the first uploaded image.
$image_src = wp_get_attachment_image_url( $attachment_id_image1, 'large' );
// Test: attachment ID points to a different, non-image attachment.
$request_1 = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id_file}/edit" );
$request_1->set_body_params( array( 'src' => $image_src ) );
$response_1 = rest_do_request( $request_1 );
$this->assertErrorResponse( 'rest_unknown_attachment', $response_1, 404 );
// Test: attachment ID points to a different image attachment.
$request_2 = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id_image2}/edit" );
$request_2->set_body_params( array( 'src' => $image_src ) );
$response_2 = rest_do_request( $request_2 );
$this->assertErrorResponse( 'rest_unknown_attachment', $response_2, 404 );
// Test: attachment src points to a sub-size of the image.
$request_3 = new WP_REST_Request( 'POST', "/wp/v2/media/{$attachment_id_image1}/edit" );
$request_3->set_body_params( array( 'src' => wp_get_attachment_image_url( $attachment_id_image1, 'medium' ) ) );
$response_3 = rest_do_request( $request_3 );
// 'rest_image_not_edited' as the file wasn't edited.
$this->assertErrorResponse( 'rest_image_not_edited', $response_3, 400 );
}
/**
* Sets up the mock image editor.
*

View File

@ -2377,6 +2377,11 @@ mockedApiResponse.Schema = {
"required": false,
"description": "As a percentage of the image, the height to crop the image to.",
"type": "number"
},
"src": {
"required": true,
"description": "URL to the edited image file.",
"type": "string"
}
}
}