prop/lib/microwaveprop_web/controllers/user_settings_controller.ex
Graham McIntire 355bed178d Add beacon monitor registration and fix prod SMTP
Users can now register beacon monitors on the settings page. Each
monitor gets a unique random token the remote program will use to
authenticate its reports. Name is the only user-supplied field for
now; more will be added as the monitor protocol is defined.

Also adds :gen_smtp to deps. Swoosh's SMTP adapter depends on
:mimemail which lives in that package, and production was 500'ing
when trying to send confirmation emails without it.
2026-04-08 11:30:28 -05:00

87 lines
2.6 KiB
Elixir

defmodule MicrowavepropWeb.UserSettingsController do
use MicrowavepropWeb, :controller
import MicrowavepropWeb.UserAuth, only: [require_sudo_mode: 2]
alias Microwaveprop.Accounts
alias Microwaveprop.BeaconMonitors
alias MicrowavepropWeb.UserAuth
plug :require_sudo_mode
plug :assign_email_and_password_changesets
plug :assign_beacon_monitors
def edit(conn, _params) do
render(conn, :edit)
end
def update(conn, %{"action" => "update_email"} = params) do
%{"user" => user_params} = params
user = conn.assigns.current_scope.user
case Accounts.change_user_email(user, user_params) do
%{valid?: true} = changeset ->
Accounts.deliver_user_update_email_instructions(
Ecto.Changeset.apply_action!(changeset, :insert),
user.email,
&url(~p"/users/settings/confirm-email/#{&1}")
)
conn
|> put_flash(
:info,
"A link to confirm your email change has been sent to the new address."
)
|> redirect(to: ~p"/users/settings")
changeset ->
render(conn, :edit, email_changeset: %{changeset | action: :insert})
end
end
def update(conn, %{"action" => "update_password"} = params) do
%{"user" => user_params} = params
user = conn.assigns.current_scope.user
case Accounts.update_user_password(user, user_params) do
{:ok, {user, _}} ->
conn
|> put_flash(:info, "Password updated successfully.")
|> put_session(:user_return_to, ~p"/users/settings")
|> UserAuth.log_in_user(user)
{:error, changeset} ->
render(conn, :edit, password_changeset: changeset)
end
end
def confirm_email(conn, %{"token" => token}) do
case Accounts.update_user_email(conn.assigns.current_scope.user, token) do
{:ok, _user} ->
conn
|> put_flash(:info, "Email changed successfully.")
|> redirect(to: ~p"/users/settings")
{:error, _} ->
conn
|> put_flash(:error, "Email change link is invalid or it has expired.")
|> redirect(to: ~p"/users/settings")
end
end
defp assign_email_and_password_changesets(conn, _opts) do
user = conn.assigns.current_scope.user
conn
|> assign(:email_changeset, Accounts.change_user_email(user))
|> assign(:password_changeset, Accounts.change_user_password(user))
end
defp assign_beacon_monitors(conn, _opts) do
user = conn.assigns.current_scope.user
conn
|> assign(:beacon_monitors, BeaconMonitors.list_monitors_for_user(user))
|> assign(:beacon_monitor_changeset, BeaconMonitors.change_monitor())
end
end