separate account settings from shop settings
All checks were successful
deploy / deploy (push) Successful in 3m28s
All checks were successful
deploy / deploy (push) Successful in 3m28s
- Create dedicated /admin/account page for user account management - Move email, password, and 2FA settings from /admin/settings - Add Account link to top of admin sidebar navigation - Add TOTP-based two-factor authentication with NimbleTOTP - Add TOTP verification LiveView for login flow - Add AccountController for TOTP session management - Remove Advanced section from settings (duplicated in dev tools) - Remove user email from sidebar footer (replaced by Account link) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
123
test/berrypod_web/live/admin/account_test.exs
Normal file
123
test/berrypod_web/live/admin/account_test.exs
Normal file
@@ -0,0 +1,123 @@
|
||||
defmodule BerrypodWeb.Admin.AccountTest do
|
||||
use BerrypodWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import Berrypod.AccountsFixtures
|
||||
|
||||
alias Berrypod.Accounts
|
||||
|
||||
setup do
|
||||
user = user_fixture()
|
||||
%{user: user}
|
||||
end
|
||||
|
||||
describe "unauthenticated" do
|
||||
test "redirects to login", %{conn: conn} do
|
||||
{:error, redirect} = live(conn, ~p"/admin/account")
|
||||
assert {:redirect, %{to: path}} = redirect
|
||||
assert path == ~p"/users/log-in"
|
||||
end
|
||||
end
|
||||
|
||||
describe "account page" do
|
||||
setup %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
%{conn: conn, user: user}
|
||||
end
|
||||
|
||||
test "renders email and password forms", %{conn: conn, user: user} do
|
||||
{:ok, view, html} = live(conn, ~p"/admin/account")
|
||||
|
||||
assert html =~ "Account"
|
||||
assert html =~ user.email
|
||||
assert has_element?(view, "#email_form")
|
||||
assert has_element?(view, "#password_form")
|
||||
end
|
||||
|
||||
test "validates email change", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/account")
|
||||
|
||||
result =
|
||||
view
|
||||
|> element("#email_form")
|
||||
|> render_change(%{"user" => %{"email" => "with spaces"}})
|
||||
|
||||
assert result =~ "must have the @ sign and no spaces"
|
||||
end
|
||||
|
||||
test "submits email change", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/account")
|
||||
|
||||
result =
|
||||
view
|
||||
|> form("#email_form", %{"user" => %{"email" => unique_user_email()}})
|
||||
|> render_submit()
|
||||
|
||||
assert result =~ "A link to confirm your email"
|
||||
end
|
||||
|
||||
test "validates password", %{conn: conn} do
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/account")
|
||||
|
||||
result =
|
||||
view
|
||||
|> element("#password_form")
|
||||
|> render_change(%{
|
||||
"user" => %{
|
||||
"password" => "short",
|
||||
"password_confirmation" => "mismatch"
|
||||
}
|
||||
})
|
||||
|
||||
assert result =~ "should be at least 12 character(s)"
|
||||
end
|
||||
|
||||
test "submits valid password change", %{conn: conn, user: user} do
|
||||
new_password = valid_user_password()
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/account")
|
||||
|
||||
form =
|
||||
form(view, "#password_form", %{
|
||||
"user" => %{
|
||||
"email" => user.email,
|
||||
"password" => new_password,
|
||||
"password_confirmation" => new_password
|
||||
}
|
||||
})
|
||||
|
||||
render_submit(form)
|
||||
new_password_conn = follow_trigger_action(form, conn)
|
||||
|
||||
assert redirected_to(new_password_conn) == ~p"/admin/account"
|
||||
assert Accounts.get_user_by_email_and_password(user.email, new_password)
|
||||
end
|
||||
end
|
||||
|
||||
describe "two-factor authentication" do
|
||||
setup %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
%{conn: conn, user: user}
|
||||
end
|
||||
|
||||
test "shows 2FA section", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/account")
|
||||
|
||||
assert html =~ "Two-factor authentication"
|
||||
assert html =~ "Off"
|
||||
assert html =~ "Enable 2FA"
|
||||
end
|
||||
|
||||
test "shows enabled state when TOTP is enabled", %{conn: conn, user: user} do
|
||||
# Enable TOTP for the user
|
||||
secret = NimbleTOTP.secret()
|
||||
code = NimbleTOTP.verification_code(secret)
|
||||
{:ok, _user, _codes} = Accounts.enable_totp(user, secret, code)
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/account")
|
||||
|
||||
assert html =~ "Two-factor authentication"
|
||||
assert html =~ "Enabled"
|
||||
assert html =~ "Disable 2FA"
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user