Basis: Certvia dev@a48c5fb als Fundament für Craftvia
Unveränderter Stand von certvia/dev (a48c5fb) plus Craftvia-Spezifikation und Brandbook unter docs/craftvia/. ISMS-Module werden im Folgecommit entfernt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
// Rollen-Rechte-Sync (Wartung): gleicht die Rollen→Rechte-Zuordnung ALLER bestehenden
|
||||
// Mandanten mit dem aktuellen Rechtekatalog (ROLE_DEFS) ab. Nötig, weil Rechte bei der
|
||||
// Provisionierung in die DB geschrieben werden — neu hinzugekommene Rechte (z. B.
|
||||
// `onboarding:use`, `validate_objects`) fehlen bestehenden Mandanten sonst, bis dieses
|
||||
// Skript läuft. Rein additiv (entfernt keine bestehenden Zuordnungen).
|
||||
//
|
||||
// Lauf (lokal): npx tsx scripts/sync-role-permissions.ts
|
||||
// Lauf (Deploy): im Container/Coolify mit gesetzter DATABASE_URL ausführen.
|
||||
// WICHTIG: Betroffene Nutzer müssen sich danach neu einloggen (Rechte werden im JWT
|
||||
// beim Login aufgelöst).
|
||||
|
||||
import "dotenv/config"; // lädt DATABASE_URL aus .env beim lokalen `npx tsx`-Lauf
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import { PrismaPg } from "@prisma/adapter-pg";
|
||||
import { PERMISSIONS, ROLE_DEFS } from "../src/server/rbac";
|
||||
|
||||
const prisma = new PrismaClient({ adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL }) });
|
||||
|
||||
async function main() {
|
||||
// 1. Globalen Rechtekatalog sicherstellen.
|
||||
for (const key of PERMISSIONS) {
|
||||
await prisma.permission.upsert({ where: { key }, update: {}, create: { key } });
|
||||
}
|
||||
const permByKey = new Map((await prisma.permission.findMany()).map((p) => [p.key, p.id]));
|
||||
|
||||
// 2. Fehlende ROLE_DEFS-Rollen je Mandant anlegen (z. B. neue Rolle „pm").
|
||||
const tenants = await prisma.tenant.findMany({ select: { id: true } });
|
||||
let createdRoles = 0;
|
||||
for (const tenant of tenants) {
|
||||
for (const [key, def] of Object.entries(ROLE_DEFS)) {
|
||||
const existing = await prisma.role.findUnique({ where: { tenantId_key: { tenantId: tenant.id, key } } });
|
||||
if (!existing) {
|
||||
await prisma.role.create({ data: { tenantId: tenant.id, key, name: def.name } });
|
||||
createdRoles++;
|
||||
console.log(` ${tenant.id}: Rolle „${key}" angelegt`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Alle Rollen (mandantenübergreifend) gegen ROLE_DEFS abgleichen (Rechte + Name).
|
||||
const roles = await prisma.role.findMany({ include: { rolePermissions: true } });
|
||||
let addedTotal = 0;
|
||||
let touchedRoles = 0;
|
||||
|
||||
for (const role of roles) {
|
||||
const def = ROLE_DEFS[role.key as keyof typeof ROLE_DEFS];
|
||||
if (!def) continue; // unbekannte/manuelle Rolle unangetastet lassen
|
||||
const have = new Set(role.rolePermissions.map((rp) => rp.permissionId));
|
||||
const missing = def.permissions.filter((k) => {
|
||||
const id = permByKey.get(k);
|
||||
return id && !have.has(id);
|
||||
});
|
||||
if (missing.length === 0) continue;
|
||||
|
||||
for (const key of missing) {
|
||||
const permissionId = permByKey.get(key)!;
|
||||
await prisma.rolePermission.upsert({
|
||||
where: { roleId_permissionId: { roleId: role.id, permissionId } },
|
||||
update: {},
|
||||
create: { roleId: role.id, permissionId },
|
||||
});
|
||||
}
|
||||
// Rollenname ebenfalls aktualisieren (falls in ROLE_DEFS geändert).
|
||||
if (role.name !== def.name) await prisma.role.update({ where: { id: role.id }, data: { name: def.name } });
|
||||
|
||||
addedTotal += missing.length;
|
||||
touchedRoles++;
|
||||
console.log(` ${role.tenantId}/${role.key}: +${missing.length} Recht(e) [${missing.join(", ")}]`);
|
||||
}
|
||||
|
||||
console.log(`\nFertig: ${createdRoles} Rolle(n) neu angelegt, ${addedTotal} Zuordnung(en) über ${touchedRoles} Rolle(n) ergänzt. Betroffene Nutzer bitte neu einloggen.`);
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error("Sync fehlgeschlagen:", e.message);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(() => prisma.$disconnect());
|
||||
Reference in New Issue
Block a user