我正在使用苦艾酒并且有一个突变的迹象。当用户通过有效凭据发送时,我想通过在响应中设置会话 cookie put_session
。
我面临的问题是我无法conn
从解析器函数中访问。这告诉我,我不应该从解析器中更新连接的属性。
用苦艾酒可以做到这一点吗?有哪些替代解决方案?
我正在使用苦艾酒并且有一个突变的迹象。当用户通过有效凭据发送时,我想通过在响应中设置会话 cookie put_session
。
我面临的问题是我无法conn
从解析器函数中访问。这告诉我,我不应该从解析器中更新连接的属性。
用苦艾酒可以做到这一点吗?有哪些替代解决方案?
{:ok, _}
或 an{:error, _}
resolution.value
并更新 GraphQL 上下文put_session
功能(在发送响应之前可以访问 GraphQL 上下文和连接突变:
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,
schema: AppWeb.Schema,
before_send: {__MODULE__, :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
不知道为什么要使用会话,这不能使用承载来解决吗?
请忽略接口。:-)
突变。
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, :absinthe, %{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