/** * Keeps the server and the client agreed on what each role may do. The server * enforces this table (`api/lib/permissions.ts`, `api/routes/ws.ts`) and the * client reads the same one to hide what a role can't do * (`src/utils/auth/permissions.ts`). * * @module */ import type { Role } from "./user.ts"; /** * An action only some roles may take. A new one goes in this union and in * `ALL_PERMISSIONS`, which is what grants it to admins. */ export type Permission = | "dump:moderate" | "comment:moderate" | "playlist:moderate" | "chat:moderate" | "chat:everyone" | "user:manage" | "category:manage"; const ALL_PERMISSIONS: readonly Permission[] = [ "dump:moderate", "comment:moderate", "playlist:moderate", "chat:moderate", "chat:everyone", "user:manage", "category:manage", ]; /** * Read through {@link hasPermission}. Roles are fixed in code. An admin holds * every permission, and a moderator the moderation ones and `@everyone` in * the chat. */ export const ROLE_PERMISSIONS: Record = { admin: ALL_PERMISSIONS, moderator: [ "dump:moderate", "comment:moderate", "playlist:moderate", "chat:moderate", "chat:everyone", ], user: [], }; /** * Checks whether `role` grants `permission`. The server's `can` and the * client's `can` both wrap it. */ export function hasPermission(role: Role, permission: Permission): boolean { return ROLE_PERMISSIONS[role].includes(permission); }