import { isly } from "isly" import { typedly } from "typedly" import { zod } from "../../zod" export type Permission = zod.infer export namespace Permission { export type Realm = Record export type Global = Record export function check(constraint: Permission, privilege: Permission): boolean { return typedly.Object.entries(constraint).every( ([collection, level]) => Permission.Level.get(privilege[collection]) >= Permission.Level.get(level) || (collection != "user" && Permission.Level.get(privilege["*"]) >= Permission.Level.get(level)) ) } export type Level = zod.infer export namespace Level { export const values = ["read", "write", "developer", "admin"] as const export const typeZod = zod.enum(values) export const type = isly.string(values) export function get(level: Level | undefined): number { return level ? value[level] : 0 } export const value: Record = { read: 1, write: 2, developer: 3, admin: 4, } as const } export type Collection = zod.infer export namespace Collection { export type Realm = (typeof Realm.values)[number] export namespace Realm { export const values = [ "*", "card", "log", "operation", "organization", "rule", // realm rules "settlement", "transaction", "treasury", ] as const } export type Global = (typeof Global.values)[number] export namespace Global { export const values = ["user"] as const } export const values = [...Realm.values, ...Global.values] as const export const typeZod = zod.enum(values) export const type = isly.string(values) } export const type = isly.record(Collection.type, Level.type) export const typeZod = zod.partialRecord(Collection.typeZod, Level.typeZod) }