ApiPlatform - collectionOperations 未在选民上传递支持方法
ApiPlatform - collectionOperations not passing support method on voter
我使用 Symfony5
和 ApiPlaform
我遇到了一个小问题,但我找不到任何材料来帮助我解决这个问题
所以,我有一个对 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 则抛出异常。此方法会对性能产生负面影响。
这是我的规范化器的例子
归一化方法:
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))
);
}
我使用 Symfony5
和 ApiPlaform
我遇到了一个小问题,但我找不到任何材料来帮助我解决这个问题
所以,我有一个对 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 则抛出异常。此方法会对性能产生负面影响。
这是我的规范化器的例子
归一化方法:
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))
);
}