The implementation of RequestBodyParamConverter seems so "naive", hope that is my bad configuration or something. It works fine when you don't provide entity identifiers in the body payload, but is potentially dangerous when you do.
Consider this scenario: a POST request to /api/products in order to create a new entity:
In this scenario, the converter deserialized the provided payload. In turn, the JMS serializer would retrive the existing record with the given id, and merge the name property. Without any futher control, you end up updating the resource instead of creating a new one!
Even worst example: a PUT to/products/1 request with { "id": 2, "name": "Foo Bar" } as payload, which is supposed to replace the resource at the id 1. In this case it would end up updating the wrong resource!
This is an example controller action:
/**
* Creates a new product.
*
* @Rest\Post("/products", name="_api_products_create")
* @ParamConverter("product", class=Product::class, converter="fos_rest.request_body")
* @Rest\View(statusCode=Response::HTTP_OK)
*/
public function createAction(Product $product, ConstraintViolationListInterface $violations)
{
if (count($violations)) {
return $this->view($violations, Response::HTTP_BAD_REQUEST);
}
$em = $this->getDoctrine()->getManagerForClass($product);
$em->persist($product);
$em->flush();
return $product;
}
The implementation of
RequestBodyParamConverter
seems so "naive", hope that is my bad configuration or something. It works fine when you don't provide entity identifiers in the body payload, but is potentially dangerous when you do.Consider this scenario: a
POST
request to/api/products
in order to create a new entity:In this scenario, the converter deserialized the provided payload. In turn, the JMS serializer would retrive the existing record with the given
id
, and merge thename
property. Without any futher control, you end up updating the resource instead of creating a new one!Even worst example: a
PUT
to/products/1
request with{ "id": 2, "name": "Foo Bar" }
as payload, which is supposed to replace the resource at the id1
. In this case it would end up updating the wrong resource!This is an example controller action: