我正在使用基本的Phoenix应用程序中的身份验证概念。我有一个User
has_many
emails
。用户可以通过输入他/她的电子邮件地址在http://localhost:4000/sessions/new
登录。不幸的是,我陷入了困境。我需要在 auth.ex 中做些什么来解决这个问题?
mix phoenix.new my_app --database mysql
cd my_app
mix phoenix.gen.html User users name:string
mix phoenix.gen.html Email emails value:string user_id:references:users
mix ecto.create
mix ecto.migrate
网络/ router.ex
[...]
scope "/", MyApp do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
resources "/users", UserController
resources "/emails", EmailController
resources "/sessions", SessionController, only: [:new, :create, :delete]
end
[...]
网络/模型/ user.ex
defmodule MyApp.User do
use MyApp.Web, :model
schema "users" do
field :name, :string
has_many :emails, MyApp.Email
timestamps
end
@required_fields ~w(name)
@optional_fields ~w()
def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
end
end
网络/模型/ email.ex
defmodule MyApp.Email do
use MyApp.Web, :model
schema "emails" do
field :value, :string
belongs_to :user, MyApp.User
timestamps
end
@required_fields ~w(value user_id)
@optional_fields ~w()
def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
end
end
网络/视图/ session_view.ex
defmodule MyApp.SessionView do
use MyApp.Web, :view
end
网络/模板/会话/ new.html.eex
<h1>Login</h1>
<%= form_for @conn, session_path(@conn, :create), [as: :session], fn f -> %>
<div class="form-group">
<%= text_input f, :email, placeholder: "email" %>
</div>
<%= submit "Log in" %>
<% end %>
网络/控制器/ session_controller.ex
defmodule MyApp.SessionController do
use MyApp.Web, :controller
def new(conn, _) do
render conn, "new.html"
end
def create(conn, %{"session" => %{"email" => email}}) do
case MyApp.Auth.login_by_email(conn, email, repo: Repo) do
{:ok, conn} ->
conn
|> put_flash(:info, "Welcome!")
|> redirect(to: page_path(conn, :index))
{:error, _reason, conn} ->
conn
|> put_flash(:error, "Invalid email")
|> render("new.html")
end
end
end
网络/控制器/ auth.ex
defmodule MyApp.Auth do
import Plug.Conn
alias MyApp.User
def init(opts) do
Keyword.fetch!(opts, :repo)
end
def login_by_email(conn, email, _opts) do
# What code would fix this?
#
user = repo.get!(User, email)
conn
|> assign(:current_user, user)
|> put_session(:user_id, user.id)
|> configure_session(renew: true)
end
end
答案 0 :(得分:1)
您需要导入$.ajaxSetup({ cache: false });
才能使查询生效。
Ecto.Query
另外,请注意内部联接,它假定电子邮件&#39;价值观是独一无二的。
答案 1 :(得分:0)
您只需查询电子邮件并预加载用户。
email_with_user =
repo.one(from e in Email,
join: u in assoc(e, :user),
where: e.value == ^email)
user = email_with_user.user
此外,plug specification表示必须有init
和call
功能才能让插件正常工作。