4.7 KiB
4.7 KiB
Business Rules — Unit 6: Profile, Settings & CMS Placeholder
Access Control Rules
graph TD
Request["Incoming Route Request"]
IsAuth{"Authenticated?"}
Route{"Which route?"}
IsOwner{"Role = Owner?"}
AccessDenied["403 AccessDeniedPage"]
NotFound["404 NotFoundPage"]
Profile["ProfilePage"]
Settings["SettingsPage"]
Cms["CmsPage"]
Login["Redirect to /login"]
Request --> IsAuth
IsAuth -->|No| Login
IsAuth -->|Yes| Route
Route -->|/profile| Profile
Route -->|/settings| IsOwner
Route -->|/cms| IsOwner
Route -->|unknown path| NotFound
IsOwner -->|Yes| Settings
IsOwner -->|Yes| Cms
IsOwner -->|No| AccessDenied
classDef guard fill:#FF9800,stroke:#e65100,color:#000
classDef page fill:#2196F3,stroke:#0d47a1,color:#000
classDef error fill:#F44336,stroke:#b71c1c,color:#000
classDef start fill:#9C27B0,stroke:#4a148c,color:#000
class IsAuth guard
class IsOwner guard
class Route guard
class Profile page
class Settings page
class Cms page
class AccessDenied error
class NotFound error
class Login error
class Request start
Text alternative: All routes require authentication (redirect to /login if not). /settings and /cms additionally require Owner role; non-Owners are shown 403. Unknown paths show 404.
BR-01: Profile Access
- Rule: Any authenticated user can access
/profile - Implementation: ProfilePage is a child of
_authenticated.tsx(inherits ProtectedRoute); no additional RoleGuard - Data: Profile data is read from AuthContext (no extra API call for display)
BR-02: Profile — Name and Email are Editable
- Rule: The logged-in user may update their own
nameandemail - Validation (frontend, mirrors backend):
name: required, non-emptyemail: required, valid email format
- Endpoint:
PUT /api/v1/Users/me - After save: Call
POST /api/v1/Auth/refreshto synchronize AuthContext with updated values
BR-03: Profile — Role is Read-Only
- Rule: A user cannot change their own role from the profile page
- Display: Role shown as a static badge; no edit controls rendered
BR-04: Change Password
- Rule: The logged-in user may change their own password via a dialog on ProfilePage
- Validation (frontend, mirrors backend password policy):
currentPassword: required, non-emptynewPassword: required, min 8 chars, at least 1 uppercase, 1 lowercase, 1 digit, 1 special characterconfirmPassword(UI-only field): must matchnewPassword
- Endpoint:
POST /api/v1/Auth/change-password - On success: Close dialog, show success toast; no AuthContext update needed (password change does not affect access token)
BR-05: Settings — Owner Only
- Rule: Only users with role
Ownermay access/settings - Implementation:
RoleGuardwithallowedRoles={["Owner"]}wraps SettingsPage - On violation: Redirect to
/403
BR-06: Settings — Availability Management
- Rule: Owner may change the system availability status from SettingsPage
- Allowed modes:
Available,Maintenance,Unavailable - Endpoint:
POST /api/v1/Availability/admin/status(OwnerOnly — already enforced by backend) - Message field: Optional free-text reason displayed to end-users
- On save: Invalidate
useAvailabilityStatusquery cache to reflect new status immediately
BR-07: CMS Page — Owner Only
- Rule: Only users with role
Ownermay access/cms - Implementation:
RoleGuardwithallowedRoles={["Owner"]}wraps CmsPage - On violation: Redirect to
/403 - Content: Placeholder only — no functional CMS features in this unit
BR-08: 403 Access Denied Page
- Rule: Rendered when
RoleGuardrejects a route request - Content: Heading "Access Denied" + explanatory message + "Back to Dashboard" button (navigates to
/) - No authentication required: 403 is a public route (unauthenticated users hitting protected routes are redirected to
/loginby ProtectedRoute first)
BR-09: 404 Not Found Page
- Rule: Rendered when TanStack Router cannot match any registered route
- Content: Heading "Page Not Found" + brief message + "Back to Dashboard" button (navigates to
/) - Implementation: TanStack Router catch-all route (
$404.tsx)
BR-10: Backend — New Endpoints Required
The following new backend endpoints must be added as part of Unit 6:
| Endpoint | Method | Policy | Purpose |
|---|---|---|---|
/api/v1/Users/me |
PUT | Authenticated | Update own name and email |
/api/v1/Auth/change-password |
POST | Authenticated | Change own password |
Both endpoints operate on the currently authenticated user (identified via JWT claims).