Files
slp-modular-cms/aidlc-docs/features/cms-frontend/construction/unit-5/functional-design/business-rules.md
T
2026-06-22 21:14:22 +02:00

4.9 KiB

Business Rules — Unit 5: User Management

Rule Index

ID Rule Enforced In
BR-U5-01 Only Owner and Administrator can access UsersPage Frontend (RoleGuard), Backend (AdminOnly policy)
BR-U5-02 Owner role cannot be assigned via invitation Frontend (role selector), Backend
BR-U5-03 At least one Owner must exist at all times Backend (change role endpoint)
BR-U5-04 Owner can change any user's role (subject to BR-U5-03) Backend (change role endpoint)
BR-U5-05 Administrator can only promote User to Administrator Backend (change role endpoint)
BR-U5-06 Copy invite link action is only shown for users where invitationPending = true Frontend (conditional rendering)
BR-U5-07 Invite form requires valid email format and role selection Frontend (zod validation)
BR-U5-08 An email already registered cannot be invited again Backend (invite endpoint validation)

Decision Flow 1 — Invite User Authorization

graph TD
    invite_req["Invite User request"]
    check_access{"Requester is Owner\nor Administrator?"}
    check_email{"Email has valid format?"}
    check_registered{"Email already registered?"}
    check_role{"Role is Administrator\nor User?"}
    success_invite["Create invitation token\nReturn inviteLink"]
    deny_403["403 Forbidden"]
    err_email["Validation error\nInvalid email format"]
    err_registered["Validation error\nEmail already in use"]
    err_role["Validation error\nOwner role cannot be invited"]

    invite_req --> check_access
    check_access -->|No| deny_403
    check_access -->|Yes| check_email
    check_email -->|No| err_email
    check_email -->|Yes| check_registered
    check_registered -->|Yes| err_registered
    check_registered -->|No| check_role
    check_role -->|Owner| err_role
    check_role -->|Administrator or User| success_invite

    classDef start_node fill:#2196F3,stroke:#0d47a1,stroke-width:1px,color:#000
    classDef decision_node fill:#FF9800,stroke:#e65100,stroke-width:1px,color:#000
    classDef success_node fill:#4CAF50,stroke:#2e7d32,stroke-width:1px,color:#000
    classDef error_node fill:#F44336,stroke:#b71c1c,stroke-width:1px,color:#000

    class invite_req start_node
    class check_access,check_email,check_registered,check_role decision_node
    class success_invite success_node
    class deny_403,err_email,err_registered,err_role error_node

Text alternative: Invite request checked for requester access, email validity, registration status, and role — only valid Administrator/User invites proceed; all others are blocked.


Decision Flow 2 — Change Role Authorization

graph TD
    change_req["Change Role request\nPUT /Users/{userId}/role"]
    req_role{"Requester role?"}
    deny_user["403 Forbidden\nUser role cannot change roles"]
    admin_target{"Target user's current role?"}
    deny_admin["403 Forbidden\nAdmin cannot change Owner or Admin roles"]
    owner_check{"Would this leave\nzero Owners?"}
    deny_last["Blocked\nAt least 1 Owner required"]
    success_change["Update user role\nReturn 200 OK"]

    change_req --> req_role
    req_role -->|User| deny_user
    req_role -->|Administrator| admin_target
    req_role -->|Owner| owner_check
    admin_target -->|Owner or Administrator| deny_admin
    admin_target -->|User| success_change
    owner_check -->|Yes| deny_last
    owner_check -->|No| success_change

    classDef start_node fill:#2196F3,stroke:#0d47a1,stroke-width:1px,color:#000
    classDef decision_node fill:#FF9800,stroke:#e65100,stroke-width:1px,color:#000
    classDef success_node fill:#4CAF50,stroke:#2e7d32,stroke-width:1px,color:#000
    classDef error_node fill:#F44336,stroke:#b71c1c,stroke-width:1px,color:#000

    class change_req start_node
    class req_role,admin_target,owner_check decision_node
    class success_change success_node
    class deny_user,deny_admin,deny_last error_node

Text alternative: Role change checked for requester level — User is blocked; Administrator can only change User-role targets; Owner can change any role, blocked only if it would leave zero Owners.


Frontend Validation Rules (InviteUserForm — zod schema)

const inviteUserSchema = z.object({
    email: z.string().email({ message: 'Valid email address required' }),
    role: z.enum(['Administrator', 'User'], {
        required_error: 'Role selection is required',
    }),
});

Frontend Access Control Rules (RoleGuard / conditional rendering)

Element Visibility condition
UsersPage route role === 'Owner' || role === 'Administrator'
Invite User button Always visible on UsersPage (same role requirement as page)
Copy invite link action user.invitationPending === true
Change role dropdown Visible to all UsersPage visitors; available target roles differ by requester role (see BR-U5-04, BR-U5-05)
Owner option in role dropdown Only shown when requester is Owner