Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/utils/db/permissions/permissions.db.server.ts
T

255 lines
6.7 KiB
TypeScript

import { db } from "../../db.server";
import { Entity, Permission, Role, RolePermission } from "@toolctrl/db/prisma-browser";
import { getAllRolesNames, getRoleByName } from "./roles.db.server";
import { createRolePermission, getAllRolePermissions } from "./rolePermissions.db.server";
import RowFiltersHelper from "~/utils/helpers/RowFiltersHelper";
import { FiltersDto } from "~/application/dtos/data/FiltersDto";
import { getEntityPermissions } from "~/utils/helpers/PermissionsHelper";
import { cachified, clearCacheKey } from "~/utils/cache.server";
import { createScopedLogger } from "~/utils/logger.server";
const permissionsLogger = createScopedLogger("db.permissions");
export type PermissionWithRoles = Permission & {
inRoles: (RolePermission & { role: Role })[];
};
export async function getAllPermissions(type?: string, filters?: FiltersDto): Promise<PermissionWithRoles[]> {
let where: any = {
type,
};
if (filters) {
where = RowFiltersHelper.getFiltersCondition(filters);
const roleId = filters?.properties.find((f) => f.name === "roleId")?.value;
if (roleId) {
where = {
OR: [where, { inRoles: { some: { roleId } } }],
};
}
if (type !== undefined) {
where = {
AND: [type, where],
};
}
}
return await db.permission.findMany({
where,
include: {
inRoles: {
include: {
role: true,
},
},
},
orderBy: [{ type: "asc" }, { name: "asc" }],
});
}
export async function getAllPermissionsIdsAndNames(): Promise<{ id: string; name: string }[]> {
return await db.permission.findMany({
select: { id: true, name: true },
orderBy: { name: "asc" },
});
}
export async function getPermission(id: string): Promise<PermissionWithRoles | null> {
return await db.permission.findUnique({
where: {
id,
},
include: {
inRoles: {
include: {
role: true,
},
},
},
});
}
export async function getPermissionByName(name: string): Promise<PermissionWithRoles | null> {
return await db.permission.findUnique({
where: {
name,
},
include: {
inRoles: {
include: {
role: true,
},
},
},
});
}
export async function getPermissionName(name: string): Promise<{ id: string; name: string; description: string } | null> {
return await cachified({
key: `permission:${name}`,
ttl: 1000 * 60 * 60 * 24,
getFreshValue: () =>
db.permission.findUnique({
where: {
name,
},
select: { id: true, name: true, description: true },
}),
});
}
export async function getPermissionByNames(names: string[]): Promise<PermissionWithRoles[]> {
return await db.permission.findMany({
where: {
name: {
in: names,
},
},
include: {
inRoles: {
include: {
role: true,
},
},
},
});
}
export async function getNextPermissionsOrder(type?: string): Promise<number> {
let where = {};
if (type !== undefined) {
where = {
type,
};
}
return (
((
await db.permission.aggregate({
where,
_max: {
order: true,
},
})
)._max.order ?? 0) + 1
);
}
export async function createPermissions(
permissions: { inRoles: string[]; name: string; description: string; type: string; entityId?: string | null }[],
fromOrder: number = 0
) {
const allRolePermissions = await getAllRolePermissions();
const allPermissions = await getAllPermissions();
const permissionByName = new Map<string, { id: string; name: string }>(allPermissions.map((permission) => [permission.name, permission]));
const createdPermissionNames = new Set<string>();
for (const [idx, data] of permissions.entries()) {
const existing = permissionByName.get(data.name);
if (createdPermissionNames.has(data.name)) {
permissionsLogger.info({ permission: data.name }, "Permission already exists");
continue;
}
const permission =
existing ??
(await createPermission({
order: fromOrder + idx + 1,
name: data.name,
description: data.description,
type: data.type,
isDefault: true,
entityId: data.entityId ?? null,
}));
createdPermissionNames.add(permission.name);
if (existing) {
permissionsLogger.info({ permission: data.name }, "Permission already exists");
} else {
permissionByName.set(permission.name, permission);
clearCacheKey(`permission:${permission.name}`);
}
await Promise.all(
data.inRoles.map(async (inRole) => {
const role = await getRoleByName(inRole);
if (!role) {
throw new Error("Role required: " + inRole);
}
const existing = allRolePermissions.find((p) => p.roleId === role.id && p.permission.name === permission.name);
if (existing) {
return existing;
}
return await createRolePermission({
permissionId: permission.id,
roleId: role.id,
});
})
);
}
}
export async function createPermission(data: { order: number; name: string; description: string; type: string; isDefault: boolean; entityId: string | null }) {
return await db.permission.create({
data,
});
}
export async function updatePermission(
id: string,
data: {
name?: string;
description?: string;
type?: string;
order?: number;
}
) {
return await db.permission
.update({
where: { id },
data,
})
.then((item) => {
clearCacheKey(`permission:${item.name}`);
return item;
});
}
export async function deletePermission(id: string) {
return await db.permission
.delete({
where: { id },
})
.then((item) => {
clearCacheKey(`permission:${item.name}`);
return item;
});
}
export async function deleteEntityPermissions(entity: Entity) {
const entityPermissions = await getEntityPermissions(entity);
const names = entityPermissions.map((p) => p.name);
if (names.length > 0) {
return await db.permission.deleteMany({
where: {
name: {
in: names,
},
},
});
}
}
export async function createEntityPermissions(entity: Entity) {
const allUserRoles = await getAllRolesNames();
// const assignToAllUserRoles = allUserRoles.filter((f) => f.assignToNewUsers);
const entityPermissions = await getEntityPermissions(entity);
await Promise.all(
entityPermissions.map(async (permission, idx) => {
const entityPermission = {
inRoles: allUserRoles.map((f) => f.name),
name: permission.name,
description: permission.description,
type: "app",
entityId: entity.id,
};
return await createPermissions([entityPermission], allUserRoles.length + idx);
})
);
}