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