api-platform icon indicating copy to clipboard operation
api-platform copied to clipboard

Problem with new ApiProperty security

Open VincentDugard opened this issue 4 years ago • 5 comments

API Platform version(s) affected: 2.6.1

Description

I have this property in my User entity

image

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).

VincentDugard avatar Feb 05 '21 09:02 VincentDugard

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.

mbrodala avatar Mar 17 '21 13:03 mbrodala

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.

yobud avatar May 04 '21 20:05 yobud

Also, on a collection, in my case, object is a doctrine-paginator instance. Thats very unexpected, i think.

dennobaby avatar Nov 02 '21 07:11 dennobaby

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.

mbrodala avatar Feb 21 '22 09:02 mbrodala

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.

mbrodala avatar Feb 21 '22 09:02 mbrodala