【问题标题】:How can I use Laravel Policies to filter list responses from GraphQL?如何使用 Laravel 策略过滤来自 GraphQL 的列表响应?
【发布时间】:2020-08-23 18:58:36
【问题描述】:

我想根据模型策略中的视图方法过滤(不阻止访问)从我的 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);
    }
}

【问题讨论】:

    标签: laravel-lighthouse


    【解决方案1】:

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

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

    【讨论】:

      猜你喜欢
      • 2019-02-06
      • 1970-01-01
      • 1970-01-01
      • 2012-06-29
      • 2014-08-29
      • 1970-01-01
      • 1970-01-01
      • 2021-02-21
      • 1970-01-01
      相关资源
      最近更新 更多