GraphQl - 如何将当前用户添加到变异对象
GraphQl - how to add current user to mutation object
我正在尝试根据 the documentation.
通过装饰 graphql 阶段将当前用户添加到 create
突变
这是一个允许用户在消息系统中屏蔽其他用户的功能,仅供参考。
需要满足以下访问控制:
"access_control"="is_granted('IS_AUTHENTICATED_FULLY') and object.getBlocker() == user"
这意味着阻止的用户是当前经过身份验证的用户。
只要把上面的修改为:
就可以搞定
"access_control"="is_granted('IS_AUTHENTICATED_FULLY')"
像这样装饰 deserialize stage
:
App/Stage/DeserializeStage
/**
* @param object|null $objectToPopulate
*
* @return object|null
*/
public function __invoke($objectToPopulate, string $resourceClass, string $operationName, array $context)
{
// Call the decorated serialized stage (this syntax calls the __invoke method).
$deserializeObject = ($this->deserializeStage)($objectToPopulate, $resourceClass, $operationName, $context);
if ($resourceClass === 'App\Entity\BlockedUser' && $operationName === 'create') {
$user = $this->tokenStorage->getToken()->getUser();
$deserializeObject->setBlocker($user);
}
return $deserializeObject;
}
据我所知,为了让它完全满足访问控制的要求,我需要修饰 read stage
,它位于 security stage
之前,并插入当前经过身份验证的用户到对象。
这样就满足了访问控制的第二部分,即
and object.getBlocker() == user
我试图按如下方式进行,但我得到了一个 NULL
对象:
App/Stage/ReadStage
/**
* @return object|iterable|null
*/
public function __invoke(?string $resourceClass, ?string $rootClass, string $operationName, array $context)
{
$readObject = ($this->readStage)($resourceClass, $rootClass, $operationName, $context);
var_dump($readObject->getBlocked()->getUsername()); // throws error 'method getBlocked on NULL
if ($resourceClass === 'App\Entity\BlockedUser' && $operationName === 'create') {
$userId = $this->tokenStorage->getToken()->getUser();
$readObject->setBlocker($user);
}
return $readObject;
}
好吧,在重新启动应用程序后,它似乎在 deserialize
阶段正常工作。可能是缓存或其他问题。
我仍然不确定它为什么在 deserialize
阶段工作,也不确定那是否是修改对象的正确位置。
无论如何,它都按原样工作,所以...
所以,我发布了完整的代码以供参考。
App/Stage/DeserializeStage
<?php
namespace App\Stage;
use ApiPlatform\Core\GraphQl\Resolver\Stage\DeserializeStageInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
final class DeserializeStage implements DeserializeStageInterface
{
private $deserializeStage;
/**
* @var TokenStorageInterface
*/
private $tokenStorage;
public function __construct(
DeserializeStageInterface $deserializeStage,
TokenStorageInterface $tokenStorage)
{
$this->deserializeStage = $deserializeStage;
$this->tokenStorage = $tokenStorage;
}
/**
* @param object|null $objectToPopulate
*
* @return object|null
*/
public function __invoke($objectToPopulate, string $resourceClass, string $operationName, array $context)
{
// Call the decorated serialized stage (this syntax calls the __invoke method).
$deserializeObject = ($this->deserializeStage)($objectToPopulate, $resourceClass, $operationName, $context);
if ($resourceClass === 'App\Entity\BlockedUser' && $operationName === 'create') {
$user = $this->tokenStorage->getToken()->getUser();
$deserializeObject->setBlocker($user);
}
return $deserializeObject;
}
}
并且您需要将其添加到 config/services.yaml
App\Stage\DeserializeStage:
decorates: api_platform.graphql.resolver.stage.deserialize
我正在尝试根据 the documentation.
通过装饰 graphql 阶段将当前用户添加到create
突变
这是一个允许用户在消息系统中屏蔽其他用户的功能,仅供参考。
需要满足以下访问控制:
"access_control"="is_granted('IS_AUTHENTICATED_FULLY') and object.getBlocker() == user"
这意味着阻止的用户是当前经过身份验证的用户。
只要把上面的修改为:
就可以搞定"access_control"="is_granted('IS_AUTHENTICATED_FULLY')"
像这样装饰 deserialize stage
:
App/Stage/DeserializeStage
/**
* @param object|null $objectToPopulate
*
* @return object|null
*/
public function __invoke($objectToPopulate, string $resourceClass, string $operationName, array $context)
{
// Call the decorated serialized stage (this syntax calls the __invoke method).
$deserializeObject = ($this->deserializeStage)($objectToPopulate, $resourceClass, $operationName, $context);
if ($resourceClass === 'App\Entity\BlockedUser' && $operationName === 'create') {
$user = $this->tokenStorage->getToken()->getUser();
$deserializeObject->setBlocker($user);
}
return $deserializeObject;
}
据我所知,为了让它完全满足访问控制的要求,我需要修饰 read stage
,它位于 security stage
之前,并插入当前经过身份验证的用户到对象。
这样就满足了访问控制的第二部分,即
and object.getBlocker() == user
我试图按如下方式进行,但我得到了一个 NULL
对象:
App/Stage/ReadStage
/**
* @return object|iterable|null
*/
public function __invoke(?string $resourceClass, ?string $rootClass, string $operationName, array $context)
{
$readObject = ($this->readStage)($resourceClass, $rootClass, $operationName, $context);
var_dump($readObject->getBlocked()->getUsername()); // throws error 'method getBlocked on NULL
if ($resourceClass === 'App\Entity\BlockedUser' && $operationName === 'create') {
$userId = $this->tokenStorage->getToken()->getUser();
$readObject->setBlocker($user);
}
return $readObject;
}
好吧,在重新启动应用程序后,它似乎在 deserialize
阶段正常工作。可能是缓存或其他问题。
我仍然不确定它为什么在 deserialize
阶段工作,也不确定那是否是修改对象的正确位置。
无论如何,它都按原样工作,所以...
所以,我发布了完整的代码以供参考。
App/Stage/DeserializeStage
<?php
namespace App\Stage;
use ApiPlatform\Core\GraphQl\Resolver\Stage\DeserializeStageInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
final class DeserializeStage implements DeserializeStageInterface
{
private $deserializeStage;
/**
* @var TokenStorageInterface
*/
private $tokenStorage;
public function __construct(
DeserializeStageInterface $deserializeStage,
TokenStorageInterface $tokenStorage)
{
$this->deserializeStage = $deserializeStage;
$this->tokenStorage = $tokenStorage;
}
/**
* @param object|null $objectToPopulate
*
* @return object|null
*/
public function __invoke($objectToPopulate, string $resourceClass, string $operationName, array $context)
{
// Call the decorated serialized stage (this syntax calls the __invoke method).
$deserializeObject = ($this->deserializeStage)($objectToPopulate, $resourceClass, $operationName, $context);
if ($resourceClass === 'App\Entity\BlockedUser' && $operationName === 'create') {
$user = $this->tokenStorage->getToken()->getUser();
$deserializeObject->setBlocker($user);
}
return $deserializeObject;
}
}
并且您需要将其添加到 config/services.yaml
App\Stage\DeserializeStage:
decorates: api_platform.graphql.resolver.stage.deserialize