Files
slp-modular-cms/aidlc-docs/features/cms-frontend/construction/unit-6/functional-design/business-rules.md
T

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 name and email
  • Validation (frontend, mirrors backend):
    • name: required, non-empty
    • email: required, valid email format
  • Endpoint: PUT /api/v1/Users/me
  • After save: Call POST /api/v1/Auth/refresh to 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-empty
    • newPassword: required, min 8 chars, at least 1 uppercase, 1 lowercase, 1 digit, 1 special character
    • confirmPassword (UI-only field): must match newPassword
  • 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 Owner may access /settings
  • Implementation: RoleGuard with allowedRoles={["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 useAvailabilityStatus query cache to reflect new status immediately

BR-07: CMS Page — Owner Only

  • Rule: Only users with role Owner may access /cms
  • Implementation: RoleGuard with allowedRoles={["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 RoleGuard rejects 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 /login by 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).