微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

苦艾酒-如何在解析器功能中放置put_session?

如何解决苦艾酒-如何在解析器功能中放置put_session?

我正在使用苦艾酒,并且有突变迹象。当用户发送有效凭据时,我想通过put_session在响应中设置会话cookie。

我面临的问题是我无法从解析器函数中访问conn。这告诉我,我不应该从解析器中更新连接的属性

用苦艾酒可以做到这一点吗?有哪些替代解决方案?

解决方法

不确定您为什么要使用会话,使用承载不能解决此问题吗?

请忽略接口。 :-)

突变。

  object :user_token_payload do
    field(:user,:user)
    field(:token,:string)
  end

  object :login_user_mutation_response,is_type_of: :login_user do
    interface(:straw_hat_mutation_response)

    field(:errors,list_of(:straw_hat_error))
    field(:successful,non_null(:boolean))
    field(:payload,:user_token_payload)
  end

解析器。

  def authenticate_user(args,_) do
    case Accounts.authenticate_user(args) do
      {:ok,user,token} -> MutationResponse.succeeded(%{user: user,token: token})
      {:error,message} -> MutationResponse.failed(StrawHat.Error.new(message))
    end
  end

现在,客户端可以将令牌与Authorization标头一起传递,并使用插件将其提取。

defmodule MyAppWeb.Plugs.Context do
  import Plug.Conn
  alias MyApp.Admission

  def init(opts),do: opts

  def call(conn,_) do
    case build_context(conn) do
      {:ok,context} -> put_private(conn,:absinthe,%{context: context})
      _ -> put_private(conn,%{context: %{}})
    end
  end

  @doc """
  Return the current user context based on the authorization header
  """
  def build_context(conn) do
    auth_header =
      get_req_header(conn,"authorization")
      |> List.first()

    if auth_header do
      "Bearer " <> token = auth_header

      case Admission.get_token_by_hash(token) do
        nil -> :error
        token -> {:ok,%{current_user: token.user}}
      end
    else
      :error
    end
  end
end

然后将插件添加到您的管道

plug(MyApp.Plugs.Context)

然后,您可以像这样在解析器中选择当前用户。

  def create_note(%{input: input},%{context: %{current_user: user}}) do
  end
,

似乎一种解决方案是:

  1. 在解析器中,正常解析{:ok,_}{:error,_}
  2. 添加middleware after the resolver来与resolution.value从步骤1返回的模式匹配并更新GraphQL上下文
  3. 使用苦艾酒的before_send功能(该功能可以在发送响应之前访问GraphQL上下文和与put_session的连接

代码示例

突变:

mutation do
  @desc "Authenticate a user."
  field :login,:user do
    arg(:email,non_null(:string))
    arg(:password,non_null(:string))
    resolve(&Resolvers.Accounts.signin/3)

    middleware(fn resolution,_ ->
      case resolution.value do
        %{user: user,auth_token: auth_token} ->
          Map.update!(
            resolution,:context,&Map.merge(&1,%{auth_token: auth_token,user: user})
          )

        _ ->
          resolution
      end
    end)
  end
end

解析器:

defmodule AppWeb.Resolvers.Accounts do
  alias App.Accounts

  def signin(_,%{email: email,password: password},_) do
    if user = Accounts.get_user_by_email_and_password(email,password) do
      auth_token = Accounts.generate_user_session_token(user)
      {:ok,%{user: user,auth_token: auth_token}}
    else
      {:error,"Invalid credentials."}
    end
  end
end

路由器:

defmodule AppWeb.Router do
  use AppWeb,:router

  pipeline :api do
    plug(:accepts,["json"])
    plug(:fetch_session)
  end

  scope "/" do
    pipe_through(:api)

    forward("/api",Absinthe.Plug,schema: AppWeb.Schema,before_send: {__MODULE__,:absinthe_before_send}
    )

    forward("/graphiql",Absinthe.Plug.GraphiQL,:absinthe_before_send}
    )
  end

  def absinthe_before_send(conn,%Absinthe.Blueprint{} = blueprint) do
    if auth_token = blueprint.execution.context[:auth_token] do
      put_session(conn,:auth_token,auth_token)
    else
      conn
    end
  end

  def absinthe_before_send(conn,_) do
    conn
  end
end

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?