|
@@ -1,4 +1,4 @@
|
|
|
-# Frontend UI: App Shell, Routing, Auth/RBAC, Explorer, Search, Date Range Filter, Navigation Polish, Profile Password Change, User Management, and Role Refinement (RHL-019 / RHL-020 / RHL-021 / RHL-022 / RHL-023 / RHL-024 / RHL-025 / RHL-037 / RHL-032 / RHL-009 / RHL-012 / RHL-041)
|
|
|
|
|
|
|
+# Frontend UI: App Shell, Routing, Auth/RBAC, Explorer, Search, Date Range Filter, Navigation Polish, Profile Password Change, User Management, Role Refinement, and Must-Change-Password Gate (RHL-019 / RHL-020 / RHL-021 / RHL-022 / RHL-023 / RHL-024 / RHL-025 / RHL-037 / RHL-032 / RHL-009 / RHL-012 / RHL-041 / RHL-044)
|
|
|
|
|
|
|
|
This document describes the **frontend routing scaffold**, the **application shell layout**, and the core UI modules for the RHL Lieferscheine app.
|
|
This document describes the **frontend routing scaffold**, the **application shell layout**, and the core UI modules for the RHL Lieferscheine app.
|
|
|
|
|
|
|
@@ -16,6 +16,7 @@ Timeline:
|
|
|
- **RHL-009**: Profile password change UI (Change Password form + toasts).
|
|
- **RHL-009**: Profile password change UI (Change Password form + toasts).
|
|
|
- **RHL-041**: Role refinement (`superadmin`) + capability separation (branch access vs user management).
|
|
- **RHL-041**: Role refinement (`superadmin`) + capability separation (branch access vs user management).
|
|
|
- **RHL-012**: User management UI (list/create/update/delete users) + guarded admin endpoints.
|
|
- **RHL-012**: User management UI (list/create/update/delete users) + guarded admin endpoints.
|
|
|
|
|
+- **RHL-044**: Must-change-password enforcement (central protected-route gate, `/profile` redirect, and post-change resume flow).
|
|
|
|
|
|
|
|
> **Language policy**
|
|
> **Language policy**
|
|
|
>
|
|
>
|
|
@@ -27,7 +28,7 @@ Timeline:
|
|
|
|
|
|
|
|
## 1. Scope
|
|
## 1. Scope
|
|
|
|
|
|
|
|
-### 1.1 Implemented (as of RHL-012 + RHL-041 + RHL-037 + RHL-025 + RHL-032 + RHL-009)
|
|
|
|
|
|
|
+### 1.1 Implemented (as of RHL-012 + RHL-041 + RHL-037 + RHL-025 + RHL-032 + RHL-009 + RHL-044)
|
|
|
|
|
|
|
|
- **Public** `/login` route with a functional login form (shadcn/ui primitives).
|
|
- **Public** `/login` route with a functional login form (shadcn/ui primitives).
|
|
|
|
|
|
|
@@ -57,6 +58,20 @@ Timeline:
|
|
|
- Uses inline validation for actionable form errors.
|
|
- Uses inline validation for actionable form errors.
|
|
|
- Uses toast notifications (Sonner) for success/error feedback.
|
|
- Uses toast notifications (Sonner) for success/error feedback.
|
|
|
|
|
|
|
|
|
|
+- **Must-change-password enforcement (RHL-044)**:
|
|
|
|
|
+ - Session identity (`GET /api/auth/me`) includes `mustChangePassword`.
|
|
|
|
|
+ - `AuthGate` centrally enforces:
|
|
|
|
|
+ - if `mustChangePassword=true`, redirect any protected non-profile route to `/profile`.
|
|
|
|
|
+ - keep users on `/profile` until password is changed.
|
|
|
|
|
+ - Redirect state is preserved with:
|
|
|
|
|
+ - `/profile?mustChangePasswordGate=1&next=<safe-internal-url>`
|
|
|
|
|
+ - After successful password change:
|
|
|
|
|
+ - backend clears `mustChangePassword` and refreshes the session cookie.
|
|
|
|
|
+ - frontend revalidates auth state and automatically resumes `next` when available.
|
|
|
|
|
+ - `/profile` shows:
|
|
|
|
|
+ - required-action alert (red) while `mustChangePassword=true`
|
|
|
|
|
+ - success alert (green) after successful password change once the gate is lifted.
|
|
|
|
|
+
|
|
|
- **Global toast notifications (Sonner)**:
|
|
- **Global toast notifications (Sonner)**:
|
|
|
- Sonner Toaster is mounted once in the root layout.
|
|
- Sonner Toaster is mounted once in the root layout.
|
|
|
- UI code uses a small wrapper (`lib/frontend/ui/toast.js`) to keep copy and behavior consistent.
|
|
- UI code uses a small wrapper (`lib/frontend/ui/toast.js`) to keep copy and behavior consistent.
|
|
@@ -164,9 +179,6 @@ Timeline:
|
|
|
- branch user creation UX (fixed `NL` prefix + numeric-only input)
|
|
- branch user creation UX (fixed `NL` prefix + numeric-only input)
|
|
|
- optional branch existence check / warning when creating branch users
|
|
- optional branch existence check / warning when creating branch users
|
|
|
|
|
|
|
|
-- `mustChangePassword` enforcement (separate follow-up ticket):
|
|
|
|
|
- - gate/redirect until password change is completed
|
|
|
|
|
-
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
## 2. Route Groups & URL Structure
|
|
## 2. Route Groups & URL Structure
|
|
@@ -183,7 +195,8 @@ The app uses Next.js App Router **Route Groups** to separate public and protecte
|
|
|
- Routes that render inside the AppShell.
|
|
- Routes that render inside the AppShell.
|
|
|
- Protected routes are guarded by:
|
|
- Protected routes are guarded by:
|
|
|
1. Session check (AuthProvider)
|
|
1. Session check (AuthProvider)
|
|
|
- 2. UI RBAC check for branch routes (BranchGuard)
|
|
|
|
|
|
|
+ 2. Must-change-password gate (`AuthGate`, RHL-044)
|
|
|
|
|
+ 3. UI RBAC check for branch routes (BranchGuard)
|
|
|
|
|
|
|
|
### 2.2 URL map
|
|
### 2.2 URL map
|
|
|
|
|
|
|
@@ -417,7 +430,7 @@ Behavior:
|
|
|
Notes:
|
|
Notes:
|
|
|
|
|
|
|
|
- `GET /api/auth/me` returns minimal identity data for the UI:
|
|
- `GET /api/auth/me` returns minimal identity data for the UI:
|
|
|
- - `userId`, `role`, `branchId`, and (optionally) `email`.
|
|
|
|
|
|
|
+ - `userId`, `role`, `branchId`, `email`, `mustChangePassword`.
|
|
|
|
|
|
|
|
- Role is one of: `branch | admin | superadmin | dev`.
|
|
- Role is one of: `branch | admin | superadmin | dev`.
|
|
|
|
|
|
|
@@ -430,6 +443,11 @@ Behavior:
|
|
|
- While session is loading: render a minimal in-shell state.
|
|
- While session is loading: render a minimal in-shell state.
|
|
|
- On auth errors: show an in-shell error card + retry.
|
|
- On auth errors: show an in-shell error card + retry.
|
|
|
- On unauthenticated: show a short “redirecting” message while redirect happens.
|
|
- On unauthenticated: show a short “redirecting” message while redirect happens.
|
|
|
|
|
+- On authenticated + `mustChangePassword=true`:
|
|
|
|
|
+ - redirect to `/profile` unless already on `/profile`.
|
|
|
|
|
+ - preserve a safe resume target via `next`.
|
|
|
|
|
+- On authenticated + `mustChangePassword=false` and gate marker present:
|
|
|
|
|
+ - resume to `next` automatically (if present and safe).
|
|
|
|
|
|
|
|
RHL-032 note:
|
|
RHL-032 note:
|
|
|
|
|
|
|
@@ -689,10 +707,13 @@ The UI uses the API client wrappers from `lib/frontend/apiClient.js`:
|
|
|
|
|
|
|
|
- `components/profile/ProfilePage.jsx`
|
|
- `components/profile/ProfilePage.jsx`
|
|
|
- Shows read-only account/session info (role, branch, email).
|
|
- Shows read-only account/session info (role, branch, email).
|
|
|
|
|
+ - Shows required-action alert when `mustChangePassword=true`.
|
|
|
|
|
+ - Shows success alert after a successful forced password change.
|
|
|
|
|
|
|
|
- `components/profile/ChangePasswordCard.jsx`
|
|
- `components/profile/ChangePasswordCard.jsx`
|
|
|
- Calls `apiClient.changePassword({ currentPassword, newPassword })`.
|
|
- Calls `apiClient.changePassword({ currentPassword, newPassword })`.
|
|
|
- Maps password policy errors into user-friendly German hints.
|
|
- Maps password policy errors into user-friendly German hints.
|
|
|
|
|
+ - Triggers auth revalidation after success (`retry()` from AuthContext).
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
@@ -755,6 +776,10 @@ npm run build
|
|
|
- branch user → forbidden on foreign branches
|
|
- branch user → forbidden on foreign branches
|
|
|
- admin-like → notfound on non-existent branches
|
|
- admin-like → notfound on non-existent branches
|
|
|
- admin/branch → forbidden on `/admin/users`
|
|
- admin/branch → forbidden on `/admin/users`
|
|
|
|
|
+- Validate must-change-password behavior:
|
|
|
|
|
+ - new user with `mustChangePassword=true` is forced to `/profile`
|
|
|
|
|
+ - gate lifts immediately after password change (no logout/login required)
|
|
|
|
|
+ - user resumes the previously blocked protected route when `next` is available
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
@@ -764,6 +789,3 @@ npm run build
|
|
|
- delete with explicit username confirmation
|
|
- delete with explicit username confirmation
|
|
|
- branch user creation UX (fixed `NL` prefix + numeric-only input)
|
|
- branch user creation UX (fixed `NL` prefix + numeric-only input)
|
|
|
- optional branch existence check / warning when creating branch users
|
|
- optional branch existence check / warning when creating branch users
|
|
|
-
|
|
|
|
|
-- `mustChangePassword` enforcement (separate ticket):
|
|
|
|
|
- - redirect/gate until password is changed
|
|
|