Return HTTP 404 in REST API for non-existent product reviews (#48726)
* Return HTTP 404 when accessing non-existent product views via REST API * Fix unit tests * Add changelog * Address feedback
This commit is contained in:
parent
ec95afc178
commit
21cc919094
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: update
|
||||
|
||||
Return HTTP 404 when trying to read or delete a non-existent product review.
|
|
@ -144,6 +144,11 @@ class WC_REST_Product_Reviews_V1_Controller extends WC_REST_Controller {
|
|||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_item_permissions_check( $request ) {
|
||||
$review = $this->get_review( (int) $request['id'], (int) $request['product_id'] );
|
||||
if ( is_wp_error( $review ) ) {
|
||||
return $review;
|
||||
}
|
||||
|
||||
if ( ! wc_rest_check_product_reviews_permissions( 'read', (int) $request['id'] ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
@ -172,6 +177,11 @@ class WC_REST_Product_Reviews_V1_Controller extends WC_REST_Controller {
|
|||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function update_item_permissions_check( $request ) {
|
||||
$review = $this->get_review( (int) $request['id'], (int) $request['product_id'] );
|
||||
if ( is_wp_error( $review ) ) {
|
||||
return $review;
|
||||
}
|
||||
|
||||
if ( ! wc_rest_check_product_reviews_permissions( 'edit', (int) $request['id'] ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you cannot edit this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
@ -186,6 +196,11 @@ class WC_REST_Product_Reviews_V1_Controller extends WC_REST_Controller {
|
|||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function delete_item_permissions_check( $request ) {
|
||||
$review = $this->get_review( (int) $request['id'], (int) $request['product_id'] );
|
||||
if ( is_wp_error( $review ) ) {
|
||||
return $review;
|
||||
}
|
||||
|
||||
if ( ! wc_rest_check_product_reviews_permissions( 'delete', (int) $request['id'] ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_delete', __( 'Sorry, you cannot delete this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
@ -218,6 +233,28 @@ class WC_REST_Product_Reviews_V1_Controller extends WC_REST_Controller {
|
|||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a single product review from the database.
|
||||
*
|
||||
* @param int $id Review ID.
|
||||
* @param int $product_id Product ID.
|
||||
*
|
||||
* @since 9.2.0
|
||||
* @return \WP_Comment
|
||||
*/
|
||||
protected function get_review( int $id, int $product_id ) {
|
||||
if ( 0 >= $product_id || 'product' !== get_post_type( $product_id ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_product_invalid_id', __( 'Invalid product ID.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$review = 0 <= $id ? get_comment( $id ) : null;
|
||||
if ( empty( $review ) || empty( $review->comment_ID ) || 'review' !== get_comment_type( $id ) || empty( $review->comment_post_ID ) || (int) $review->comment_post_ID !== $product_id ) {
|
||||
return new WP_Error( 'woocommerce_rest_product_review_invalid_id', __( 'Invalid product review ID.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
return $review;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single product review.
|
||||
*
|
||||
|
@ -225,17 +262,9 @@ class WC_REST_Product_Reviews_V1_Controller extends WC_REST_Controller {
|
|||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_item( $request ) {
|
||||
$id = (int) $request['id'];
|
||||
$product_id = (int) $request['product_id'];
|
||||
|
||||
if ( 'product' !== get_post_type( $product_id ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_product_invalid_id', __( 'Invalid product ID.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$review = get_comment( $id );
|
||||
|
||||
if ( empty( $id ) || empty( $review ) || intval( $review->comment_post_ID ) !== $product_id ) {
|
||||
return new WP_Error( 'woocommerce_rest_invalid_id', __( 'Invalid resource ID.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
$review = $this->get_review( (int) $request['id'], (int) $request['product_id'] );
|
||||
if ( is_wp_error( $review ) ) {
|
||||
return $review;
|
||||
}
|
||||
|
||||
$delivery = $this->prepare_item_for_response( $review, $request );
|
||||
|
@ -309,14 +338,9 @@ class WC_REST_Product_Reviews_V1_Controller extends WC_REST_Controller {
|
|||
$product_review_id = (int) $request['id'];
|
||||
$product_id = (int) $request['product_id'];
|
||||
|
||||
if ( 'product' !== get_post_type( $product_id ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_product_invalid_id', __( 'Invalid product ID.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$review = get_comment( $product_review_id );
|
||||
|
||||
if ( empty( $product_review_id ) || empty( $review ) || intval( $review->comment_post_ID ) !== $product_id ) {
|
||||
return new WP_Error( 'woocommerce_rest_product_review_invalid_id', __( 'Invalid resource ID.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
$review = $this->get_review( $product_review_id, $product_id );
|
||||
if ( is_wp_error( $review ) ) {
|
||||
return $review;
|
||||
}
|
||||
|
||||
$prepared_review = $this->prepare_item_for_database( $request );
|
||||
|
@ -358,15 +382,11 @@ class WC_REST_Product_Reviews_V1_Controller extends WC_REST_Controller {
|
|||
public function delete_item( $request ) {
|
||||
$product_id = (int) $request['product_id'];
|
||||
$product_review_id = (int) $request['id'];
|
||||
$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
|
||||
$product_review = $this->get_review( $product_review_id, $product_id );
|
||||
$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
|
||||
|
||||
if ( 'product' !== get_post_type( $product_id ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_product_invalid_id', __( 'Invalid product ID.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$product_review = get_comment( $product_review_id );
|
||||
if ( empty( $product_review_id ) || empty( $product_review->comment_ID ) || empty( $product_review->comment_post_ID ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_product_review_invalid_id', __( 'Invalid product review ID.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
if ( is_wp_error( $product_review ) ) {
|
||||
return $product_review;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -149,6 +149,11 @@ class WC_REST_Product_Reviews_Controller extends WC_REST_Controller {
|
|||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_item_permissions_check( $request ) {
|
||||
$review = $this->get_review( (int) $request['id'] );
|
||||
if ( is_wp_error( $review ) ) {
|
||||
return $review;
|
||||
}
|
||||
|
||||
if ( ! wc_rest_check_product_reviews_permissions( 'read', (int) $request['id'] ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
@ -177,6 +182,11 @@ class WC_REST_Product_Reviews_Controller extends WC_REST_Controller {
|
|||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function update_item_permissions_check( $request ) {
|
||||
$review = $this->get_review( (int) $request['id'] );
|
||||
if ( is_wp_error( $review ) ) {
|
||||
return $review;
|
||||
}
|
||||
|
||||
if ( ! wc_rest_check_product_reviews_permissions( 'edit', (int) $request['id'] ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you cannot edit this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
@ -191,6 +201,11 @@ class WC_REST_Product_Reviews_Controller extends WC_REST_Controller {
|
|||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function delete_item_permissions_check( $request ) {
|
||||
$review = $this->get_review( (int) $request['id'] );
|
||||
if ( is_wp_error( $review ) ) {
|
||||
return $review;
|
||||
}
|
||||
|
||||
if ( ! wc_rest_check_product_reviews_permissions( 'delete', (int) $request['id'] ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_delete', __( 'Sorry, you cannot delete this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
@ -1057,13 +1072,11 @@ class WC_REST_Product_Reviews_Controller extends WC_REST_Controller {
|
|||
}
|
||||
|
||||
$review = get_comment( $id );
|
||||
if ( empty( $review ) ) {
|
||||
if ( empty( $review ) || 'review' !== get_comment_type( $id ) ) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
if ( ! empty( $review->comment_post_ID ) ) {
|
||||
$post = get_post( (int) $review->comment_post_ID );
|
||||
|
||||
if ( 'product' !== get_post_type( (int) $review->comment_post_ID ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_product_invalid_id', __( 'Invalid product ID.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const { test, expect } = require( '@playwright/test' );
|
||||
const { API_BASE_URL } = process.env;
|
||||
const shouldSkip = API_BASE_URL != undefined;
|
||||
const shouldSkip = API_BASE_URL !== undefined;
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -717,12 +717,7 @@ test.describe( 'Products API tests: CRUD', () => {
|
|||
const getDeletedProductReviewResponse = await request.get(
|
||||
`wp-json/wc/v3/products/reviews/${ productReviewId }`
|
||||
);
|
||||
/**
|
||||
* currently returns a 403 (forbidden) rather than a 404 (not found)
|
||||
* an issue has been raised to track this
|
||||
* See: https://github.com/woocommerce/woocommerce/issues/35162
|
||||
*/
|
||||
expect( getDeletedProductReviewResponse.status() ).toEqual( 403 );
|
||||
expect( getDeletedProductReviewResponse.status() ).toEqual( 404 );
|
||||
} );
|
||||
|
||||
test( 'can batch update product reviews', async ( { request } ) => {
|
||||
|
@ -817,12 +812,7 @@ test.describe( 'Products API tests: CRUD', () => {
|
|||
const getDeletedProductReviewResponse = await request.get(
|
||||
`wp-json/wc/v3/products/reviews/${ review2Id }`
|
||||
);
|
||||
/**
|
||||
* currently returns a 403 (forbidden) rather than a 404 (not found)
|
||||
* an issue has been raised to track this
|
||||
* See: https://github.com/woocommerce/woocommerce/issues/35162
|
||||
*/
|
||||
expect( getDeletedProductReviewResponse.status() ).toEqual( 403 );
|
||||
expect( getDeletedProductReviewResponse.status() ).toEqual( 404 );
|
||||
|
||||
// Batch delete the created tags
|
||||
await request.post( `wp-json/wc/v3/products/reviews/batch`, {
|
||||
|
@ -1534,12 +1524,9 @@ test.describe( 'Products API tests: CRUD', () => {
|
|||
// Send request to batch delete the products created earlier
|
||||
const idsToDelete = expectedProducts.map( ( { id } ) => id );
|
||||
const batchDeletePayload = batch( 'delete', idsToDelete );
|
||||
const response = await request.post(
|
||||
'wp-json/wc/v3/products/batch',
|
||||
{
|
||||
data: batchDeletePayload,
|
||||
}
|
||||
);
|
||||
let response = await request.post( 'wp-json/wc/v3/products/batch', {
|
||||
data: batchDeletePayload,
|
||||
} );
|
||||
const responseJSON = await response.json();
|
||||
const actualBatchDeletedProducts = responseJSON.delete;
|
||||
|
||||
|
@ -1556,7 +1543,7 @@ test.describe( 'Products API tests: CRUD', () => {
|
|||
|
||||
// Verify that the deleted product ID's can no longer be retrieved
|
||||
for ( const id of idsToDelete ) {
|
||||
const response = await request.get(
|
||||
response = await request.get(
|
||||
`wp-json/wc/v3/products/${ id }`
|
||||
);
|
||||
expect( response.status() ).toEqual( 404 );
|
||||
|
|
|
@ -75,6 +75,7 @@ class WC_REST_Product_Reviews_V1_Controller_Tests extends WC_Unit_Test_Case {
|
|||
*/
|
||||
public function test_permissions_for_updating_product_reviews() {
|
||||
$api_request = new WP_REST_Request( 'PUT', '/wc/v1/products/' . $this->product_id . '/reviews/' . $this->review_id );
|
||||
$api_request->set_param( 'product_id', $this->product_id );
|
||||
$api_request->set_param( 'id', $this->review_id );
|
||||
$api_request->set_body( '{ "review": "Modified automatically." }' );
|
||||
|
||||
|
@ -93,6 +94,7 @@ class WC_REST_Product_Reviews_V1_Controller_Tests extends WC_Unit_Test_Case {
|
|||
|
||||
$nonexistent_product_id = $this->product_id * 10;
|
||||
$api_request->set_route( "/wc/v1/products/{$nonexistent_product_id}/reviews/" . $this->review_id );
|
||||
$api_request->set_param( 'product_id', $nonexistent_product_id );
|
||||
|
||||
$this->assertEquals(
|
||||
'woocommerce_rest_product_invalid_id',
|
||||
|
@ -146,8 +148,8 @@ class WC_REST_Product_Reviews_V1_Controller_Tests extends WC_Unit_Test_Case {
|
|||
$request->set_param( 'id', $order_note_id );
|
||||
|
||||
$this->assertEquals(
|
||||
'woocommerce_rest_cannot_delete',
|
||||
$this->sut->delete_item_permissions_check( $request )->get_error_code(),
|
||||
'woocommerce_rest_product_invalid_id',
|
||||
$this->sut->delete_item( $request )->get_error_code(),
|
||||
'Comments that are not product reviews cannot be deleted via this endpoint.'
|
||||
);
|
||||
|
||||
|
@ -163,8 +165,8 @@ class WC_REST_Product_Reviews_V1_Controller_Tests extends WC_Unit_Test_Case {
|
|||
$request->set_param( 'id', $comment_id );
|
||||
|
||||
$this->assertEquals(
|
||||
'woocommerce_rest_cannot_delete',
|
||||
$this->sut->delete_item_permissions_check( $request )->get_error_code(),
|
||||
'woocommerce_rest_product_invalid_id',
|
||||
$this->sut->delete_item( $request )->get_error_code(),
|
||||
'Comments that are not product reviews (including other types of comments belonging to products) cannot be deleted via this endpoint.'
|
||||
);
|
||||
}
|
||||
|
|
|
@ -178,8 +178,8 @@ class WC_REST_Product_Reviews_Controller_Tests extends WC_REST_Unit_Test_Case {
|
|||
$request->set_param( 'id', $order_note_id );
|
||||
|
||||
$this->assertEquals(
|
||||
'woocommerce_rest_cannot_delete',
|
||||
$this->sut->delete_item_permissions_check( $request )->get_error_code(),
|
||||
'woocommerce_rest_review_invalid_id',
|
||||
$this->sut->delete_item( $request )->get_error_code(),
|
||||
'Comments that are not product reviews cannot be deleted via this endpoint.'
|
||||
);
|
||||
|
||||
|
@ -195,8 +195,8 @@ class WC_REST_Product_Reviews_Controller_Tests extends WC_REST_Unit_Test_Case {
|
|||
$request->set_param( 'id', $comment_id );
|
||||
|
||||
$this->assertEquals(
|
||||
'woocommerce_rest_cannot_delete',
|
||||
$this->sut->delete_item_permissions_check( $request )->get_error_code(),
|
||||
'woocommerce_rest_review_invalid_id',
|
||||
$this->sut->delete_item( $request )->get_error_code(),
|
||||
'Comments that are not product reviews (including other types of comments belonging to products) cannot be deleted via this endpoint.'
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue