我想从服务器端找出当前用户。 user_controller模块显示如何返回current_user以响应客户端请求。但是我很难从服务器上的另一个模块中找到如何做到这一点。
以下是我尝试但失败并出现以下错误。基本上我复制了user_controller.ex中的Guardian.Plug代码块。
正确的方法是什么?
(CompileError) web/GraphQLSession.ex:9: undefined function put_status/2
(stdlib) lists.erl:1337: :lists.foreach/2
(stdlib) erl_eval.erl:669: :erl_eval.do_apply/6
defmodule App.GraphQLSession do
use Guardian.Hooks
def root_eval(_conn) do
current_user =
case Guardian.Plug.current_resource(_conn) do
nil ->
_conn
|> put_status(:not_found)
|> render(App.V1.SessionView, "error.json", error: "User not found")
user ->
_conn
|> put_status(:ok)
|> render("show.json", user: user)
end
%{author: current_user}
end
end
<<<<< router.ex>>>>
defmodule App.Router do
use App.Web, :router
...
pipeline :api do
plug :accepts, ["json"]
plug Guardian.Plug.VerifyHeader
plug Guardian.Plug.LoadResource
end
scope "/graphql" do
pipe_through :api
forward "/", GraphQL.Plug, [schema: {App.PublicSchema, :schema}, root_value: {App.GraphQLSession, :root_eval} ]
end
<<<< user_controller.ex>> ....这显示了客户端如何通过控制器检索current_user。
defmodule App.V1.UserController do
use App.Web, :controller
alias App.User
plug Guardian.Plug.EnsureAuthenticated, on_failure: { App.V1.SessionController, :unauthenticated_api }
plug :scrub_params, "user" when action in [:create, :update]
def current_user(conn, %{"jwt" => jwt}) do
case Guardian.Plug.current_resource(conn) do
nil ->
conn
|> put_status(:not_found)
|> render(App.V1.SessionView, "error.json", error: "User not found")
user ->
conn
|> put_status(:ok)
|> render("show.json", user: user)
end
更新:导入Plug.Conn并将_conn更改为conn后,根据David Sulc的建议,我得到的下一个错误如下:
[error] #PID<0.1026.0> running App.Endpoint terminated
Server: localhost:4000 (http)
Request: POST /graphql
** (exit) an exception was raised:
** (Protocol.UndefinedError) protocol Enumerable not implemented for %Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}, assigns: %{error: "User not found", guardian_default_resource: nil, layout:
false}, before_send: [#Function<1.34093945/1 in Plug.Logger.call/2>, #Function<0.30221299/1 in Phoenix.LiveReloader.before_send_inject_reloader/1>], body_params: %{"query" => "mutation CreateMutation(
$input_0:CreateInput!){createQ(input:$input_0){clientMutationId,...F3}} fragment F0 on ...}
}}, cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false, host: "localhost", method: "POST", owner: #PID<0.1026.0>, params: %{"query" => "mutation ....}}}, path_info: [], peer: {{1
27, 0, 0, 1}, 50944}, port: 4000, private: %{App.Router => {[], %{GraphQL.Plug => []}}, :phoenix_endpoint => App.Endpoint, :phoenix_format => "json", :phoenix_pipelines => [:api], :phoenix_route => #Funct
ion<0.58758354/1 in App.Router.match_route/4>, :phoenix_router => App.Router, :phoenix_template => "error.json", :phoenix_view => App.V1.SessionView, :plug_session_fetch => #Function<0.29336444/1 in Plug.
Session.fetch_session/1>}, query_params: %{}, query_string: "", remote_ip: {127, 0, 0, 1}, req_cookies: %Plug.Conn.Unfetched{aspect: :cookies}, req_headers: [{"host", "localhost:4000"}, {"connection", "ke
ep-alive"}, {"content-length", "632"}, {"accept", "*/*"}, {"origin", "http://localhost:4000"}, {"user-agent", "}, {"content-type", "application/json"}, {"referer", "http://localhost:4000/"}, {"accept-encoding", "gzip, deflate"}, {"accept-language", "en-US,en;q=0.8,ko;q=0.6,zh-CN;q=0.4"
}, {"alexatoolbar-alx_ns_ph", "AlexaToolbar/alx-4.0"}], request_path: "/graphql", resp_body: nil, resp_cookies: %{}, resp_headers: [{"content-type", "application/json; charset=utf-8"}, {"cache-control", "
max-age=0, private, must-revalidate"}, {"x-request-id", "ikh03v5kqightov3npgl8bv0do5rv77d"}, {"access-control-allow-origin", "*"}, {"access-control-expose-headers", ""}, {"access-control-allow-credentials
", "true"}], scheme: :http, script_name: ["graphql"], secret_key_base: "x4K=====-00-----lksMUX", state: :sent, status: 404}
(elixir) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir) lib/enum.ex:116: Enumerable.reduce/3
(elixir) lib/enum.ex:1477: Enum.reduce/3
(elixir) lib/enum.ex:1092: Enum.map/2
(rethinkdb) lib/rethinkdb/query/macros.ex:93: RethinkDB.Query.Macros.wrap/1
(rethinkdb) lib/rethinkdb/query/macros.ex:94: anonymous fn/1 in RethinkDB.Query.Macros.wrap/1
(elixir) lib/enum.ex:1092: anonymous fn/3 in Enum.map/2
(stdlib) lists.erl:1262: :lists.foldl/3
答案 0 :(得分:1)
我自己正在学习Elixir,但希望这会对你有帮助......
Elixir抱怨,因为控制器为您导入Plug
模块(通过use App.Web, :controller
)。在您定义的模块中不是这种情况,因此您需要自己导入它(参见第2行)。
另外,请注意,如果对于要忽略的变量(因此未使用),带有下划线的变量前面的命名约定。由于您的代码使用conn
参数,因此不应将其匹配为_conn
。
defmodule App.GraphQLSession do
import Plug.Conn, only: [put_status: 2]
def root_eval(conn) do
current_user =
case Guardian.Plug.current_resource(conn) do
nil ->
conn
|> put_status(:not_found)
|> render(App.V1.SessionView, "error.json", error: "User not found")
user ->
conn
|> put_status(:ok)
|> render("show.json", user: user)
end
%{author: current_user}
end
end
答案 1 :(得分:0)
要回答您更新的问题,您应该注意以下几点:
** (Protocol.UndefinedError) protocol Enumerable not implemented
。检查使用Enum.*
模块的任何代码。确保您传入函数的任何内容都是可枚举的。assigns: %{error: "User not found", guardian_default_resource: nil
。尝试使用Guardian提供的api_sign_in
功能。您可以找到更多information here。然后你应该可以使用Guardian.Plug.current_resource(conn)