54 lines
1.3 KiB
TypeScript
54 lines
1.3 KiB
TypeScript
/**
|
|
* Maps each role to what it may do. The server enforces the 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"
|
|
| "user:manage"
|
|
| "category:manage";
|
|
|
|
const ALL_PERMISSIONS: readonly Permission[] = [
|
|
"dump:moderate",
|
|
"comment:moderate",
|
|
"playlist:moderate",
|
|
"chat:moderate",
|
|
"user:manage",
|
|
"category:manage",
|
|
];
|
|
|
|
/**
|
|
* Read through {@link hasPermission}. Roles are fixed in code. An admin holds
|
|
* every permission, and a moderator the moderation ones only.
|
|
*/
|
|
export const ROLE_PERMISSIONS: Record<Role, readonly Permission[]> = {
|
|
admin: ALL_PERMISSIONS,
|
|
moderator: [
|
|
"dump:moderate",
|
|
"comment:moderate",
|
|
"playlist:moderate",
|
|
"chat:moderate",
|
|
],
|
|
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);
|
|
}
|