datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } // ========================================== // ENUMS // ========================================== enum Status { healthy warning critical maintenance disabled } enum Runtime { Static PHP Node_js @map("Node.js") Python Ruby Docker Reverse_proxy @map("Reverse proxy") Custom_service @map("Custom service") } enum Environment { production staging } enum DomainType { primary addon alias subdomain parked } enum DnsRecordType { A AAAA CNAME MX TXT SRV CAA NS PTR } enum DatabaseEngine { MySQL MariaDB PostgreSQL } enum BackupScope { full website database email configuration snapshot } enum SecuritySeverity { critical high medium low } enum SecurityStatus { open acknowledged resolved } enum NotificationCategory { security backup resource ssl deployment system } enum Permission { dashboard_read @map("dashboard:read") tools_read @map("tools:read") websites_manage @map("websites:manage") domains_manage @map("domains:manage") files_manage @map("files:manage") databases_manage @map("databases:manage") email_manage @map("email:manage") metrics_read @map("metrics:read") security_manage @map("security:manage") software_manage @map("software:manage") advanced_manage @map("advanced:manage") servers_manage @map("servers:manage") users_manage @map("users:manage") resellers_manage @map("resellers:manage") backups_manage @map("backups:manage") automation_manage @map("automation:manage") notifications_read @map("notifications:read") audit_read @map("audit:read") support_manage @map("support:manage") settings_manage @map("settings:manage") } // ========================================== // MODELS // ========================================== model User { id String @id @default(cuid()) name String email String @unique passwordHash String? role String // String allows custom roles (e.g. "Super administrator") avatarInitials String twoFactorEnabled Boolean @default(false) lastLogin DateTime @default(now()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations sessions Session[] permissions UserPermission[] accounts AccountUser[] } model Session { id String @id @default(uuid()) userId String user User @relation(fields: [userId], references: [id], onDelete: Cascade) expiresAt DateTime createdAt DateTime @default(now()) userAgent String? ipAddress String? challenge String? // Stores authentication flow state, e.g. "totp" or null } model UserPermission { id String @id @default(cuid()) userId String user User @relation(fields: [userId], references: [id], onDelete: Cascade) permission Permission @@unique([userId, permission]) } model HostingAccount { id String @id @default(cuid()) username String @unique primaryDomain String homeDirectory String sharedIp String dedicatedIp String? theme String @default("system") // "system" | "light" | "dark" createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations users AccountUser[] websites Website[] domains Domain[] databases Database[] mailboxes Mailbox[] backups Backup[] automations Automation[] notifications Notification[] auditEntries AuditEntry[] resourceUsage ResourceUsage[] metricPoints MetricPoint[] findings SecurityFinding[] } model AccountUser { userId String user User @relation(fields: [userId], references: [id], onDelete: Cascade) accountId String account HostingAccount @relation(fields: [accountId], references: [id], onDelete: Cascade) @@id([userId, accountId]) } model Website { id String @id @default(cuid()) name String domain String // Primary domain name for the website runtime Runtime status Status @default(healthy) ssl Status @default(healthy) repository String? environment Environment @default(production) cpuLimit String // e.g. "2 vCPU" memoryLimit String // e.g. "2 GB" lastDeployment DateTime? // Relations accountId String account HostingAccount @relation(fields: [accountId], references: [id], onDelete: Cascade) domains Domain[] // Domains mapped to this website } model Domain { id String @id @default(cuid()) name String @unique // Domain name (e.g. "example.com") type DomainType documentRoot String sslStatus Status @default(healthy) dnssec Boolean @default(false) propagation Int @default(100) // Percentage (0-100) // Relations accountId String account HostingAccount @relation(fields: [accountId], references: [id], onDelete: Cascade) websiteId String? website Website? @relation(fields: [websiteId], references: [id], onDelete: SetNull) dnsRecords DnsRecord[] mailboxes Mailbox[] } model DnsRecord { id String @id @default(cuid()) name String // e.g. "www.example.com." ttl Int @default(14400) class String @default("IN") type DnsRecordType record String // Record value (e.g. IP address, text string, target) priority Int? // Optional priority for MX/SRV records warning String? // Optional validation warnings // Relations domainId String domain Domain @relation(fields: [domainId], references: [id], onDelete: Cascade) } model Server { id String @id @default(cuid()) name String hostname String os String panelVersion String load1 Float // 1-min load average load5 Float // 5-min load average load15 Float // 15-min load average ipAddress String status Status @default(healthy) location String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model Database { id String @id @default(cuid()) name String @unique engine DatabaseEngine size BigInt // Storage size in bytes tables Int @default(0) connections Int @default(0) lastBackup DateTime? // Relations accountId String account HostingAccount @relation(fields: [accountId], references: [id], onDelete: Cascade) users DatabaseUserAccess[] } model DatabaseUser { id String @id @default(cuid()) username String @unique databases DatabaseUserAccess[] } model DatabaseUserAccess { databaseId String database Database @relation(fields: [databaseId], references: [id], onDelete: Cascade) username String // Foreign key pointing to DatabaseUser.username user DatabaseUser @relation(fields: [username], references: [username], onDelete: Cascade) @@id([databaseId, username]) } model Mailbox { id String @id @default(cuid()) address String @unique // e.g. "admin@example.com" used BigInt @default(0) // Storage used in bytes quota BigInt // Storage quota in bytes lastLogin DateTime? forwarding Boolean @default(false) spamScore Float @default(0.0) authStatus Status @default(healthy) // Relations domainId String domain Domain @relation(fields: [domainId], references: [id], onDelete: Cascade) accountId String account HostingAccount @relation(fields: [accountId], references: [id], onDelete: Cascade) } model ResourceUsage { id String @id @default(cuid()) key String // e.g. "disk", "bandwidth", "cpu", "memory" label String used Float limit Float unit String status Status // Relations accountId String account HostingAccount @relation(fields: [accountId], references: [id], onDelete: Cascade) @@unique([accountId, key]) } model MetricPoint { id String @id @default(cuid()) timestamp DateTime @default(now()) cpu Float memory Float disk Float bandwidth Float requests Int // Relations accountId String account HostingAccount @relation(fields: [accountId], references: [id], onDelete: Cascade) } model SecurityFinding { id String @id @default(cuid()) severity SecuritySeverity title String target String status SecurityStatus @default(open) recommendation String // Relations accountId String account HostingAccount @relation(fields: [accountId], references: [id], onDelete: Cascade) } model Backup { id String @id @default(cuid()) name String scope BackupScope destination String size BigInt status Status encrypted Boolean @default(true) createdAt DateTime @default(now()) // Relations accountId String account HostingAccount @relation(fields: [accountId], references: [id], onDelete: Cascade) } model Automation { id String @id @default(cuid()) name String trigger String status Status lastRun DateTime? successRate Int @default(100) // Relations accountId String account HostingAccount @relation(fields: [accountId], references: [id], onDelete: Cascade) } model Notification { id String @id @default(cuid()) title String category NotificationCategory read Boolean @default(false) createdAt DateTime @default(now()) body String // Relations accountId String account HostingAccount @relation(fields: [accountId], references: [id], onDelete: Cascade) } model AuditEntry { id String @id @default(cuid()) actor String action String target String ipAddress String createdAt DateTime @default(now()) requestId String // Relations accountId String account HostingAccount @relation(fields: [accountId], references: [id], onDelete: Cascade) }