towerops/lib/towerops_web/controllers/user_session_controller.ex
2026-01-17 15:00:52 -06:00

100 lines
2.9 KiB
Elixir

defmodule ToweropsWeb.UserSessionController do
@moduledoc false
use ToweropsWeb, :controller
alias Towerops.Accounts
alias ToweropsWeb.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
case Accounts.login_user_by_magic_link(token) do
{:ok, {user, _expired_tokens}} ->
conn =
if params["_action"] == "confirmed" do
put_flash(conn, :info, "User confirmed successfully.")
else
conn
end
UserAuth.log_in_user(conn, 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
UserAuth.log_in_user(conn, 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
# Check if user was previously confirmed before logging in
was_confirmed =
case Accounts.get_user_by_magic_link_token(token) do
%Accounts.User{confirmed_at: confirmed_at} when not is_nil(confirmed_at) -> true
_ -> false
end
case Accounts.login_user_by_magic_link(token) do
{:ok, {user, _expired_tokens}} ->
conn =
if was_confirmed do
conn
else
put_flash(conn, :info, "User confirmed successfully.")
end
# Always use remember_me: true to keep user logged in
UserAuth.log_in_user(conn, user, %{"remember_me" => "true"})
{:error, :not_found} ->
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