mirror of
https://github.com/hanzoai/calendar.git
synced 2026-10-30 14:46:43 +00:00
121 lines
4.1 KiB
TypeScript
121 lines
4.1 KiB
TypeScript
import type { TeamPermissions, Permission } from "../models/Permission";
|
|
import { CrudAction, CustomAction, Resource, PERMISSION_REGISTRY } from "../types/permission-registry";
|
|
import type { PermissionString, PermissionRegistry } from "../types/permission-registry";
|
|
|
|
export type ResourceActions<R extends Resource> = keyof PermissionRegistry[R];
|
|
|
|
export class PermissionMapper {
|
|
static toDomain(
|
|
dbPermissions: {
|
|
teamId: number;
|
|
role: {
|
|
id: string | null;
|
|
permissions: { resource: string | null; action: string | null }[];
|
|
} | null;
|
|
}[]
|
|
): TeamPermissions[] {
|
|
return dbPermissions
|
|
.filter(
|
|
(membership) =>
|
|
membership.teamId != null && membership.role?.id != null && membership.role.permissions
|
|
)
|
|
.map((membership) => ({
|
|
teamId: membership.teamId,
|
|
roleId: membership.role!.id!,
|
|
permissions: membership
|
|
.role!.permissions.filter(
|
|
(p): p is { resource: string; action: string } =>
|
|
typeof p.resource === "string" &&
|
|
typeof p.action === "string" &&
|
|
p.resource !== null &&
|
|
p.action !== null
|
|
)
|
|
.map((p) => ({
|
|
resource: p.resource as Resource,
|
|
action: p.action as CrudAction | CustomAction,
|
|
})),
|
|
}));
|
|
}
|
|
|
|
static toPermissionString(permission: Permission): PermissionString {
|
|
return `${permission.resource}.${permission.action}` as PermissionString;
|
|
}
|
|
|
|
static fromPermissionString(permissionString: PermissionString): Permission {
|
|
if (!permissionString || typeof permissionString !== "string" || !permissionString.includes(".")) {
|
|
throw new Error(`Invalid permission format: ${permissionString}`);
|
|
}
|
|
|
|
// Split from the right side to handle resources with dots
|
|
const lastDotIndex = permissionString.lastIndexOf(".");
|
|
const resource = permissionString.substring(0, lastDotIndex);
|
|
const action = permissionString.substring(lastDotIndex + 1);
|
|
|
|
if (!resource || !action) {
|
|
throw new Error(`Invalid permission format: ${permissionString}`);
|
|
}
|
|
|
|
return {
|
|
resource: resource as Resource,
|
|
action: action as CrudAction | CustomAction,
|
|
};
|
|
}
|
|
|
|
static toActionMap<R extends Resource>(
|
|
permissions: PermissionString[],
|
|
resource: R
|
|
): Record<ResourceActions<R>, boolean> {
|
|
const actionMap = {} as Record<ResourceActions<R>, boolean>;
|
|
|
|
// Initialize all actions as false
|
|
Object.values(CrudAction).forEach((action) => {
|
|
if (action !== CrudAction.All && this.isActionAvailableForResource(resource, action)) {
|
|
actionMap[action as ResourceActions<R>] = false;
|
|
}
|
|
});
|
|
Object.values(CustomAction).forEach((action) => {
|
|
if (this.isActionAvailableForResource(resource, action)) {
|
|
actionMap[action as ResourceActions<R>] = false;
|
|
}
|
|
});
|
|
|
|
// Set permitted actions to true
|
|
permissions.forEach((permString) => {
|
|
try {
|
|
// Check for *.* first as it grants all permissions
|
|
if (permString === `${Resource.All}.${CrudAction.All}`) {
|
|
Object.keys(actionMap).forEach((key) => {
|
|
actionMap[key as ResourceActions<R>] = true;
|
|
});
|
|
return;
|
|
}
|
|
|
|
const { action, resource: permResource } = this.fromPermissionString(permString);
|
|
|
|
// Only process permissions for the requested resource
|
|
if (permResource === resource || permResource === Resource.All) {
|
|
if (action === CrudAction.All) {
|
|
// If wildcard action, set all available actions to true
|
|
Object.keys(actionMap).forEach((key) => {
|
|
actionMap[key as ResourceActions<R>] = true;
|
|
});
|
|
} else if (this.isActionAvailableForResource(resource, action)) {
|
|
actionMap[action as ResourceActions<R>] = true;
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error(`Invalid permission string: ${permString}`);
|
|
}
|
|
});
|
|
|
|
return actionMap;
|
|
}
|
|
|
|
private static isActionAvailableForResource(
|
|
resource: Resource,
|
|
action: CrudAction | CustomAction
|
|
): boolean {
|
|
return !!PERMISSION_REGISTRY[resource]?.[action];
|
|
}
|
|
}
|