towerops/lib/towerops_web/controllers/user_sudo_html/verify.html.heex
Graham McIntire 9ff9c4ddc8
fix: address UserSudoController critical issues
Critical fixes:
- Renamed controller actions to follow Phoenix conventions (verify→new, create→verify)
- Added sudo mode check in GET action using last_sudo_at timestamp
- Added TOTP enrollment check in GET action with redirect
- Changed default return path from /orgs to /users/settings
- Updated route paths from /users/sudo/verify to /users/sudo-verify (dash separator)
- Added success flash message "Identity verified."

Implementation details:
- new/2 (GET): Checks recently_verified_sudo?/1 helper that examines last_sudo_at
  instead of authenticated_at to distinguish sudo verification from regular login
- verify/2 (POST): Adds info flash and defaults to /users/settings
- recently_verified_sudo?/1: Private helper checking last_sudo_at within 10 minutes
- Updated all routes, templates, and tests to use new paths and action names

Tests:
- Added tests for already-in-sudo-mode redirect behavior
- Added test for TOTP enrollment requirement
- Updated all test assertions for new route paths and success messages
- All 15 controller tests passing
- Full test suite passing (4076 tests, 0 failures)
2026-02-01 14:45:05 -06:00

47 lines
1.4 KiB
Text

<Layouts.app flash={@flash} current_scope={@current_scope}>
<div class="mx-auto max-w-sm">
<div class="text-center">
<.header>
Re-authenticate
<:subtitle>
Enter the 6-digit code from your authenticator app to continue
</:subtitle>
</.header>
</div>
<div class="mt-8">
<.form :let={f} for={@form} as={:user} id="sudo_verify_form" action={~p"/users/sudo-verify"}>
<.input
field={f[:totp_code]}
type="text"
label="Authentication Code"
placeholder="000000"
autocomplete="one-time-code"
inputmode="numeric"
required
phx-mounted={JS.focus()}
/>
<div class="mt-2">
<p class="text-sm text-gray-500 dark:text-gray-400">
Enter the 6-digit code from your authenticator app. Recovery codes are not allowed for sensitive operations.
</p>
</div>
<div class="mt-6">
<.button class="w-full" variant="primary">
Verify <span aria-hidden="true">→</span>
</.button>
</div>
</.form>
<div class="mt-6 text-center">
<.link
href={~p"/users/log-out"}
method="delete"
class="text-sm font-semibold text-gray-600 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
>
← Log out instead
</.link>
</div>
</div>
</div>
</Layouts.app>