439 lines
16 KiB
Plaintext
439 lines
16 KiB
Plaintext
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "mysql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
// ─── Admin / WHM Users ───────────────────────────────────────────────────────
|
|
|
|
model AdminUser {
|
|
id Int @id @default(autoincrement())
|
|
username String @unique @db.VarChar(64)
|
|
passwordHash String @db.VarChar(255)
|
|
email String @unique @db.VarChar(255)
|
|
twoFactorSecret String? @db.VarChar(64)
|
|
twoFactorEnabled Boolean @default(false)
|
|
lastLogin DateTime?
|
|
lastLoginIp String? @db.VarChar(45)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
refreshTokens RefreshToken[]
|
|
auditLogs AuditLog[]
|
|
|
|
@@map("admin_users")
|
|
}
|
|
|
|
// ─── Resellers ───────────────────────────────────────────────────────────────
|
|
|
|
model Reseller {
|
|
id Int @id @default(autoincrement())
|
|
username String @unique @db.VarChar(64)
|
|
passwordHash String @db.VarChar(255)
|
|
email String @unique @db.VarChar(255)
|
|
contactName String? @db.VarChar(255)
|
|
company String? @db.VarChar(255)
|
|
maxAccounts Int @default(0)
|
|
diskLimitMb BigInt @default(0)
|
|
bandwidthLimitMb BigInt @default(0)
|
|
diskUsedMb BigInt @default(0)
|
|
bandwidthUsedMb BigInt @default(0)
|
|
status String @default("active") @db.VarChar(20)
|
|
brandName String? @db.VarChar(255)
|
|
brandLogo String? @db.VarChar(500)
|
|
notes String? @db.Text
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
accounts Account[]
|
|
refreshTokens RefreshToken[]
|
|
|
|
@@map("resellers")
|
|
}
|
|
|
|
// ─── Hosting Packages ────────────────────────────────────────────────────────
|
|
|
|
model Package {
|
|
id Int @id @default(autoincrement())
|
|
name String @unique @db.VarChar(100)
|
|
diskMb BigInt @default(1024)
|
|
bandwidthMb BigInt @default(10240)
|
|
maxDatabases Int @default(5)
|
|
maxEmailAccounts Int @default(10)
|
|
maxSubdomains Int @default(10)
|
|
maxAddonDomains Int @default(5)
|
|
maxParkedDomains Int @default(5)
|
|
maxFtpAccounts Int @default(3)
|
|
maxCronJobs Int @default(5)
|
|
phpVersion String @default("8.3") @db.VarChar(10)
|
|
sslEnabled Boolean @default(true)
|
|
backupEnabled Boolean @default(true)
|
|
dedicatedIp Boolean @default(false)
|
|
notes String? @db.Text
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
accounts Account[]
|
|
|
|
@@map("packages")
|
|
}
|
|
|
|
// ─── Hosting Accounts (cPanel users) ─────────────────────────────────────────
|
|
|
|
model Account {
|
|
id Int @id @default(autoincrement())
|
|
username String @unique @db.VarChar(64)
|
|
passwordHash String @db.VarChar(255)
|
|
email String @db.VarChar(255)
|
|
domain String @unique @db.VarChar(255)
|
|
homedir String @db.VarChar(500)
|
|
shell String @default("/bin/false") @db.VarChar(100)
|
|
status String @default("active") @db.VarChar(20)
|
|
diskUsedMb BigInt @default(0)
|
|
bandwidthUsedMb BigInt @default(0)
|
|
ipAddress String? @db.VarChar(45)
|
|
nameservers String? @db.VarChar(500)
|
|
notes String? @db.Text
|
|
suspendedAt DateTime?
|
|
suspendReason String? @db.VarChar(500)
|
|
terminatedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
resellerId Int?
|
|
reseller Reseller? @relation(fields: [resellerId], references: [id])
|
|
packageId Int?
|
|
package Package? @relation(fields: [packageId], references: [id])
|
|
ipId Int?
|
|
ip IpAddress? @relation(fields: [ipId], references: [id])
|
|
|
|
dnsZones DnsZone[]
|
|
emailAccounts EmailAccount[]
|
|
emailForwarders EmailForwarder[]
|
|
ftpAccounts FtpAccount[]
|
|
databases Database[]
|
|
subdomains Subdomain[]
|
|
addonDomains AddonDomain[]
|
|
parkedDomains ParkedDomain[]
|
|
sslCertificates SslCertificate[]
|
|
cronJobs CronJob[]
|
|
refreshTokens RefreshToken[]
|
|
|
|
@@map("accounts")
|
|
}
|
|
|
|
// ─── IP Addresses ─────────────────────────────────────────────────────────────
|
|
|
|
model IpAddress {
|
|
id Int @id @default(autoincrement())
|
|
address String @unique @db.VarChar(45)
|
|
netmask String? @db.VarChar(45)
|
|
gateway String? @db.VarChar(45)
|
|
type String @default("shared") @db.VarChar(20)
|
|
status String @default("available") @db.VarChar(20)
|
|
notes String? @db.Text
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
accounts Account[]
|
|
|
|
@@map("ip_addresses")
|
|
}
|
|
|
|
// ─── DNS ──────────────────────────────────────────────────────────────────────
|
|
|
|
model DnsZone {
|
|
id Int @id @default(autoincrement())
|
|
domain String @unique @db.VarChar(255)
|
|
zoneFile String? @db.VarChar(500)
|
|
serial BigInt @default(1)
|
|
status String @default("active") @db.VarChar(20)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
accountId Int
|
|
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
|
|
|
records DnsRecord[]
|
|
|
|
@@map("dns_zones")
|
|
}
|
|
|
|
model DnsRecord {
|
|
id Int @id @default(autoincrement())
|
|
type String @db.VarChar(10)
|
|
name String @db.VarChar(255)
|
|
value String @db.VarChar(500)
|
|
ttl Int @default(3600)
|
|
priority Int?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
zoneId Int
|
|
zone DnsZone @relation(fields: [zoneId], references: [id], onDelete: Cascade)
|
|
|
|
@@map("dns_records")
|
|
}
|
|
|
|
// ─── Email ────────────────────────────────────────────────────────────────────
|
|
|
|
model EmailAccount {
|
|
id Int @id @default(autoincrement())
|
|
username String @db.VarChar(64)
|
|
domain String @db.VarChar(255)
|
|
address String @unique @db.VarChar(320)
|
|
passwordHash String @db.VarChar(255)
|
|
quotaMb Int @default(500)
|
|
usedMb Int @default(0)
|
|
status String @default("active") @db.VarChar(20)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
accountId Int
|
|
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
|
|
|
@@map("email_accounts")
|
|
}
|
|
|
|
model EmailForwarder {
|
|
id Int @id @default(autoincrement())
|
|
source String @db.VarChar(320)
|
|
destination String @db.VarChar(320)
|
|
createdAt DateTime @default(now())
|
|
|
|
accountId Int
|
|
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
|
|
|
@@map("email_forwarders")
|
|
}
|
|
|
|
// ─── FTP ──────────────────────────────────────────────────────────────────────
|
|
|
|
model FtpAccount {
|
|
id Int @id @default(autoincrement())
|
|
username String @db.VarChar(64)
|
|
passwordHash String @db.VarChar(255)
|
|
homedir String @db.VarChar(500)
|
|
quotaMb Int @default(0)
|
|
status String @default("active") @db.VarChar(20)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
accountId Int
|
|
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
|
|
|
@@map("ftp_accounts")
|
|
}
|
|
|
|
// ─── Databases ────────────────────────────────────────────────────────────────
|
|
|
|
model Database {
|
|
id Int @id @default(autoincrement())
|
|
name String @unique @db.VarChar(64)
|
|
charset String @default("utf8mb4") @db.VarChar(32)
|
|
collation String @default("utf8mb4_unicode_ci") @db.VarChar(64)
|
|
sizeMb Float @default(0)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
accountId Int
|
|
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
|
|
|
dbUsers DatabaseUser[]
|
|
|
|
@@map("databases")
|
|
}
|
|
|
|
model DatabaseUser {
|
|
id Int @id @default(autoincrement())
|
|
username String @db.VarChar(64)
|
|
passwordHash String @db.VarChar(255)
|
|
host String @default("localhost") @db.VarChar(255)
|
|
privileges String @default("ALL") @db.VarChar(255)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
databaseId Int
|
|
database Database @relation(fields: [databaseId], references: [id], onDelete: Cascade)
|
|
|
|
@@map("database_users")
|
|
}
|
|
|
|
// ─── Subdomains / Addon / Parked Domains ─────────────────────────────────────
|
|
|
|
model Subdomain {
|
|
id Int @id @default(autoincrement())
|
|
subdomain String @db.VarChar(255)
|
|
domain String @db.VarChar(255)
|
|
fqdn String @unique @db.VarChar(510)
|
|
documentRoot String @db.VarChar(500)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
accountId Int
|
|
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
|
|
|
@@map("subdomains")
|
|
}
|
|
|
|
model AddonDomain {
|
|
id Int @id @default(autoincrement())
|
|
domain String @unique @db.VarChar(255)
|
|
subdomain String @db.VarChar(255)
|
|
documentRoot String @db.VarChar(500)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
accountId Int
|
|
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
|
|
|
@@map("addon_domains")
|
|
}
|
|
|
|
model ParkedDomain {
|
|
id Int @id @default(autoincrement())
|
|
domain String @unique @db.VarChar(255)
|
|
createdAt DateTime @default(now())
|
|
|
|
accountId Int
|
|
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
|
|
|
@@map("parked_domains")
|
|
}
|
|
|
|
// ─── SSL ──────────────────────────────────────────────────────────────────────
|
|
|
|
model SslCertificate {
|
|
id Int @id @default(autoincrement())
|
|
domain String @db.VarChar(255)
|
|
type String @default("letsencrypt") @db.VarChar(30)
|
|
certPath String? @db.VarChar(500)
|
|
keyPath String? @db.VarChar(500)
|
|
chainPath String? @db.VarChar(500)
|
|
issuedAt DateTime?
|
|
expiresAt DateTime?
|
|
autoRenew Boolean @default(true)
|
|
status String @default("pending") @db.VarChar(20)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
accountId Int
|
|
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
|
|
|
@@map("ssl_certificates")
|
|
}
|
|
|
|
// ─── Cron Jobs ────────────────────────────────────────────────────────────────
|
|
|
|
model CronJob {
|
|
id Int @id @default(autoincrement())
|
|
schedule String @db.VarChar(100)
|
|
command String @db.VarChar(1000)
|
|
comment String? @db.VarChar(255)
|
|
enabled Boolean @default(true)
|
|
lastRun DateTime?
|
|
nextRun DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
accountId Int
|
|
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
|
|
|
@@map("cron_jobs")
|
|
}
|
|
|
|
// ─── Security ─────────────────────────────────────────────────────────────────
|
|
|
|
model SecurityEvent {
|
|
id Int @id @default(autoincrement())
|
|
type String @db.VarChar(50)
|
|
severity String @default("info") @db.VarChar(20)
|
|
message String @db.Text
|
|
sourceIp String? @db.VarChar(45)
|
|
resolved Boolean @default(false)
|
|
resolvedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
|
|
@@map("security_events")
|
|
}
|
|
|
|
model BlockedIp {
|
|
id Int @id @default(autoincrement())
|
|
ip String @unique @db.VarChar(45)
|
|
reason String? @db.VarChar(500)
|
|
expiresAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
|
|
@@map("blocked_ips")
|
|
}
|
|
|
|
model WhitelistedIp {
|
|
id Int @id @default(autoincrement())
|
|
ip String @unique @db.VarChar(45)
|
|
note String? @db.VarChar(255)
|
|
createdAt DateTime @default(now())
|
|
|
|
@@map("whitelisted_ips")
|
|
}
|
|
|
|
// ─── Audit Log ────────────────────────────────────────────────────────────────
|
|
|
|
model AuditLog {
|
|
id Int @id @default(autoincrement())
|
|
action String @db.VarChar(100)
|
|
target String? @db.VarChar(255)
|
|
details String? @db.Text
|
|
sourceIp String? @db.VarChar(45)
|
|
createdAt DateTime @default(now())
|
|
|
|
adminId Int?
|
|
admin AdminUser? @relation(fields: [adminId], references: [id])
|
|
|
|
@@map("audit_log")
|
|
}
|
|
|
|
// ─── Auth ─────────────────────────────────────────────────────────────────────
|
|
|
|
model RefreshToken {
|
|
id Int @id @default(autoincrement())
|
|
token String @unique @db.VarChar(500)
|
|
role String @db.VarChar(20)
|
|
expiresAt DateTime
|
|
revokedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
|
|
adminId Int?
|
|
admin AdminUser? @relation(fields: [adminId], references: [id])
|
|
resellerId Int?
|
|
reseller Reseller? @relation(fields: [resellerId], references: [id])
|
|
accountId Int?
|
|
account Account? @relation(fields: [accountId], references: [id])
|
|
|
|
@@map("refresh_tokens")
|
|
}
|
|
|
|
// ─── Settings ─────────────────────────────────────────────────────────────────
|
|
|
|
model Setting {
|
|
key String @id @db.VarChar(100)
|
|
value String @db.Text
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@map("settings")
|
|
}
|
|
|
|
// ─── Terminal Sessions ────────────────────────────────────────────────────────
|
|
|
|
model TerminalSession {
|
|
id Int @id @default(autoincrement())
|
|
adminId Int
|
|
sourceIp String? @db.VarChar(45)
|
|
startedAt DateTime @default(now())
|
|
endedAt DateTime?
|
|
|
|
@@map("terminal_sessions")
|
|
}
|