feat: password reset flow frontend pages #63
No reviewers
Labels
No labels
domain:backend
domain:devops
domain:frontend
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/westside-landing!63
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "132-password-reset-frontend"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
/forgot-passwordand/reset-passwordfrontend pages so parents can reset their own passwords through the basketball-api Gmail OAuth flow, bypassing Keycloak's broken built-in reset linkChanges
src/routes/forgot-password/+page.svelte: New page with email input form. POSTs to/api/password-reset/request. Shows generic "check your email" message on success (no email enumeration).src/routes/reset-password/+page.svelte: New page that readstokenfrom URL query params. Two password inputs with client-side match validation (min 8 chars). POSTs to/api/password-reset/confirm. Shows success with link to signin, or error with link to request new token.src/routes/+layout.svelte: Added/forgot-passwordand/reset-passwordto PUBLIC_ROUTES so the auth guard does not redirect these pages.src/routes/signin/+page.svelte: Added "Forgot Password?" link between Sign In button and "Back to home" link.src/app.css: Added.forgot-linkstyles for the signin page link.Test Plan
/forgot-password— form renders, submit with email shows success message/reset-password?token=test— form renders, password mismatch validation works client-side/reset-password(no token) — "no token" error state with link to request a new one/signin— "Forgot Password?" link visible and navigates to/forgot-passwordnpm run buildandnpm run checkpass with no new errorsReview Checklist
Related
Self-review: PASS -- no issues found.
Reviewed all 5 changed files (512 additions, 1 deletion):
npm run buildandnpm run checkpass with no new errors or warningsPR #63 Review
DOMAIN REVIEW
Tech stack: SvelteKit (Svelte 5 runes), scoped CSS, REST API integration via
$lib/api.js.Security — anti-enumeration (good)
The forgot-password page correctly shows a generic "check your email" message regardless of API response status. The
if (!res.ok)block is intentionally empty, falling through tosubmitted = true. This prevents email enumeration. Well done.API integration (good)
Both pages correctly import
API_BASEfrom$lib/api.jsand use rawfetch()instead of the authenticatedapiFetch()wrapper. This is correct — these are unauthenticated public endpoints. Token is not leaked into the request.Password validation (good)
oninputvalidation feedbackminlength="8"attribute provides native browser validation as backuppasswordsMatchis trueerroranddetailresponse fields with a safe fallbackToken handling (good)
$derived($page.url.searchParams.get('token'))is reactive. The no-token state renders a clear error card with a link to request a new token. Expired/invalid token errors from the API are caught and displayed.State management (good)
Both pages use Svelte 5
$stateand$derivedrunes correctly. The double-submit guard (if (submitting) return) is in place on both forms.PUBLIC_ROUTES (good)
Both
/forgot-passwordand/reset-passwordadded to the auth guard whitelist in+layout.svelte. The layout'sPUBLIC_ROUTES.some()check with trailing-slash handling covers both paths.CSS pattern consistency (acceptable)
Both pages use hardcoded hex values in scoped
<style>blocks. This matches the existing pattern acrosscheckout/cancel,checkout/success, and other pages. The codebase does define CSS custom properties in:root(e.g.,--color-red: #d42026), but scoped styles in route pages consistently hardcode values. Not a new deviation.BLOCKERS
None.
Re: test coverage — This repo has zero test infrastructure (no vitest, no playwright config, no test files). There is an open issue (#62) for E2E tests. Adding test infrastructure is out of scope for this PR, and the manual test plan in the PR body is thorough. This is not a blocker given the repo's current state.
NITS
Massive CSS duplication between the two pages. The
forgot-passwordandreset-passwordscoped styles share ~130 lines of near-identical CSS (.form-group,.form-label,.form-input,.btn-action,.back-link,.success-message,.success-note, plus the page/card/header/logo/title/subtitle patterns). If a third password-flow page is ever added, or if the design changes, these will diverge. Consider extracting shared form/card styles intoapp.cssin a follow-up.!importantoverrides in.success-note. Both pages usecolor: #737373 !important; font-size: 0.8rem !important; margin-bottom: 0 !important;to override parent.success-message prules. This works but is fragile. A more specific selector (.success-message .success-note) would avoid!important.Accessibility: no ARIA live regions. When the form submits and transitions to the success/error state, screen readers will not announce the change. Adding
aria-live="polite"to the success-message and error-card containers would improve accessibility for parents using assistive technology.Cross-repo "Closes" reference is wrong. The PR body says
Closes forgejo_admin/westside-app#132but westside-app has no issue #132. The parent issue isforgejo_admin/basketball-api#132. This should beCloses forgejo_admin/basketball-api#132or simply reference it asRelated: forgejo_admin/basketball-api#132(since the frontend PR alone doesn't close a cross-repo feature issue).Logo URL hardcoded in both pages.
https://minio-api.tail5b443a.ts.net/assets/westside/branding/logo.jpegappears in forgot-password, reset-password, signin, register, and layout. This is pre-existing across the codebase, but worth noting — if the MinIO hostname changes, every page needs updating. A$lib/constants.jswould help.SOP COMPLIANCE
132-password-reset-frontendreferences basketball-api #132PROCESS OBSERVATIONS
PUBLIC_ROUTES, which is additive and safe./api/password-reset/requestand/api/password-reset/confirm). Both must be deployed together. The frontend gracefully handles API errors, so deploying frontend-first would show a user-friendly error rather than a crash.VERDICT: APPROVED
Clean implementation of the password reset frontend. Security-conscious (anti-enumeration), properly integrated with the auth guard, mobile-friendly card layouts consistent with existing pages, solid client-side validation. The CSS duplication and missing ARIA live regions should be tracked as follow-up work but do not block this Tuesday-critical feature.