add user auth

This commit is contained in:
Graham McIntire 2025-07-09 08:53:50 -05:00
parent fd82d6e7bd
commit 41eaec5c8e
No known key found for this signature in database
12 changed files with 627 additions and 221 deletions

View file

@ -119,6 +119,8 @@
color: oklch(58% 0.233 277.117) !important;
}
/* Input field dark mode fixes */
/* Marker cluster styles */
.marker-cluster-small {
background-color: rgba(16, 185, 129, 0.8);
@ -326,4 +328,60 @@
.historical-dot-marker {
z-index: 15 !important;
}
/* Input field dark mode fixes - Override DaisyUI CSS variables for dark theme */
[data-theme="dark"] {
--color-base-100: #2d3748 !important;
--color-base-200: #1a202c !important;
--color-base-300: #171923 !important;
--color-base-content: #f7fafc !important;
--input-bg: #2d3748;
--input-color: #f7fafc;
--input-border: #4a5568;
}
/* Ultra-specific selector to override DaisyUI */
html[data-theme="dark"] .card .input,
html[data-theme="dark"] .card .input-bordered,
html[data-theme="dark"] .card input.input,
html[data-theme="dark"] .card input.input-bordered,
html[data-theme="dark"] .card input[type="email"],
html[data-theme="dark"] .card input[type="password"],
html[data-theme="dark"] .form-control input.input,
html[data-theme="dark"] .form-control input.input-bordered,
html[data-theme="dark"] .form-control input[type="email"],
html[data-theme="dark"] .form-control input[type="password"] {
background-color: #2d3748 !important;
color: #f7fafc !important;
border-color: #4a5568 !important;
}
html[data-theme="dark"] .card .input:focus,
html[data-theme="dark"] .card .input-bordered:focus,
html[data-theme="dark"] .card input.input:focus,
html[data-theme="dark"] .card input.input-bordered:focus,
html[data-theme="dark"] .card input[type="email"]:focus,
html[data-theme="dark"] .card input[type="password"]:focus,
html[data-theme="dark"] .form-control input.input:focus,
html[data-theme="dark"] .form-control input.input-bordered:focus,
html[data-theme="dark"] .form-control input[type="email"]:focus,
html[data-theme="dark"] .form-control input[type="password"]:focus {
background-color: #2d3748 !important;
color: #f7fafc !important;
border-color: #6366f1 !important;
}
html[data-theme="dark"] .input::placeholder,
html[data-theme="dark"] input.input::placeholder,
html[data-theme="dark"] input[type="email"]::placeholder,
html[data-theme="dark"] input[type="password"]::placeholder {
color: oklch(60% 0.029 256.847) !important;
}
html[data-theme="dark"] .checkbox,
html[data-theme="dark"] input.checkbox {
background-color: var(--input-bg) !important;
border-color: var(--input-border) !important;
}

View file

@ -237,7 +237,7 @@ defmodule AprsmeWeb.CoreComponents do
def simple_form(assigns) do
~H"""
<.form :let={f} for={@for} as={@as} {@rest}>
<div class="space-y-8 bg-white mt-10">
<div class="space-y-8 bg-base-100 mt-10">
{render_slot(@inner_block, f)}
<div :for={action <- @actions} class="mt-2 flex items-center justify-between gap-6">
{render_slot(action, f)}
@ -442,6 +442,7 @@ defmodule AprsmeWeb.CoreComponents do
"""
attr :class, :string, default: ""
attr :dev_mode, :boolean, default: false
attr :current_user, :any, default: nil
def header(assigns) do
~H"""
@ -455,7 +456,7 @@ defmodule AprsmeWeb.CoreComponents do
</.link>
</div>
<div class="navbar-center hidden lg:flex">
<.navigation variant={:horizontal} />
<.navigation variant={:horizontal} current_user={@current_user} />
</div>
<div class="navbar-end">
<.theme_selector />
@ -474,7 +475,7 @@ defmodule AprsmeWeb.CoreComponents do
tabindex="0"
class="menu menu-sm dropdown-content mt-3 z-[1] p-2 shadow bg-base-100 rounded-box w-52"
>
<.navigation variant={:vertical} />
<.navigation variant={:vertical} current_user={@current_user} />
</ul>
</div>
</div>
@ -750,6 +751,7 @@ defmodule AprsmeWeb.CoreComponents do
"""
attr :class, :string, default: ""
attr :variant, :atom, values: [:horizontal, :vertical], default: :horizontal
attr :current_user, :any, default: nil
def navigation(assigns) do
~H"""
@ -764,6 +766,29 @@ defmodule AprsmeWeb.CoreComponents do
{gettext("About")}
</.link>
</li>
<%= if @current_user do %>
<li>
<.link navigate="/users/settings" class="text-gray-900 hover:text-gray-700">
{gettext("Settings")}
</.link>
</li>
<li>
<.link href="/users/log_out" method="delete" class="text-gray-900 hover:text-gray-700">
{gettext("Log out")}
</.link>
</li>
<% else %>
<li>
<.link navigate="/users/register" class="text-gray-900 hover:text-gray-700">
{gettext("Register")}
</.link>
</li>
<li>
<.link navigate="/users/log_in" class="text-gray-900 hover:text-gray-700">
{gettext("Log in")}
</.link>
</li>
<% end %>
</ul>
<% else %>
<li><.link navigate="/" class="text-gray-900 hover:text-gray-700">{gettext("Home")}</.link></li>
@ -771,6 +796,29 @@ defmodule AprsmeWeb.CoreComponents do
<li>
<.link navigate="/about" class="text-gray-900 hover:text-gray-700">{gettext("About")}</.link>
</li>
<%= if @current_user do %>
<li>
<.link navigate="/users/settings" class="text-gray-900 hover:text-gray-700">
{gettext("Settings")}
</.link>
</li>
<li>
<.link href="/users/log_out" method="delete" class="text-gray-900 hover:text-gray-700">
{gettext("Log out")}
</.link>
</li>
<% else %>
<li>
<.link navigate="/users/register" class="text-gray-900 hover:text-gray-700">
{gettext("Register")}
</.link>
</li>
<li>
<.link navigate="/users/log_in" class="text-gray-900 hover:text-gray-700">
{gettext("Log in")}
</.link>
</li>
<% end %>
<% end %>
"""
end

View file

@ -200,7 +200,7 @@
}
</style>
<.header dev_mode={Application.get_env(:aprsme, :dev_routes, false)} />
<.header dev_mode={Application.get_env(:aprsme, :dev_routes, false)} current_user={@current_user} />
<main
id="main-content"
class={if assigns[:map_page], do: "min-h-screen bg-base-100", else: "bg-base-100"}

View file

@ -906,7 +906,7 @@ defmodule AprsmeWeb.MapLive.Index do
</svg>
<span class="font-medium">{gettext("Navigation")}</span>
</div>
<.navigation variant={:vertical} class="text-sm" />
<.navigation variant={:vertical} class="text-sm" current_user={@current_user} />
</div>
<!-- Deployment Information -->

View file

@ -6,25 +6,61 @@ defmodule AprsmeWeb.UserConfirmationInstructionsLive do
def render(assigns) do
~H"""
<.header />
<div class="hero min-h-screen bg-base-200">
<div class="hero-content text-center">
<div class="max-w-md">
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h1 class="card-title text-3xl mb-4 justify-center">
Resend confirmation instructions
</h1>
<p class="text-base-content/70 mb-6">
Enter your email address to receive a new confirmation link
</p>
<.simple_form
:let={f}
for={%{}}
as={:user}
id="resend_confirmation_form"
phx-submit="send_instructions"
>
<.input field={{f, :email}} type="email" label="Email" required />
<:actions>
<.button phx-disable-with="Sending...">Resend confirmation instructions</.button>
</:actions>
</.simple_form>
<.simple_form
:let={_f}
for={%{}}
as={:user}
id="resend_confirmation_form"
phx-submit="send_instructions"
>
<div class="form-control w-full">
<label class="label">
<span class="label-text">Email</span>
</label>
<input
type="email"
name="user[email]"
class="input input-bordered w-full bg-base-100 text-base-content"
placeholder="Enter your email"
required
/>
</div>
<p>
<.link navigate={~p"/users/register"}>Register</.link>
| <.link navigate={~p"/users/log_in"}>Log in</.link>
</p>
<div class="form-control mt-6">
<button type="submit" class="btn btn-primary w-full" phx-disable-with="Sending...">
Resend confirmation instructions
</button>
</div>
</.simple_form>
<div class="divider">OR</div>
<div class="text-center text-sm">
<.link navigate={~p"/users/register"} class="link link-primary">
Register
</.link>
|
<.link navigate={~p"/users/log_in"} class="link link-primary">
Log in
</.link>
</div>
</div>
</div>
</div>
</div>
</div>
"""
end

View file

@ -6,20 +6,49 @@ defmodule AprsmeWeb.UserConfirmationLive do
def render(%{live_action: :edit} = assigns) do
~H"""
<div class="mx-auto max-w-sm">
<.header class="text-center" />
<div class="hero min-h-screen bg-base-200">
<div class="hero-content text-center">
<div class="max-w-md">
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h1 class="card-title text-3xl mb-4 justify-center">Confirm your account</h1>
<p class="text-base-content/70 mb-6">Click the button below to confirm your account</p>
<.simple_form :let={f} for={%{}} as={:user} id="confirmation_form" phx-submit="confirm_account">
<.input field={{f, :token}} type="hidden" value={@token} />
<:actions>
<.button phx-disable-with="Confirming..." class="w-full">Confirm my account</.button>
</:actions>
</.simple_form>
<.simple_form
:let={_f}
for={%{}}
as={:user}
id="confirmation_form"
phx-submit="confirm_account"
>
<input type="hidden" name="user[token]" value={@token} />
<p class="text-center mt-4">
<.link navigate={~p"/users/register"}>Register</.link>
| <.link navigate={~p"/users/log_in"}>Log in</.link>
</p>
<div class="form-control mt-6">
<button
type="submit"
class="btn btn-primary w-full"
phx-disable-with="Confirming..."
>
Confirm my account
</button>
</div>
</.simple_form>
<div class="divider">OR</div>
<div class="text-center text-sm">
<.link navigate={~p"/users/register"} class="link link-primary">
Register
</.link>
|
<.link navigate={~p"/users/log_in"} class="link link-primary">
Log in
</.link>
</div>
</div>
</div>
</div>
</div>
</div>
"""
end

View file

@ -6,24 +6,56 @@ defmodule AprsmeWeb.UserForgotPasswordLive do
def render(assigns) do
~H"""
<div class="mx-auto max-w-sm">
<.header class="text-center" />
<div class="hero min-h-screen bg-base-200">
<div class="hero-content text-center">
<div class="max-w-md">
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h1 class="card-title text-3xl mb-4 justify-center">Forgot your password?</h1>
<p class="text-base-content/70 mb-6">We'll send a password reset link to your inbox</p>
<h2 class="text-center text-2xl font-bold mt-6 mb-2">Forgot your password?</h2>
<p class="text-center text-gray-600 mb-6">We'll send a password reset link to your inbox</p>
<.simple_form
:let={_f}
id="reset_password_form"
for={%{}}
as={:user}
phx-submit="send_email"
>
<div class="form-control w-full">
<label class="label">
<span class="label-text">Email</span>
</label>
<input
type="email"
name="user[email]"
class="input input-bordered w-full bg-base-100 text-base-content"
placeholder="Enter your email"
required
/>
</div>
<.simple_form :let={f} id="reset_password_form" for={%{}} as={:user} phx-submit="send_email">
<.input field={{f, :email}} type="email" placeholder="Email" required />
<:actions>
<.button phx-disable-with="Sending..." class="w-full">
Send password reset instructions
</.button>
</:actions>
</.simple_form>
<p class="text-center mt-4">
<.link navigate={~p"/users/register"}>Register</.link>
| <.link navigate={~p"/users/log_in"}>Log in</.link>
</p>
<div class="form-control mt-6">
<button type="submit" class="btn btn-primary w-full" phx-disable-with="Sending...">
Send password reset instructions
</button>
</div>
</.simple_form>
<div class="divider">OR</div>
<div class="text-center text-sm">
<.link navigate={~p"/users/register"} class="link link-primary">
Register
</.link>
|
<.link navigate={~p"/users/log_in"} class="link link-primary">
Log in
</.link>
</div>
</div>
</div>
</div>
</div>
</div>
"""
end

View file

@ -7,41 +7,88 @@ defmodule AprsmeWeb.UserLoginLive do
def render(assigns) do
~H"""
<div class="mx-auto max-w-sm">
<.header class="text-center" />
<div class="hero min-h-screen bg-base-200">
<div class="hero-content text-center">
<div class="max-w-md">
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h1 class="card-title text-3xl mb-4 justify-center">Sign in to account</h1>
<p class="text-base-content/70 mb-6">
Don't have an account?
<.link navigate={~p"/users/register"} class="link link-primary">
Sign up
</.link>
for an account now.
</p>
<h2 class="text-center text-2xl font-bold mt-6 mb-2">Sign in to account</h2>
<p class="text-center text-gray-600 mb-6">
Don't have an account?
<.link navigate={~p"/users/register"} class="font-semibold text-brand hover:underline">
Sign up
</.link>
for an account now.
</p>
<.simple_form
:let={f}
id="login_form"
for={@changeset}
action={~p"/users/log_in"}
as={:user}
phx-update="ignore"
>
<div class="form-control w-full">
<label class="label">
<span class="label-text">Email</span>
</label>
<input
type="email"
name={Phoenix.HTML.Form.input_name(f, :email)}
value={Phoenix.HTML.Form.input_value(f, :email) || ""}
class="input input-bordered w-full"
placeholder="Enter your email"
required
/>
</div>
<.simple_form
:let={f}
id="login_form"
for={@changeset}
action={~p"/users/log_in"}
as={:user}
phx-update="ignore"
>
<.input field={{f, :email}} type="email" label="Email" required />
<.input field={{f, :password}} type="password" label="Password" required />
<div class="form-control w-full">
<label class="label">
<span class="label-text">Password</span>
</label>
<input
type="password"
name={Phoenix.HTML.Form.input_name(f, :password)}
value={Phoenix.HTML.Form.input_value(f, :password) || ""}
class="input input-bordered w-full"
placeholder="Enter your password"
required
/>
</div>
<:actions :let={f}>
<.input field={{f, :remember_me}} type="checkbox" label="Keep me logged in" />
<.link navigate={~p"/users/reset_password"} class="text-sm font-semibold">
Forgot your password?
</.link>
</:actions>
<:actions>
<.button phx-disable-with="Signing in..." class="w-full">
Sign in <span aria-hidden="true"></span>
</.button>
</:actions>
</.simple_form>
<div class="form-control">
<label class="label cursor-pointer justify-start">
<input
type="checkbox"
name={Phoenix.HTML.Form.input_name(f, :remember_me)}
value="true"
class="checkbox checkbox-primary mr-2"
/>
<span class="label-text">Keep me logged in</span>
</label>
</div>
<div class="text-center mb-4">
<.link navigate={~p"/users/reset_password"} class="link link-primary text-sm">
Forgot your password?
</.link>
</div>
<div class="form-control mt-6">
<button
type="submit"
class="btn btn-primary w-full"
phx-disable-with="Signing in..."
>
Sign in
</button>
</div>
</.simple_form>
</div>
</div>
</div>
</div>
</div>
"""
end

View file

@ -7,40 +7,77 @@ defmodule AprsmeWeb.UserRegistrationLive do
def render(assigns) do
~H"""
<div class="mx-auto max-w-sm">
<.header class="text-center" />
<div class="hero min-h-screen bg-base-200">
<div class="hero-content text-center">
<div class="max-w-md">
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h1 class="card-title text-3xl mb-4 justify-center">Register for an account</h1>
<p class="text-base-content/70 mb-6">
Already registered?
<.link navigate={~p"/users/log_in"} class="link link-primary">
Sign in
</.link>
to your account now.
</p>
<h2 class="text-center text-2xl font-bold mt-6 mb-2">Register for an account</h2>
<p class="text-center text-gray-600 mb-6">
Already registered?
<.link navigate={~p"/users/log_in"} class="font-semibold text-brand hover:underline">
Sign in
</.link>
to your account now.
</p>
<.simple_form
:let={f}
id="registration_form"
for={@changeset}
phx-submit="save"
phx-change="validate"
phx-trigger-action={@trigger_submit}
action={~p"/users/log_in?_action=registered"}
method="post"
as={:user}
>
<div :if={@changeset.action == :insert} class="alert alert-error mb-4">
<span>Oops, something went wrong! Please check the errors below.</span>
</div>
<.simple_form
:let={f}
id="registration_form"
for={@changeset}
phx-submit="save"
phx-change="validate"
phx-trigger-action={@trigger_submit}
action={~p"/users/log_in?_action=registered"}
method="post"
as={:user}
>
<.error :if={@changeset.action == :insert}>
Oops, something went wrong! Please check the errors below.
</.error>
<div class="form-control w-full">
<label class="label">
<span class="label-text">Email</span>
</label>
<input
type="email"
name={Phoenix.HTML.Form.input_name(f, :email)}
value={Phoenix.HTML.Form.input_value(f, :email) || ""}
class="input input-bordered w-full bg-base-100 text-base-content"
placeholder="Enter your email"
required
/>
</div>
<.input field={{f, :email}} type="email" label="Email" required />
<.input field={{f, :password}} type="password" label="Password" required />
<div class="form-control w-full">
<label class="label">
<span class="label-text">Password</span>
</label>
<input
type="password"
name={Phoenix.HTML.Form.input_name(f, :password)}
value={Phoenix.HTML.Form.input_value(f, :password) || ""}
class="input input-bordered w-full bg-base-100 text-base-content"
placeholder="Enter your password"
required
/>
</div>
<:actions>
<.button phx-disable-with="Creating account..." class="w-full">Create an account</.button>
</:actions>
</.simple_form>
<div class="form-control mt-6">
<button
type="submit"
class="btn btn-primary w-full"
phx-disable-with="Creating account..."
>
Create an account
</button>
</div>
</.simple_form>
</div>
</div>
</div>
</div>
</div>
"""
end

View file

@ -6,36 +6,75 @@ defmodule AprsmeWeb.UserResetPasswordLive do
def render(assigns) do
~H"""
<div class="mx-auto max-w-sm">
<.header class="text-center" />
<div class="hero min-h-screen bg-base-200">
<div class="hero-content text-center">
<div class="max-w-md">
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h1 class="card-title text-3xl mb-4 justify-center">Reset Password</h1>
<p class="text-base-content/70 mb-6">Enter your new password below</p>
<.simple_form
:let={f}
for={@changeset}
id="reset_password_form"
phx-submit="reset_password"
phx-change="validate"
>
<.error :if={@changeset.action == :insert}>
Oops, something went wrong! Please check the errors below.
</.error>
<.simple_form
:let={f}
for={@changeset}
id="reset_password_form"
phx-submit="reset_password"
phx-change="validate"
>
<div :if={@changeset.action == :insert} class="alert alert-error mb-4">
<span>Oops, something went wrong! Please check the errors below.</span>
</div>
<.input field={{f, :password}} type="password" label="New password" required />
<.input
field={{f, :password_confirmation}}
type="password"
label="Confirm new password"
required
/>
<:actions>
<.button phx-disable-with="Resetting..." class="w-full">Reset Password</.button>
</:actions>
</.simple_form>
<div class="form-control w-full">
<label class="label">
<span class="label-text">New password</span>
</label>
<input
type="password"
name={Phoenix.HTML.Form.input_name(f, :password)}
value={Phoenix.HTML.Form.input_value(f, :password) || ""}
class="input input-bordered w-full bg-base-100 text-base-content"
placeholder="Enter new password"
required
/>
</div>
<p class="text-center mt-4">
<.link navigate={~p"/users/register"}>Register</.link>
| <.link navigate={~p"/users/log_in"}>Log in</.link>
</p>
<div class="form-control w-full">
<label class="label">
<span class="label-text">Confirm new password</span>
</label>
<input
type="password"
name={Phoenix.HTML.Form.input_name(f, :password_confirmation)}
value={Phoenix.HTML.Form.input_value(f, :password_confirmation) || ""}
class="input input-bordered w-full bg-base-100 text-base-content"
placeholder="Confirm new password"
required
/>
</div>
<div class="form-control mt-6">
<button type="submit" class="btn btn-primary w-full" phx-disable-with="Resetting...">
Reset Password
</button>
</div>
</.simple_form>
<div class="divider">OR</div>
<div class="text-center text-sm">
<.link navigate={~p"/users/register"} class="link link-primary">
Register
</.link>
|
<.link navigate={~p"/users/log_in"} class="link link-primary">
Log in
</.link>
</div>
</div>
</div>
</div>
</div>
</div>
"""
end

View file

@ -6,68 +6,147 @@ defmodule AprsmeWeb.UserSettingsLive do
def render(assigns) do
~H"""
<.header />
<div class="hero min-h-screen bg-base-200">
<div class="hero-content flex-col w-full max-w-4xl">
<div class="text-center mb-8">
<h1 class="text-4xl font-bold">Account Settings</h1>
<p class="text-base-content/70">Update your email address and password</p>
</div>
<.simple_form
:let={f}
id="email_form"
for={@email_changeset}
phx-submit="update_email"
phx-change="validate_email"
>
<.error :if={@email_changeset.action == :insert}>
Oops, something went wrong! Please check the errors below.
</.error>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 w-full">
<!-- Change Email Section -->
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title text-2xl mb-4">Change Email</h2>
<.input field={{f, :email}} type="email" label="Email" required />
<.simple_form
:let={f}
id="email_form"
for={@email_changeset}
phx-submit="update_email"
phx-change="validate_email"
>
<div :if={@email_changeset.action == :insert} class="alert alert-error mb-4">
<span>Oops, something went wrong! Please check the errors below.</span>
</div>
<.input
field={{f, :current_password}}
name="current_password"
id="current_password_for_email"
type="password"
label="Current password"
value={@email_form_current_password}
required
/>
<:actions>
<.button phx-disable-with="Changing...">Change Email</.button>
</:actions>
</.simple_form>
<div class="form-control w-full">
<label class="label">
<span class="label-text">Email</span>
</label>
<input
type="email"
name={Phoenix.HTML.Form.input_name(f, :email)}
value={Phoenix.HTML.Form.input_value(f, :email) || ""}
class="input input-bordered w-full bg-base-100 text-base-content"
placeholder="Enter your email"
required
/>
</div>
<.header />
<div class="form-control w-full">
<label class="label">
<span class="label-text">Current password</span>
</label>
<input
type="password"
name="current_password"
id="current_password_for_email"
value={@email_form_current_password || ""}
class="input input-bordered w-full bg-base-100 text-base-content"
placeholder="Enter current password"
required
/>
</div>
<.simple_form
:let={f}
id="password_form"
for={@password_changeset}
action={~p"/users/log_in?_action=password_updated"}
method="post"
phx-change="validate_password"
phx-submit="update_password"
phx-trigger-action={@trigger_submit}
>
<.error :if={@password_changeset.action == :insert}>
Oops, something went wrong! Please check the errors below.
</.error>
<div class="form-control mt-6">
<button type="submit" class="btn btn-primary w-full" phx-disable-with="Changing...">
Change Email
</button>
</div>
</.simple_form>
</div>
</div>
<!-- Change Password Section -->
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title text-2xl mb-4">Change Password</h2>
<.input field={{f, :email}} type="hidden" value={@current_email} />
<.simple_form
:let={f}
id="password_form"
for={@password_changeset}
action={~p"/users/log_in?_action=password_updated"}
method="post"
phx-change="validate_password"
phx-submit="update_password"
phx-trigger-action={@trigger_submit}
>
<div :if={@password_changeset.action == :insert} class="alert alert-error mb-4">
<span>Oops, something went wrong! Please check the errors below.</span>
</div>
<.input field={{f, :password}} type="password" label="New password" required />
<.input field={{f, :password_confirmation}} type="password" label="Confirm new password" />
<.input
field={{f, :current_password}}
name="current_password"
type="password"
label="Current password"
id="current_password_for_password"
value={@current_password}
required
/>
<:actions>
<.button phx-disable-with="Changing...">Change Password</.button>
</:actions>
</.simple_form>
<input
type="hidden"
name={Phoenix.HTML.Form.input_name(f, :email)}
value={@current_email}
/>
<div class="form-control w-full">
<label class="label">
<span class="label-text">New password</span>
</label>
<input
type="password"
name={Phoenix.HTML.Form.input_name(f, :password)}
value={Phoenix.HTML.Form.input_value(f, :password) || ""}
class="input input-bordered w-full bg-base-100 text-base-content"
placeholder="Enter new password"
required
/>
</div>
<div class="form-control w-full">
<label class="label">
<span class="label-text">Confirm new password</span>
</label>
<input
type="password"
name={Phoenix.HTML.Form.input_name(f, :password_confirmation)}
value={Phoenix.HTML.Form.input_value(f, :password_confirmation) || ""}
class="input input-bordered w-full bg-base-100 text-base-content"
placeholder="Confirm new password"
required
/>
</div>
<div class="form-control w-full">
<label class="label">
<span class="label-text">Current password</span>
</label>
<input
type="password"
name="current_password"
id="current_password_for_password"
value={@current_password || ""}
class="input input-bordered w-full bg-base-100 text-base-content"
placeholder="Enter current password"
required
/>
</div>
<div class="form-control mt-6">
<button type="submit" class="btn btn-primary w-full" phx-disable-with="Changing...">
Change Password
</button>
</div>
</.simple_form>
</div>
</div>
</div>
</div>
</div>
"""
end

View file

@ -51,10 +51,37 @@ defmodule AprsmeWeb.Router do
get "/status.json", PageController, :status_json
end
## Authentication routes
scope "/", AprsmeWeb do
pipe_through [:browser, :redirect_if_user_is_authenticated]
live_session :redirect_if_user_is_authenticated,
on_mount: [{AprsmeWeb.UserAuth, :redirect_if_user_is_authenticated}, {AprsmeWeb.LocaleHook, :set_locale}] do
live "/users/register", UserRegistrationLive, :new
live "/users/log_in", UserLoginLive, :new
live "/users/reset_password", UserForgotPasswordLive, :new
live "/users/reset_password/:token", UserResetPasswordLive, :edit
end
post "/users/log_in", UserSessionController, :create
end
scope "/", AprsmeWeb do
pipe_through [:browser, :require_authenticated_user]
live_session :require_authenticated_user,
on_mount: [{AprsmeWeb.UserAuth, :ensure_authenticated}, {AprsmeWeb.LocaleHook, :set_locale}] do
live "/users/settings", UserSettingsLive, :edit
live "/users/settings/confirm_email/:token", UserSettingsLive, :confirm_email
end
end
scope "/", AprsmeWeb do
pipe_through :browser
live_session :regular_pages, on_mount: [{AprsmeWeb.LocaleHook, :set_locale}] do
live_session :regular_pages,
on_mount: [{AprsmeWeb.UserAuth, :mount_current_user}, {AprsmeWeb.LocaleHook, :set_locale}] do
live "/status", StatusLive.Index, :index
live "/packets", PacketsLive.Index, :index
live "/packets/:callsign", PacketsLive.CallsignView, :index
@ -89,30 +116,4 @@ defmodule AprsmeWeb.Router do
forward "/mailbox", Plug.Swoosh.MailboxPreview
end
end
## Authentication routes
scope "/", AprsmeWeb do
pipe_through [:browser, :redirect_if_user_is_authenticated]
live_session :redirect_if_user_is_authenticated,
on_mount: [{AprsmeWeb.UserAuth, :redirect_if_user_is_authenticated}, {AprsmeWeb.LocaleHook, :set_locale}] do
live "/users/register", UserRegistrationLive, :new
live "/users/log_in", UserLoginLive, :new
live "/users/reset_password", UserForgotPasswordLive, :new
live "/users/reset_password/:token", UserResetPasswordLive, :edit
end
post "/users/log_in", UserSessionController, :create
end
scope "/", AprsmeWeb do
pipe_through [:browser, :require_authenticated_user]
live_session :require_authenticated_user,
on_mount: [{AprsmeWeb.UserAuth, :ensure_authenticated}, {AprsmeWeb.LocaleHook, :set_locale}] do
live "/users/settings", UserSettingsLive, :edit
live "/users/settings/confirm_email/:token", UserSettingsLive, :confirm_email
end
end
end