Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/utils/services/shkRoles.server.ts
T

111 lines
4.5 KiB
TypeScript

import { db } from "~/utils/db.server";
// R-P2b — SHK-Standard-Rollen (vom Partner genannt). PROVISORISCH/ANPASSBAR: datengetrieben, per
// Tenant als Template geseedet (upsert, idempotent). Die fachspezifischen Rechte (CRM/Leads/Projekte/
// Auftraege) haengen sich PRO PHASE an, sobald die Entitaeten existieren; bei P2 differenzieren nur die
// bereits vorhandenen App-/Settings-Rechte. Anpassbar ueber den Rollen-Editor (D-P2) oder durch Aendern
// dieser Definition + Re-Seed. Bulk-entfernbar ueber SHK_ROLE_NAMES (is_demo_data-Konvention, bis das
// Entity-Model TenantRole.is_template_origin angeglichen ist).
export type ShkRoleTier = "admin" | "elevated" | "standard";
export interface ShkRoleSeed {
readonly name: string;
// i18n-Key im Namespace-Format `settings:<key>` (Doppelpunkt!), gespeichert in Role.description;
// der Rollen-Editor löst ihn via t() auf (roleDisplayDescription). i18next adressiert ausgelagerte
// Namespaces mit ":" -- ein Punkt-Präfix landet im defaultNS und erschiene als nackter Key. Kein
// Klartext im Seed -> erfüllt die Hardcoded-String-Disziplin; Text liegt in settings.json.
readonly descriptionKey: string;
readonly tier: ShkRoleTier;
readonly permissionKeys: readonly string[];
}
const DASHBOARD = "app.dashboard.view";
export const SHK_ROLE_SEEDS: readonly ShkRoleSeed[] = [
{
name: "Geschäftsführer",
descriptionKey: "settings:shkRoles.geschaeftsfuehrer.description",
tier: "admin",
permissionKeys: [
DASHBOARD,
"app.settings.members.view",
"app.settings.members.create",
"app.settings.members.update",
"app.settings.members.delete",
"app.settings.roles.view",
"app.settings.roles.set",
"app.settings.groups.full",
"app.settings.account.view",
"app.settings.account.update",
"app.settings.subscription.view",
"app.settings.subscription.update",
"app.settings.subscription.invoices.view",
"app.settings.auditTrails.view",
],
},
{
name: "Projektleiter",
descriptionKey: "settings:shkRoles.projektleiter.description",
tier: "elevated",
permissionKeys: [DASHBOARD, "app.settings.members.view", "app.settings.groups.full", "app.settings.auditTrails.view"],
},
{
name: "Verwaltung",
descriptionKey: "settings:shkRoles.verwaltung.description",
tier: "elevated",
permissionKeys: [DASHBOARD, "app.settings.members.view", "app.settings.account.view", "app.settings.subscription.invoices.view"],
},
{
name: "Vertriebler",
descriptionKey: "settings:shkRoles.vertriebler.description",
tier: "standard",
permissionKeys: [DASHBOARD],
},
{
name: "Kundensupporter",
descriptionKey: "settings:shkRoles.kundensupporter.description",
tier: "standard",
permissionKeys: [DASHBOARD],
},
{
name: "Monteur",
descriptionKey: "settings:shkRoles.monteur.description",
tier: "standard",
permissionKeys: [DASHBOARD],
},
];
export const SHK_ROLE_NAMES: readonly string[] = SHK_ROLE_SEEDS.map((role) => role.name);
// Seedt die SHK-Rollen als App-Rollen eines Tenants (idempotent). Setzt fehlende Rollen + ihre
// vorhandenen Permission-Verknuepfungen auf; bestehende bleiben unberuehrt (anpassbar im Editor).
export async function seedShkRolesForTenant(tenantId: string): Promise<{ createdRoles: number }> {
const wantedKeys = [...new Set(SHK_ROLE_SEEDS.flatMap((role) => role.permissionKeys))];
const permissions = await db.permission.findMany({ where: { name: { in: wantedKeys } }, select: { id: true, name: true } });
const permissionIdByName = new Map(permissions.map((permission) => [permission.name, permission.id]));
let createdRoles = 0;
for (const [index, seed] of SHK_ROLE_SEEDS.entries()) {
let role = await db.role.findFirst({ where: { tenantId, name: seed.name, type: "app" }, select: { id: true } });
if (!role) {
role = await db.role.create({
data: { tenantId, name: seed.name, description: seed.descriptionKey, type: "app", assignToNewUsers: false, isDefault: false, order: 100 + index },
select: { id: true },
});
createdRoles++;
}
for (const key of seed.permissionKeys) {
const permissionId = permissionIdByName.get(key);
if (!permissionId) {
continue;
}
const existing = await db.rolePermission.findFirst({ where: { roleId: role.id, permissionId } });
if (!existing) {
await db.rolePermission.create({ data: { roleId: role.id, permissionId } });
}
}
}
return { createdRoles };
}