2

我想根据模型策略中的视图方法过滤(不阻止访问)从我的 GraphQL API 返回的列表字段。

我已经编写了下面的指令,我已将其添加到我的架构中的字段中。

我有两个问题:

  1. 这不是实现我想要的结果的最佳方式,因为我必须注释我的模式中获取关系的每个字段。有一个更好的方法吗?

  2. 我在下面的解决方案有一个不起作用的边缘情况。返回过滤后的集合时,它不会加载架构中请求的对象上的嵌套字段。理想情况下,这将是递归的,对集合中的所有项目及其所有子字段使用相同的解析器。我怎样才能使这项工作?

class ViewPolicyFilterDirective extends BaseDirective implements FieldMiddleware {
    /**
     * Filters GraphQL list fields using Policies 'view' method
     *
     * @param \Nuwave\Lighthouse\Schema\Values\FieldValue $fieldValue
     * @param \Closure $next
     * @return \Nuwave\Lighthouse\Schema\Values\FieldValue
     */
    public function handleField(FieldValue $fieldValue, Closure $next): FieldValue {
        // Retrieve the existing resolver function
        /** @var Closure $previousResolver */
        $previousResolver = $fieldValue->getResolver();

        // Wrap around the resolver
        $wrappedResolver = function ($root, array $args, GraphQLContext $context, ResolveInfo $info) use ($previousResolver) {
            // Call the resolver, passing along the resolver arguments
            $result = $previousResolver($root, $args, $context, $info);
            if ($result instanceof Collection && $result->count() > 0 && $result[0] instanceof Model) {
                return $result->filter(function (Model $r) {
                    return Auth::user()->can('view', $r);
                })->toArray();
            } else if ($result instanceof Model && Auth::user()->can('view', $result)) {
                return $result;
            } else if ($result instanceof Model && !Auth::user()->can('view', $result)) {
                throw new AuthorizationException(
                    "You are not authorized to access this"
                );
            }
            return $result;
        };

        // Place the wrapped resolver back upon the FieldValue
        // It is not resolved right now - we just prepare it
        $fieldValue->setResolver($wrappedResolver);

        // Keep the middleware chain going
        return $next($fieldValue);
    }
}
4

1 回答 1

0

我建议您改用范围。
所以基本上创建一个范围来过滤掉所有你不需要的模型。

通过这种方式,您可以使用 lighthouse 的内置指令,并利用我们所有的 Lighthouse 逻辑来获取子关系等。

于 2020-12-09T09:59:36.650 回答