ApiPlatform - collectionOperations 未在选民上传递支持方法

ApiPlatform - collectionOperations not passing support method on voter

我使用 Symfony5ApiPlaform

我遇到了一个小问题,但我找不到任何材料来帮助我解决这个问题

所以,我有一个对 API 开放的实体,我想从中恢复

的列表

我自然而然地设置了 collectionOperations :

 *     collectionOperations={
 *          "get"={
 *              "mehtod"="GET",
 *              "security"="is_granted('LIST', object)",
 *              "normalization_context"={"groups"={"user:list"}},
 *          }
 *     },

然后用 supports 方法检查我的选民内部:

    protected function supports($attribute, $subject): bool
    {
        return parent::supports($attribute, $subject)
            && (
                $subject instanceof User
                || $this->arrayOf($subject, User::class)
            );
    }

我认为 arrayOf 条件会检查对象列表,但我收到了一个分页对象,因此只能检查它是否是一个分页对象,这可能会给我的其他选民带来问题。 无论如何 return 我的 Paginator 对象在 voteOnAttribute 方法中(已经尝试过)

所以我的问题是,有没有办法通过将注释中的对象发送给选民来检查对象列表的授权?

谢谢!

collection操作不会通过你的User::class。 (它可能会像分页器一样通过某事)。

方式 1:过滤您的 collection

您可以通过为用户更改 query-builder 来过滤您的 collection。 见 https://api-platform.com/docs/core/extensions/

方式二:自定义标准化器

您可以在自定义规范器中检查安全性并更改 serialization_context 或如果用户无权访问 object 则抛出异常。此方法会对性能产生负面影响。

https://api-platform.com/docs/core/serialization/#changing-the-serialization-context-on-a-per-item-basis

这是我的规范化器的例子

归一化方法:


    public function normalize($object, string $format = null, array $context = []): array
    {
        $context['groups'] = []; //remove all groups
        $context['groups'][] = 'read:always';
        
        if ($this->security->isGranted('ENTITY_ACCESS', $object)) {
            $context['groups'][] = 'read'; //allow to read properties with @Groups{{"read"}}
        } else {
            throw new ClientError(ClientErrorType::CHECK_ACCESS, ['type' => $this->getEntityName($object)]);
        }

        $context['groups'] = array_unique($context['groups']);
        $context['resource_normalizer_call_data'][] = $object->getId();
        return $this->normalizer->normalize($object, $format, $context);
    }

支持归一化方法

    public function supportsNormalization($data, string $format = null, array $context = []): bool
    {

        if ( //is object doctrine entity?
            !$this->isEntity($this->managerRegistry->getManager(), $data)
            || !isset($context['graphql_operation_name'])

        ) {
            return false;
        }

        if ( //dont normalize same entity twice! 
            isset($context['resource_normalizer_call_data'])
            && in_array($data->getId(), $context['resource_normalizer_call_data'])
        ) {
            return false;
        }

        return true;
    }

我通过如下检查查询结果的类型找到了适合我的解决方法:

    protected function supports($attribute, $subject): bool
    {
        return parent::supports($attribute, $subject)
            && (
                $subject instanceof User ||
                $this->arrayOf($subject, User::class) ||
                (is_a($subject, Paginator::class) &&
                    is_a(iterator_to_array($subject->getIterator())[0], User::class))

            );
    }