export const ROLES = { CITIZEN: 'CITIZEN', OPERATOR: 'OPERATOR', ADMIN: 'ADMIN' } as const export type Role = keyof typeof ROLES export type NegatedRole = `!${Role}` export type MetaRoleRequirement = Role | NegatedRole | Array export const ROLE_LEVELS: Record = { [ROLES.CITIZEN]: 1, [ROLES.OPERATOR]: 2, [ROLES.ADMIN]: 3 } export function normalizeRole(role?: string | null): string { return role?.trim().toUpperCase() ?? '' } export function isRole(userRole: string | undefined | null, targetRole: string): boolean { return normalizeRole(userRole) === normalizeRole(targetRole) } export function hasMinimumRole(userRole: string | undefined | null, requiredRole: string): boolean { const userLvl = ROLE_LEVELS[normalizeRole(userRole)] || 0 const reqLvl = ROLE_LEVELS[normalizeRole(requiredRole)] || 0 return userLvl >= reqLvl } export function isAdmin(userRole?: string | null): boolean { return isRole(userRole, ROLES.ADMIN) } export function isOperator(userRole?: string | null): boolean { return isRole(userRole, ROLES.OPERATOR) } export function isCitizen(userRole?: string | null): boolean { return isRole(userRole, ROLES.CITIZEN) } export function canAccess(userRole: string | undefined | null, requiredRole: string): boolean { return hasMinimumRole(userRole, requiredRole) } export function checkRoleAccess(userRole: string | undefined | null, requirement: MetaRoleRequirement | undefined): boolean { if (!requirement) return true const normalizedUserRole = normalizeRole(userRole) if (!normalizedUserRole) return false const requirements = Array.isArray(requirement) ? requirement : [requirement] for (const req of requirements) { const isNegated = req.startsWith('!') const rawTarget = isNegated ? req.substring(1) : req const targetRole = normalizeRole(rawTarget) if (isNegated) { console.log("negated", normalizedUserRole, targetRole) if (normalizedUserRole === targetRole) { return false } } else { if (!hasMinimumRole(normalizedUserRole, targetRole)) { return false } } } return true }