111 lines
4.5 KiB
TypeScript
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 };
|
|
}
|