GraphQl-如何将当前用户添加到变异对象

时间:2019-12-24 07:43:10

标签: graphql symfony4 api-platform.com

我正在尝试通过根据the documentation装饰graphql阶段,将当前用户添加到create突变中。

此功能允许用户阻止邮件系统fyi中的其他用户。

它应满足以下访问控制:

"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;
}

1 个答案:

答案 0 :(得分:0)

好吧,重新启动应用程序后,它似乎在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