- docs/SPEC.md (v1.2: Assets & BIA als ein Modul, Risiko-Detailansicht mit Maßnahmen/betroffenen Assets, Risiko-Verknüpfungen in allen Detailansichten) + UI-Mockup als Referenz - Docker-Compose: app, worker, postgres (pgvector), redis, minio, mailhog - Prisma 7: Fundament-Schema (Tenant, User, RBAC, AuditLog), prisma.config.ts, pg-Treiberadapter - Tenant-Guard (src/server/db.ts): erzwungene Mandanten-Isolation für alle tenant-gebundenen Modelle - AGENTS.md/README mit Projektregeln (Isolation, RBAC, Audit-Log, i18n, Lizenz) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
130 lines
3.5 KiB
Plaintext
130 lines
3.5 KiB
Plaintext
// ISMS-Tool — Prisma-Schema
|
|
// Fundament (Iteration 1): Mandanten, Nutzer, RBAC, Audit-Log.
|
|
// Fachliche Entitäten (Assets, BIA, Risiken, …) folgen je Iteration — siehe docs/SPEC.md §5.
|
|
//
|
|
// Multi-Tenant-Regel: Jede fachliche Tabelle trägt tenantId. Zugriff nur über den
|
|
// zentralen Tenant-Guard (src/server/db.ts); zusätzlich Postgres RLS (prisma/rls.sql).
|
|
|
|
generator client {
|
|
provider = "prisma-client-js"
|
|
previewFeatures = ["postgresqlExtensions"]
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
extensions = [pgvector(map: "vector")]
|
|
}
|
|
|
|
enum TenantStatus {
|
|
ACTIVE
|
|
SUSPENDED
|
|
}
|
|
|
|
enum UserStatus {
|
|
ACTIVE
|
|
INVITED
|
|
LOCKED
|
|
DEACTIVATED
|
|
}
|
|
|
|
model Tenant {
|
|
id String @id @default(cuid())
|
|
name String
|
|
slug String @unique
|
|
status TenantStatus @default(ACTIVE)
|
|
config Json @default("{}")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
users User[]
|
|
roles Role[]
|
|
auditLogs AuditLog[]
|
|
|
|
@@map("tenants")
|
|
}
|
|
|
|
model User {
|
|
id String @id @default(cuid())
|
|
tenantId String @map("tenant_id")
|
|
email String
|
|
passwordHash String @map("password_hash")
|
|
name String
|
|
status UserStatus @default(ACTIVE)
|
|
mfaSecret String? @map("mfa_secret")
|
|
// Plattform-Admin ist mandantenübergreifend (Betreiberrolle)
|
|
isPlatformAdmin Boolean @default(false) @map("is_platform_admin")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
tenant Tenant @relation(fields: [tenantId], references: [id])
|
|
userRoles UserRole[]
|
|
|
|
@@unique([tenantId, email])
|
|
@@index([tenantId])
|
|
@@map("users")
|
|
}
|
|
|
|
model Role {
|
|
id String @id @default(cuid())
|
|
tenantId String @map("tenant_id")
|
|
key String // z. B. tenant-admin, isb, auditor, owner, user
|
|
name String
|
|
|
|
tenant Tenant @relation(fields: [tenantId], references: [id])
|
|
userRoles UserRole[]
|
|
rolePermissions RolePermission[]
|
|
|
|
@@unique([tenantId, key])
|
|
@@index([tenantId])
|
|
@@map("roles")
|
|
}
|
|
|
|
model Permission {
|
|
id String @id @default(cuid())
|
|
key String @unique // z. B. asset:read, risk:write, incident:manage
|
|
|
|
rolePermissions RolePermission[]
|
|
|
|
@@map("permissions")
|
|
}
|
|
|
|
model UserRole {
|
|
userId String @map("user_id")
|
|
roleId String @map("role_id")
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
|
|
|
@@id([userId, roleId])
|
|
@@map("user_roles")
|
|
}
|
|
|
|
model RolePermission {
|
|
roleId String @map("role_id")
|
|
permissionId String @map("permission_id")
|
|
|
|
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
|
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
|
|
|
|
@@id([roleId, permissionId])
|
|
@@map("role_permissions")
|
|
}
|
|
|
|
model AuditLog {
|
|
id String @id @default(cuid())
|
|
tenantId String @map("tenant_id")
|
|
actorId String? @map("actor_id")
|
|
action String // create | update | delete | login | export | …
|
|
entity String // z. B. asset, risk, user
|
|
entityId String? @map("entity_id")
|
|
before Json?
|
|
after Json?
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
|
|
tenant Tenant @relation(fields: [tenantId], references: [id])
|
|
|
|
@@index([tenantId, entity, entityId])
|
|
@@index([tenantId, createdAt])
|
|
@@map("audit_logs")
|
|
}
|