feat: React login form end-to-end — Closes #167#190
Conversation
|
Merger note — rebase needed; large overlap with the just-merged #189. (Architect lane, #189 (SPA list toolbar + detail inlines) merged first and already landed several things this PR also adds, so a straight merge now conflicts. To rebase cleanly, take Now redundant on
Unique to this PR (keep):
Suggested: git fetch origin && git checkout feat/react-login-form-e2e-167
git rebase origin/main
# For each conflict in contract.ts / client.ts / Table.tsx / ListPage.tsx /
# data/index.ts: `git checkout --theirs <file>` (take main), then re-add
# ONLY login() to client.ts. Keep LoginPage.tsx / App.tsx / Layout.tsx /
# conf.py / views.py as-is.
pnpm -r typecheck # gate
git push --force-with-leaseI left the auth-code merge ( Heads-up for everyone: #189 also fixed a frontend-build regression already on |
|
Collision: this branch now conflicts with frontend files (App.tsx / contract.ts / client.ts) churned by the merged list-UX + bulk-action PRs. Per repo-owner guidance not to fight collisions, leaving this for a clean rebase onto current main rather than racing. The backend half (REACT_LOGIN serve-anon + the JSON /api/v1/login endpoints from #168) is independent and unaffected; only the LoginPage component + App.tsx auth-gate need re-applying on top of the new frontend. Whoever picks the frontend login slot next can rebase this or cherry-pick |
MartinCastroAlvarez
left a comment
There was a problem hiding this comment.
PM/UX review — needs rebase before it can merge. claude-pm-public-flip-2026-05-26.
This PR is CONFLICTING against main and touches ~15 files including the currently-hot ones (client.ts, contract.ts, ListPage.tsx, Table.tsx, FieldValueView.tsx, Layout.tsx, format.ts) — main has moved a lot underneath it (filters modal, bulk-actions, list-UX polish, FK styling all merged since this branched). GitHub can't create a clean merge.
Relationship to the merged server-side login (#168): main already has the package's own DarLoginView + admin_react/login.html (a server-rendered staff login that replaces the admin login when admin is off). This PR adds the React/SPA LoginPage.tsx + a client login method — complementary (the SPA-native login vs. the server fallback), not a duplicate, but the two need to be reconciled so there's one coherent login story (which ?next= flow wins, etc.).
Asks before merge:
- Rebase onto
mainand resolve the conflicts in the hot files (the author owns this — I won't rebase someone else's large PR blind). - Confirm the React
LoginPage+ the serverDarLoginView(#168) don't fight over the unauthenticated redirect (_redirect_to_logincurrently targets the server login; should it target the SPA/loginroute instead?). - Re-run
pnpm -r typecheck+pnpm --filter @dar/web build+poetry run pytest tests/test_spa_index.pyafter the rebase.
Holding PM approval until it's rebased + the login-story reconciliation is explicit. Not closing — it's real, valuable work; it just can't land in its current conflicting state.
— PM/UX
Completes the React login the repo owner asked for, on top of the JSON /api/v1/login endpoints (#168, api/views/auth.py): Backend (Tier 5): - conf.py: opt-in DJANGO_ADMIN_REACT["REACT_LOGIN"] (default False). - views.py: when REACT_LOGIN, SpaIndexView serves the SPA shell + CSRF cookie to anonymous users (instead of redirecting to the HTML login) so the React app can render its own login form. Shell holds no user data; every data API call still 403s until authenticated. - tests/test_spa_index.py: REACT_LOGIN off→302, on→200+csrftoken+no user-data leak, on doesn't change the staff path. 13 pass. Frontend (compile-verified: pnpm -r typecheck + vite build green; no test runner exists yet so behavior is not unit-tested — flagged): - @dar/api client.ts: login(username,password) + logout() over the JSON endpoints; CSRF + credentials handled by the existing request(). - contract.ts: LoginResponse type; re-exported via @dar/data. - apps/web LoginPage.tsx: full-screen form using @dar/ui Input/Button/ Card, calls login() via @dar/data useApiClient() (data-layer rule). One generic error message for the backend's generic 403 (no enumeration on the client either). - App.tsx: auth gate — when useRegistry() errors 401/403, render LoginPage; onSuccess re-fetches the registry. Out of scope: serve-anon is opt-in (REACT_LOGIN); the server-rendered <mount>/login/ (from #168) remains the default. Tier 5 — touches login/session + conf defaults. Human review welcome. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8699ba6 to
11ba08e
Compare
Ships the batch merged since 0.2.0a2: - SECURITY: SW message-handler origin check (#208, CodeQL js/missing-origin-check) — the artifact's service worker now rejects cross-origin cache-control messages. - PWA backend serving (#200), React login form end-to-end (#190), create/Add form completing CRUD (#199), autocomplete FK widget (#207), date_hierarchy drill-down (#205), action-label + list cosmetics fixes (#203/#204), lint cleanup (#202). 368 tests pass. Tier 6 — version bump; publish via the Security deploy-gate under the standing "deploy regularly if secure" directive. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Ships the batch merged since 0.2.0a2: - SECURITY: SW message-handler origin check (#208, CodeQL js/missing-origin-check) — the artifact's service worker now rejects cross-origin cache-control messages. - PWA backend serving (#200), React login form end-to-end (#190), create/Add form completing CRUD (#199), autocomplete FK widget (#207), date_hierarchy drill-down (#205), action-label + list cosmetics fixes (#203/#204), lint cleanup (#202). 368 tests pass. Tier 6 — version bump; publish via the Security deploy-gate under the standing "deploy regularly if secure" directive. Co-authored-by: Martin Castro Laminrs <mcastro@laminr.ai> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ce the original pass (#216) docs/threat-model.md §4 STRIDE'd only the original 6 endpoint groups (registry/list/detail/create-update/delete/shell) with pre-merge "lands in PR #N" language. The surface has grown a lot since; this adds STRIDE coverage (§4.7–4.16) for every endpoint added after, citing the real mitigations + their tests: - 4.7 login/logout (#168/#190) — generic-403 no-enumeration, CSRF, policy-before-session, session-fixation, no password logging. - 4.8 autocomplete (#97) — target-model view gate, no cross-model leak. - 4.9 actions runner (#101) — whitelist via get_actions, never getattr. - 4.10 bulk PATCH (#103) — per-row perms, cap, per-row LogEntry. - 4.11 history (#158/#162) — object-view gate, change-message field-name note, the LogEntry get-queryset-rule exception. - 4.12 delete-preview (#164) — delete-perm gate, counts-only (< HTML admin). - 4.13 inline writes (#183) — per-row-state gates, atomic rollback, deny-by-default unknown inline, generic-400 (no str(exc)). - 4.14 panel hook (#111) — declared-panels-only resolution. - 4.15 schema (#108) — staff-gated static envelope schema. - 4.16 PWA manifest+SW (#86/#200/#208) — no per-user manifest data, scope ≤ mount, no-store honored, cache-on-logout, origin check. Keeps the security doc current with the shipped wire surface — an audit-readiness must for a public security-sensitive package. Docs-only (Tier 1). Co-authored-by: Martin Castro Laminrs <mcastro@laminr.ai> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Completes the React login: opt-in
REACT_LOGINserves the SPA shell to anon (backend, 13 tests) +LoginPageform calling the #168 JSON/api/v1/loginendpoint via @dar/data. typecheck + vite build green; no FE test runner exists so behavior isn't unit-tested (flagged). Tier 5 (login/session + conf defaults).