Problem with new ApiProperty security
API Platform version(s) affected: 2.6.1
Description
I have this property in my User entity

The entity User have a manager that can access this property.
This code works for GET request, however for PUT or PATCH request I get this error
Unable to get a property on a non-object.
I don't see why this wouldn't work so I think it's a bug
edit : I did more research and it looks like "object" value is "App\Entity\User" and not the User object
How to reproduce
Access a property of "object" in @ApiProperty security feature (see code above).
I can confirm this issue. So technically the example given in the docs can actually not work:
/**
* Secured resource.
*
* @ApiResource(
* attributes={"security"="is_granted('ROLE_USER')"},
* collectionOperations={
* "get",
* "post"={"security"="is_granted('ROLE_ADMIN')"}
* },
* itemOperations={
* "get",
* "put"={"security"="is_granted('ROLE_ADMIN') or object.owner == user"},
* }
* )
* @ORM\Entity
*/
Here object can be an instance of Book or just the FQCN of Book.
We noticed this issue in our API tests where the processing of the request seems rather different and thus causes denormalization compared to normalization.
Also, shouldn't we be able to specify different security for reading and writing?
I mean, when you make a PUT, returned result might contain others fields (readonly for your security context) than the ones you sent.
Also, on a collection, in my case, object is a doctrine-paginator instance. Thats very unexpected, i think.
A possible hotfix would be this:
--- src/Serializer/AbstractItemNormalizer.php 2022-02-21 09:58:43.996978817 +0100
+++ src/Serializer/AbstractItemNormalizer.php 2022-02-21 09:57:44.872673911 +0100
@@ -372,6 +372,7 @@
{
$options = $this->getFactoryOptions($context);
$propertyNames = $this->propertyNameCollectionFactory->create($context['resource_class'], $options);
+ $classOrObject = $context[self::OBJECT_TO_POPULATE] ?? $classOrObject;
$allowedAttributes = [];
foreach ($propertyNames as $propertyName) {
See https://github.com/api-platform/core/blob/119b05b631aae94a922838c6c3ba2f64618210a5/src/Serializer/AbstractItemNormalizer.php#L416
The object is actually there but not forwarded here. Generally it's rather obscure why Symfony Serializer itself already supports an object or FQCN here.
Also see https://github.com/api-platform/docs/pull/1351, https://github.com/api-platform/docs/pull/1349 and https://github.com/api-platform/core/pull/4184 which are related.