Files
Nele-Till-Hochzeit/prisma/schema.prisma
T

120 lines
3.4 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
enum MediaType {
IMAGE
VIDEO
AUDIO
OTHER
}
enum PlacementMode {
RANKING // Position determined by likes ranking
FIXED_POSITION // Position manually set by admin
FIXED_SIZE_RANKING // Position from ranking, but size is fixed
FIXED_POSITION_ADJUSTABLE // Position and size set by admin
}
model MediaItem {
id Int @id @default(autoincrement())
relativePath String @unique // Path relative to MEDIA_ROOT, e.g. "Fotobox/001.jpg"
filename String // Just the filename, e.g. "001.jpg"
directory String // Parent directory, e.g. "Fotobox"
mediaType MediaType @default(IMAGE)
mimeType String @default("application/octet-stream")
fileSize BigInt @default(0)
width Int? // Pixels, for images and videos
height Int? // Pixels, for images and videos
duration Float? // Seconds, for video and audio
// Publication
published Boolean @default(false)
wasOncePublished Boolean @default(false)
// Layout / Placement
featured Boolean @default(false) // Prominent/title image
placementMode PlacementMode @default(RANKING)
gridColumn Int? // For fixed position (grid column start)
gridRow Int? // For fixed position (grid row start)
gridWidth Int @default(1) // Width in grid units
gridHeight Int @default(1) // Height in grid units
sortOrder Int @default(0) // Manual sort order / ranking tiebreak
// Processing status
thumbnailReady Boolean @default(false)
previewReady Boolean @default(false)
// File tracking
fileHash String? // For detecting file changes
lastModified DateTime? // File's mtime from filesystem
lastScanned DateTime @default(now())
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
likes Like[]
@@index([published])
@@index([directory])
@@index([mediaType])
@@index([published, sortOrder])
@@index([published, placementMode])
}
model Like {
id Int @id @default(autoincrement())
mediaItemId Int
ipHash String // SHA-256 hash of IP address
fingerprint String? // Optional browser fingerprint hash
createdAt DateTime @default(now())
mediaItem MediaItem @relation(fields: [mediaItemId], references: [id], onDelete: Cascade)
@@unique([mediaItemId, ipHash]) // One like per IP per media item
@@index([ipHash])
@@index([mediaItemId])
@@index([createdAt])
}
model AppSettings {
id Int @id @default(1)
votingOpen Boolean @default(false)
zipVersion Int @default(0)
zipReady Boolean @default(false)
zipBuildAt DateTime?
zipFilePath String? // Path to current valid ZIP
lastScanAt DateTime?
directoryOrder String[] @default([])
updatedAt DateTime @updatedAt
}
model AdminSession {
id String @id @default(uuid())
ipAddress String
userAgent String @default("")
createdAt DateTime @default(now())
expiresAt DateTime
@@index([expiresAt])
}
model RateLimitEntry {
id Int @id @default(autoincrement())
ipHash String
action String // e.g. "login", "like"
windowStart DateTime
count Int @default(1)
@@unique([ipHash, action, windowStart])
@@index([ipHash, action, windowStart])
@@index([windowStart]) // For cleanup of old entries
}