Graphql Absinthe基于Elixir权限的可访问字段

定义所有用户可能无法访问的字段的正确方法是什么.

例如,普通用户可以查询用户并查找其他用户句柄,但只有管理员用户才能找到他们的电子邮件地址.用户类型将其定义为字段,但可能无法访问.是否应该有一般用户可以看到的单独类型?你会如何定义它?

对不起,如果不是那么清楚,我就是不具备词汇量.

最佳答案
编辑:警告:Graphql documentation不同意这种方法.谨慎使用.无论您需要私有字段,都必须包含适当的中间件.

使用absinthe middleware.

这是一些代码如何做到这一点.在此示例中,经过身份验证的用户可以查看电子邮件地址.匿名用户不能.您可以调整逻辑以要求您需要的任何权限.

defmodule MySite.Middleware.RequireAuthenticated do
  @behaviour Absinthe.Middleware

  @moduledoc """
  Middleware to require authenticated user
  """

  def call(resolution, config) do
    case resolution.context do
      %{current_user: _} ->
        resolution
      _ ->
        Absinthe.Resolution.put_result(resolution, {:error, "unauthenticated"})
    end
  end
end

然后你定义你的对象:

  object :user do
    field :id, :id
    field :username, :string 
    field :email, :string do
      middleware MySite.Middleware.RequireAuthenticated
      middleware Absinthe.Middleware.MapGet, :email
    end
  end

因此,我们的现场电子邮件受RequireAuthenticated中间件保护.但根据上面的链接

One use of middleware/3 is setting the default middleware on a field,
replacing the default_resolver macro.

通过在字段上使用中间件/ 2宏也会发生这种情况.这就是我们需要添加的原因

  middleware Absinthe.Middleware.MapGet, :email

到该领域的中间件列表.

最后,当我们执行查询时

query {
  user(id: 1){
    username
    email
    id
  }
}

我们得到响应,填充的开放字段和受保护的字段无效

{
  "errors": [
    {
      "message": "In field \"email\": unauthenticated",
      "locations": [
        {
          "line": 4,
          "column": 0
        }
      ]
    }
  ],
  "data": {
    "user": {
      "username": "MyAwesomeUsername",
      "id": "1",
      "email": null
    }
  }
}

您还可以使用中间件/ 3回调,因此您的对象不会太冗长

  def middleware(middleware, %{identifier: :email} = field, _object) do
    [MySite.Middleware.RequireAuthenticated] ++
      [{Absinthe.Middleware.MapGet, :email}] ++
      middleware
  end

通过对__using __ / 1回调的一些创造性使用,您可以从主模式文件中获取大量此类函数.

转载注明原文:Graphql Absinthe基于Elixir权限的可访问字段 - 代码日志