如何解决苦艾酒-如何在解析器功能中放置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
,
似乎一种解决方案是:
- 在解析器中,正常解析
{:ok,_}
或{:error,_}
- 添加middleware after the resolver来与
resolution.value
从步骤1返回的模式匹配并更新GraphQL上下文 - 使用苦艾酒的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 举报,一经查实,本站将立刻删除。