firehose/app/lib/firehose_web/controllers/user_session_controller.ex
Willem van den Ende a380d0cb69 Add phx.gen.auth authentication scaffolding
- LiveView-based email/password auth via mix phx.gen.auth
- Auth links removed from public navigation (direct URL access only)
- Accounts context with User schema and token management
2026-04-01 20:31:13 +00:00

89 lines
2.5 KiB
Elixir

defmodule FirehoseWeb.UserSessionController do
use FirehoseWeb, :controller
alias Firehose.Accounts
alias FirehoseWeb.UserAuth
def new(conn, _params) do
email = get_in(conn.assigns, [:current_scope, Access.key(:user), Access.key(:email)])
form = Phoenix.Component.to_form(%{"email" => email}, as: "user")
render(conn, :new, form: form)
end
# magic link login
def create(conn, %{"user" => %{"token" => token} = user_params} = params) do
info =
case params do
%{"_action" => "confirmed"} -> "User confirmed successfully."
_ -> "Welcome back!"
end
case Accounts.login_user_by_magic_link(token) do
{:ok, {user, _expired_tokens}} ->
conn
|> put_flash(:info, info)
|> UserAuth.log_in_user(user, user_params)
{:error, :not_found} ->
conn
|> put_flash(:error, "The link is invalid or it has expired.")
|> render(:new, form: Phoenix.Component.to_form(%{}, as: "user"))
end
end
# email + password login
def create(conn, %{"user" => %{"email" => email, "password" => password} = user_params}) do
if user = Accounts.get_user_by_email_and_password(email, password) do
conn
|> put_flash(:info, "Welcome back!")
|> UserAuth.log_in_user(user, user_params)
else
form = Phoenix.Component.to_form(user_params, as: "user")
# In order to prevent user enumeration attacks, don't disclose whether the email is registered.
conn
|> put_flash(:error, "Invalid email or password")
|> render(:new, form: form)
end
end
# magic link request
def create(conn, %{"user" => %{"email" => email}}) do
if user = Accounts.get_user_by_email(email) do
Accounts.deliver_login_instructions(
user,
&url(~p"/users/log-in/#{&1}")
)
end
info =
"If your email is in our system, you will receive instructions for logging in shortly."
conn
|> put_flash(:info, info)
|> redirect(to: ~p"/users/log-in")
end
def confirm(conn, %{"token" => token}) do
if user = Accounts.get_user_by_magic_link_token(token) do
form = Phoenix.Component.to_form(%{"token" => token}, as: "user")
conn
|> assign(:user, user)
|> assign(:form, form)
|> render(:confirm)
else
conn
|> put_flash(:error, "Magic link is invalid or it has expired.")
|> redirect(to: ~p"/users/log-in")
end
end
def delete(conn, _params) do
conn
|> put_flash(:info, "Logged out successfully.")
|> UserAuth.log_out_user()
end
end