Files
home/Projects/kompose/news/apps/backend/prisma/schema.prisma
2025-10-08 10:35:48 +02:00

329 lines
7.5 KiB
Plaintext

generator client {
provider = "prisma-client-js"
previewFeatures = ["typedSql"]
output = "./client"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Organization {
id String @id @default(uuid())
name String
description String?
UserOrganizations UserOrganization[]
Lists List[]
Subscribers Subscriber[]
Templates Template[]
Campaigns Campaign[]
SmtpSettings SmtpSettings[]
ApiKeys ApiKey[]
GeneralSettings GeneralSettings?
EmailDeliverySettings EmailDeliverySettings?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model User {
id String @id @default(uuid())
name String
email String @unique
password String
pwdVersion Int @default(1)
UserOrganizations UserOrganization[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model UserOrganization {
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
organizationId String
Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
@@id([userId, organizationId])
}
model Subscriber {
id String @id @default(uuid())
name String?
email String
organizationId String
Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
ListSubscribers ListSubscriber[]
Messages Message[]
Clicks Click[]
Metadata SubscriberMetadata[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
emailVerified Boolean @default(false)
emailVerificationToken String? @unique
emailVerificationTokenExpiresAt DateTime?
@@unique([organizationId, email])
@@index([createdAt, id])
}
model SubscriberMetadata {
id String @id @default(uuid())
key String
value String
subscriberId String
Subscriber Subscriber @relation(fields: [subscriberId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([subscriberId, key])
}
enum CampaignStatus {
DRAFT
SCHEDULED
CREATING
SENDING
COMPLETED
CANCELLED
}
model Campaign {
id String @id @default(uuid())
title String
description String?
subject String?
content String?
completedAt DateTime?
status CampaignStatus @default(DRAFT)
scheduledAt DateTime?
htmlOnly Boolean @default(false)
openTracking Boolean @default(true)
unsubscribedCount Int @default(0)
organizationId String
Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
templateId String?
Template Template? @relation(fields: [templateId], references: [id], onDelete: SetNull)
Messages Message[]
CampaignLists CampaignList[]
TrackedLinks TrackedLink[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model List {
id String @id @default(uuid())
name String
description String?
organizationId String
Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
ListSubscribers ListSubscriber[]
CampaignLists CampaignList[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model CampaignList {
campaignId String
listId String
Campaign Campaign @relation(fields: [campaignId], references: [id], onDelete: Cascade)
List List @relation(fields: [listId], references: [id], onDelete: Cascade)
@@id([campaignId, listId])
}
model ListSubscriber {
id String @id @default(uuid())
unsubscribedAt DateTime?
listId String
subscriberId String
List List @relation(fields: [listId], references: [id], onDelete: Cascade)
Subscriber Subscriber @relation(fields: [subscriberId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([listId, subscriberId])
}
model Template {
id String @id @default(uuid())
name String
description String?
content String
organizationId String
Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
Campaigns Campaign[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum MessageStatus {
QUEUED
PENDING
SENT
OPENED
CLICKED
FAILED
RETRYING
CANCELLED
}
model Message {
id String @id @default(uuid())
content String?
status MessageStatus @default(QUEUED)
sentAt DateTime?
tries Int @default(0)
lastTriedAt DateTime?
/// Returned from SMTP response
messageId String?
subscriberId String
Subscriber Subscriber @relation(fields: [subscriberId], references: [id], onDelete: Cascade)
campaignId String
Campaign Campaign @relation(fields: [campaignId], references: [id], onDelete: Cascade)
error String? @db.Text
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([updatedAt, id])
}
model TrackedLink {
id String @id @default(uuid())
url String
campaignId String?
Campaign Campaign? @relation(fields: [campaignId], references: [id], onDelete: SetNull)
Clicks Click[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([url, campaignId])
}
model Click {
id String @id @default(uuid())
trackedLinkId String?
TrackedLink TrackedLink? @relation(fields: [trackedLinkId], references: [id], onDelete: Cascade)
subscriberId String?
Subscriber Subscriber? @relation(fields: [subscriberId], references: [id], onDelete: SetNull)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum SmtpEncryption {
STARTTLS
SSL_TLS
NONE
}
model ApiKey {
id String @id @default(uuid())
name String
key String @unique
lastUsed DateTime?
expiresAt DateTime?
organizationId String
Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model SmtpSettings {
id String @id @default(uuid())
host String
port Int
username String
password String
fromEmail String?
fromName String?
secure Boolean @default(true)
encryption SmtpEncryption @default(STARTTLS)
timeout Int @default(30000)
organizationId String
Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model GeneralSettings {
id String @id @default(uuid())
defaultFromEmail String?
defaultFromName String?
baseURL String?
cleanupInterval Int @default(90)
organizationId String @unique
Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model EmailDeliverySettings {
id String @id @default(uuid())
rateLimit Int @default(100)
rateWindow Int @default(3600)
maxRetries Int @default(3)
retryDelay Int @default(300)
concurrency Int @default(5)
connectionTimeout Int @default(30000)
organizationId String @unique
Organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}