Files

167 lines
5.5 KiB
Plaintext

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
output = "../src/generated/client"
binaryTargets = ["native", "linux-musl-arm64-openssl-3.0.x", "linux-musl-openssl-3.0.x"]
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model User {
id String @id @default(uuid())
username String? @unique
email String @unique
passwordHash String
name String
role String @default("USER")
mustResetPassword Boolean @default(false)
isActive Boolean @default(true)
authIdentities AuthIdentity[]
drawings Drawing[]
collections Collection[]
passwordResetTokens PasswordResetToken[]
refreshTokens RefreshToken[]
auditLogs AuditLog[]
drawingShareGrants DrawingShareGrant[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model SystemConfig {
id String @id @default("default")
authEnabled Boolean @default(false)
authOnboardingCompleted Boolean @default(false)
registrationEnabled Boolean @default(false)
authLoginRateLimitEnabled Boolean @default(true)
authLoginRateLimitWindowMs Int @default(900000) // 15 minutes
authLoginRateLimitMax Int @default(20)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Collection {
id String @id @default(uuid())
name String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
drawings Drawing[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([userId, updatedAt])
}
model Drawing {
id String @id @default(uuid())
name String
elements String // Stored as JSON string
appState String // Stored as JSON string
files String @default("{}") // Stored as JSON string
preview String? // SVG string for thumbnail
version Int @default(1)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
collectionId String?
collection Collection? @relation(fields: [collectionId], references: [id])
shareLinks DrawingShareLink[]
shareGrants DrawingShareGrant[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([userId, updatedAt])
@@index([userId, collectionId, updatedAt])
}
model DrawingShareLink {
id String @id @default(uuid())
drawingId String
drawing Drawing @relation(fields: [drawingId], references: [id], onDelete: Cascade)
role String
token String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
grants DrawingShareGrant[]
@@unique([drawingId, role])
@@index([drawingId])
}
model DrawingShareGrant {
id String @id @default(uuid())
drawingId String
drawing Drawing @relation(fields: [drawingId], references: [id], onDelete: Cascade)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
shareLinkId String
shareLink DrawingShareLink @relation(fields: [shareLinkId], references: [id], onDelete: Cascade)
role String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([drawingId, userId, shareLinkId])
@@index([drawingId, userId])
@@index([userId, createdAt])
}
model Library {
id String @id // User-specific library ID (e.g., "user_<userId>")
items String @default("[]") // Stored as JSON string array of library items
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model PasswordResetToken {
id String @id @default(uuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
token String @unique
expiresAt DateTime
used Boolean @default(false)
createdAt DateTime @default(now())
}
model RefreshToken {
id String @id @default(uuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
token String @unique
expiresAt DateTime
revoked Boolean @default(false)
createdAt DateTime @default(now())
}
model AuditLog {
id String @id @default(uuid())
userId String?
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
action String // e.g., "login", "login_failed", "password_reset", "password_changed", "drawing_deleted"
resource String? // e.g., "drawing:123", "collection:456"
ipAddress String?
userAgent String?
details String? // JSON string for additional details
createdAt DateTime @default(now())
}
model AuthIdentity {
id String @id @default(uuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
provider String
issuer String
subject String
emailAtLink String
lastLoginAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([issuer, subject])
@@unique([provider, userId])
@@index([userId])
}