taskmanager/prisma/schema.prisma

309 lines
7.9 KiB
Plaintext

// Prisma Schema für Aufgabenplaner
// Dokumentation: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// Benutzerrollen im System
enum Role {
BEARBEITER
PFLEGER
VORGESETZTER
ADMIN
}
// Aufgaben-Status
enum TaskStatus {
UNERLEDIGT
IN_BEARBEITUNG
ERLEDIGT
}
// Benutzer-Modell
model User {
id String @id @default(cuid())
email String @unique
name String
password String
role Role @default(BEARBEITER)
active Boolean @default(true)
sessionVersion Int @default(1)
mustChangePassword Boolean @default(false)
oidcSubject String? @unique
memberships UserGroup[]
roles UserRole[]
tokens ActionToken[]
notifications Notification[]
filters SavedFilter[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations: Aufgaben die der Benutzer erstellt hat
createdTasks Task[] @relation("TaskCreator")
// Relations: Aufgaben die dem Benutzer zugewiesen sind
assignedTasks Task[] @relation("TaskAssignee")
// Relations: Kommentare des Benutzers
comments Comment[]
}
// Aufgaben-Modell
model Task {
id String @id @default(cuid())
wo String
was String @db.Text
bisWann DateTime
status TaskStatus @default(UNERLEDIGT)
beauftragtAm DateTime?
firmaBeauftragt String?
version Int @default(1)
priority Int @default(2)
tags String[] @default([])
project String @default("")
archivedAt DateTime?
completedAt DateTime?
owningGroupId String @default("legacy")
owningGroup Group @relation(fields: [owningGroupId], references: [id])
parentId String?
parent Task? @relation("Subtasks", fields: [parentId], references: [id], onDelete: SetNull)
children Task[] @relation("Subtasks")
checklist Json @default("[]")
recurrenceDays Int?
recurrenceSourceId String? @unique
dependencies TaskDependency[] @relation("Dependent")
dependents TaskDependency[] @relation("Dependency")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations: Ersteller der Aufgabe
creatorId String
creator User @relation("TaskCreator", fields: [creatorId], references: [id])
// Relations: Zugewiesener Bearbeiter
assigneeId String?
assignee User? @relation("TaskAssignee", fields: [assigneeId], references: [id])
// Relations: Kommentare zur Aufgabe
comments Comment[]
// Relations: Dateien der Aufgabe
files File[]
@@index([status])
@@index([bisWann])
@@index([assigneeId])
@@index([creatorId])
@@index([owningGroupId, archivedAt, bisWann, id])
@@index([assigneeId, archivedAt, bisWann, id])
}
// Kommentar-Modell
model Comment {
id String @id @default(cuid())
content String @db.Text
createdAt DateTime @default(now())
// Relations: Zugehörige Aufgabe
taskId String
task Task @relation(fields: [taskId], references: [id], onDelete: Cascade)
// Relations: Autor des Kommentars
authorId String
author User @relation(fields: [authorId], references: [id])
@@index([taskId])
}
// Datei-Modell
model File {
id String @id @default(cuid())
name String
path String
mimeType String
uploaderId String?
size Int
createdAt DateTime @default(now())
// Relations: Zugehörige Aufgabe
taskId String
task Task @relation(fields: [taskId], references: [id], onDelete: Cascade)
@@index([taskId])
}
enum Scope {
ASSIGNED
GROUP
GLOBAL
}
model Group {
id String @id @default(cuid())
name String @unique
active Boolean @default(true)
members UserGroup[]
roles GroupRole[]
tasks Task[]
}
model UserGroup {
userId String
groupId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
group Group @relation(fields: [groupId], references: [id], onDelete: Cascade)
@@id([userId, groupId])
}
model AccessRole {
id String @id @default(cuid())
name String @unique
protected Boolean @default(false)
permissions RolePermission[]
users UserRole[]
groups GroupRole[]
}
model Permission {
key String @id
roles RolePermission[]
}
model RolePermission {
roleId String
permissionKey String
role AccessRole @relation(fields: [roleId], references: [id], onDelete: Cascade)
permission Permission @relation(fields: [permissionKey], references: [key], onDelete: Cascade)
@@id([roleId, permissionKey])
}
model UserRole {
id String @id @default(cuid())
userId String
roleId String
scope Scope
targetGroupId String @default("")
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
role AccessRole @relation(fields: [roleId], references: [id], onDelete: Cascade)
@@unique([userId, roleId, scope, targetGroupId])
}
model GroupRole {
groupId String
roleId String
scope Scope
group Group @relation(fields: [groupId], references: [id], onDelete: Cascade)
role AccessRole @relation(fields: [roleId], references: [id], onDelete: Cascade)
@@id([groupId, roleId, scope])
}
model AuditEvent {
id String @id @default(cuid())
actorId String
action String
targetId String
taskId String?
data Json @default("{}")
createdAt DateTime @default(now())
@@index([taskId, createdAt])
@@index([createdAt])
}
model ActionToken {
hash String @id
userId String
purpose String
expiresAt DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model RateLimit {
key String @id
count Int
expiresAt DateTime
}
model Notification {
id String @id @default(cuid())
userId String
taskId String
key String @unique
text String
read Boolean @default(false)
emailed Boolean @default(false)
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId, createdAt])
}
model SavedFilter {
id String @id @default(cuid())
userId String
name String
query Json
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model TaskTemplate {
id String @id @default(cuid())
name String
ownerId String
data Json
}
model TaskDependency {
taskId String
dependsOnId String
task Task @relation("Dependent", fields: [taskId], references: [id], onDelete: Cascade)
dependsOn Task @relation("Dependency", fields: [dependsOnId], references: [id], onDelete: Cascade)
@@id([taskId, dependsOnId])
}
model CleanupJob {
id String @id @default(cuid())
storageKey String
attempts Int @default(0)
createdAt DateTime @default(now())
}
model Webhook {
id String @id @default(cuid())
name String
url String
secret String
active Boolean @default(true)
}
model WebhookDelivery {
id String @id @default(cuid())
webhookId String
eventId String
attempts Int @default(0)
deliveredAt DateTime?
nextAttemptAt DateTime @default(now())
@@unique([webhookId, eventId])
}
model ApiToken {
hash String @id
userId String
name String
permissions String[]
expiresAt DateTime
createdAt DateTime @default(now())
}