52 lines
1.3 KiB
TypeScript
52 lines
1.3 KiB
TypeScript
export const ROLES = ["viewer", "operator", "admin"] as const;
|
|
export type Role = (typeof ROLES)[number];
|
|
|
|
export const CAPABILITIES = [
|
|
"kubernetes:read",
|
|
"kubernetes:write",
|
|
"kubernetes:exec",
|
|
"users:read",
|
|
"users:write",
|
|
"sessions:revoke",
|
|
"platform:adopt",
|
|
] as const;
|
|
export type Capability = (typeof CAPABILITIES)[number];
|
|
|
|
const ROLE_CAPABILITIES: Readonly<Record<Role, readonly Capability[]>> = {
|
|
viewer: ["kubernetes:read"],
|
|
operator: ["kubernetes:read", "kubernetes:write", "kubernetes:exec"],
|
|
admin: CAPABILITIES,
|
|
};
|
|
|
|
export function isRole(value: unknown): value is Role {
|
|
return (
|
|
typeof value === "string" && (ROLES as readonly string[]).includes(value)
|
|
);
|
|
}
|
|
|
|
export function isCapability(value: unknown): value is Capability {
|
|
return (
|
|
typeof value === "string" &&
|
|
(CAPABILITIES as readonly string[]).includes(value)
|
|
);
|
|
}
|
|
|
|
export function capabilitiesForRoles(
|
|
roles: readonly string[],
|
|
): ReadonlySet<Capability> {
|
|
const capabilities = new Set<Capability>();
|
|
for (const role of roles) {
|
|
if (!isRole(role)) continue;
|
|
for (const capability of ROLE_CAPABILITIES[role])
|
|
capabilities.add(capability);
|
|
}
|
|
return capabilities;
|
|
}
|
|
|
|
export function hasCapability(
|
|
roles: readonly string[],
|
|
capability: Capability,
|
|
): boolean {
|
|
return capabilitiesForRoles(roles).has(capability);
|
|
}
|