Organization, Roles & Permissions
NexusOne's master authorization model: a 16-role catalog with a cascading hierarchy, enforced entirely through route-level role checks and school-scoped queries rather than a separate permission engine. This chapter covers how roles are assigned, how staff and students are onboarded, how cross-school access is granted, and how each role's dashboard and API access is gated. Entirely Basic tier.
Basic Tier Features
BasicRole Catalog & Hierarchy
- 11 roles today: platform_admin, super_admin, admin, teacher, student, parent, accountant, librarian, facilities_admin, driver, alumni — matching the original BRD catalog
- ROLE_HIERARCHY (utils/roleHierarchy.js) is a static, in-memory cascade — platform_admin satisfies every role, super_admin satisfies admin and everything under it, admin satisfies teacher/accountant/librarian/facilities_admin
- hasRole(userRole, requiredRoles) is a pure object lookup — no database query is made to authorize a request
Route-Level Authorization
- authorize(...roles) middleware is applied per-route, e.g. authorize('admin', 'super_admin') — it is the actual permission mechanism; there is no separate Module.Action permission-string engine implemented
- belongsToSchool() and requireSchool() add tenant-scope checks on top of the role check for routes keyed by a specific school
- ownerOrAdmin allows a user to act on their own resource, or an admin/super_admin/platform_admin to act within their school(s)
- getSchoolFilter(req) is the canonical tenant-isolation helper: {} for platform_admin, { school: { $in: schools } } for super_admin, { school } for every other role
User & Staff Creation
- Admins create staff/student accounts with a generated temporary password; students get an auto studentId, staff get an auto employeeId
- Super Admin must supply schoolId explicitly when creating a user (they can operate across several owned schools); Admin implicitly uses their own school
- POST /api/users/invite sends an email invitation with a temporary password (isTemporaryPassword forces a change on first login)
- Every account status change (suspend/activate/archive) and unlock is written to AuditLog
Multi-School & Cross-Tenant Access Grants
- Platform Admin can grant or revoke any user's access to additional schools via the schools[] array
- Platform Admin creates Super Admin accounts and assigns/revokes which schools each Super Admin owns
- A user's active school and school history stay in sync via a pre-save hook on the User model
Role-Based Dashboards
- Each role lands on its own dashboard route after login (admin, teacher, student, parent, super_admin, platform_admin), resolved client-side from the authenticated user's role
- Screen-level guards (useAuth() + ProtectedRoute) redirect unauthorized access attempts to /login
- Admin UI for staff/role management: /dashboard/admin/users, /dashboard/admin/teachers
Approval & Data Ownership Model
- School creation requires Platform Admin approval; student admission, teacher creation, and transfers require Admin approval
- Fee discounts require Accountant + Admin sign-off; scholarships require Admin approval
- Bulk data export is restricted to admin, super_admin, accountant, and platform_admin roles, all logged in the audit trail
Still Planned
Still Planned
- Delegation model (e.g. temporary "Exam Coordinator" or "Attendance Coordinator" grants) — specified in the BRD, no delegation code exists yet; roles remain fixed via the role enum
- Additional future roles from the BRD roadmap: Admissions Counselor (CRM-specific), Hostel Warden, Coach, Mentor, Recruiter
- A dedicated granular Module.Action permission engine — today, access control is entirely role + route + school-scope based
Role Hierarchy (utils/roleHierarchy.js)
| Role | Also Satisfies (effective access) |
|---|---|
| platform_admin | All 11 roles |
| super_admin | admin, accountant, facilities_admin, librarian, teacher |
| admin | accountant, facilities_admin, librarian, teacher |
| teacher | |
| accountant / facilities_admin / librarian / driver / student / parent / alumni | Itself only — no further cascade |
API Reference — Chapter 4
Admin — Staff & User Management (/api/admin)
/api/admin/usersCreate a staff/student user (admin, super_admin); role restricted to admin, teacher, student, parent, accountant, librarian
/api/admin/usersPaginated, searchable user list scoped to the requester's school(s)
/api/admin/studentsList students (admin, super_admin)
/api/admin/parents/:parentId/link-studentsLink a parent account to one or more student accounts
/api/admin/parents/:parentId/childrenGet a parent's linked children
User Self-Service & Admin Actions (/api/users)
/api/usersList users in school (admin, super_admin)
/api/users/:idUpdate a user; admin may also change role, isActive, verification flags
/api/users/:id/statusSuspend / activate / archive a user account (admin)
/api/users/inviteInvite a new staff/student user by email (admin)
/api/users/:idDeactivate a user (admin)
/api/users/role/:roleList active users of a given role (admin)
Super Admin — Cross-School Role Management
/api/super-admin/usersAll users across owned schools (auth: protect + platform_admin — see note below)
/api/super-admin/users/:id/roleChange a user's role within owned schools (auth: protect + platform_admin — see note below)
/api/super-admin/school-adminsList school admin accounts
/api/super-admin/school-adminsCreate a school admin account; accepts schoolIds[] to attach the admin to multiple schools at once
/api/super-admin/school-admins/:idUpdate a school admin, including reassigning their schoolIds[]
/api/super-admin/coursesCourses across the requesting super_admin's assigned schools
/api/school-access/:id/schoolsGrant any user (admin, teacher, etc.) access to additional schools — used by the Manage School Access modal in Global User Management
/api/school-access/:id/schools/:schoolIdRevoke a user's access to one school
Platform Admin — Full-Platform Role Management
/api/platform-admin/usersAll users across all tenants
/api/platform-admin/users/:id/statusActivate or deactivate any user
/api/platform-admin/users/:id/schoolsGrant a user access to an additional school
/api/platform-admin/users/:id/schools/:schoolIdRevoke a user's access to a school
/api/super-admin/* router is gated by requireSuperAdmin, which the codebase currently defines as a backward-compatible alias for requirePlatformAdmin (an exact-role check, not the role-hierarchy cascade). In practice this means these endpoints require the platform_admin role today, not super_admin.admin and teacher accounts (not just super_admin) can belong to more than one school via User.schools[], set either at admin creation/update (schoolIds) or per-user afterwards via the Manage School Access modal (/api/school-access/:id/schools). User.school is the currently-active school; users switch it via PATCH /api/school-access/me/active-school, exposed as a school switcher in the web header and mobile home screen once a user has more than one assigned school. Every school-scoped controller now resolves the active school through a shared req.activeSchoolId (set by resolveActiveSchool middleware), so switching schools actually changes what data every screen shows — previously many endpoints silently ignored the switch and kept scoping to the user's original school.Frontend Pages
| Path | Role | Description | Tier |
|---|---|---|---|
| /dashboard/admin/users | Admin | User list, create, role/status management, invites | Basic |
| /dashboard/admin/teachers | Admin | Teacher roster and profile management | Basic |
| /dashboard/admin/iam | Admin | IAM audit log and account-lock management | Basic |
| /dashboard/super-admin/school-admins | Super Admin | Create and manage school admin accounts; assign each admin to multiple schools | Basic |
| /dashboard/super-admin/users | Super Admin | Users across all owned schools | Basic |
| /dashboard/super-admin/students | Super Admin | Active students across all owned schools | Basic |
| /dashboard/super-admin/courses | Super Admin | Courses across all owned schools | Basic |
| /dashboard/super-admin/activity | Super Admin | Full recent-activity log across owned schools | Basic |
| /dashboard/platform-admin/super-admins | Platform Admin | Create Super Admins, grant/revoke school access | Basic |
Mobile Screens
(platform-admin)/super-admins(platform-admin)/school-assignment(admin)/iam-security