Files
LNpaywall/backend/prisma/schema.prisma
2025-12-14 23:08:45 -03:00

198 lines
5.9 KiB
Plaintext

// Prisma schema for LNPaywall
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model User {
id String @id @default(uuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
status String @default("ACTIVE") // ACTIVE, DISABLED
role String @default("CREATOR") // CREATOR, ADMIN
displayName String
email String? @unique
emailVerified Boolean @default(false)
passwordHash String?
nostrPubkey String? @unique
avatarUrl String?
defaultCurrency String @default("sats")
// OAuth providers
googleId String? @unique
githubId String? @unique
// Payout configuration
lightningAddress String?
lnurlp String?
// Subscription
subscriptionTier String @default("FREE") // FREE, PRO
subscriptionExpiry DateTime?
// Relations
paywalls Paywall[]
sales Sale[]
sessions Session[]
auditLogs AuditLog[]
}
model Session {
id String @id @default(uuid())
userId String
refreshToken String @unique
userAgent String?
ipAddress String?
createdAt DateTime @default(now())
expiresAt DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model Paywall {
id String @id @default(uuid())
creatorId String
status String @default("ACTIVE") // ACTIVE, ARCHIVED, DISABLED
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Content
title String
description String?
coverImageUrl String?
originalUrl String
originalUrlType String @default("URL") // URL, YOUTUBE, NOTION, PDF, LOOM, GDOCS, GITHUB, OTHER
// Preview
previewMode String @default("NONE") // NONE, TEXT_PREVIEW, IMAGE_PREVIEW
previewContent String?
// Pricing
priceSats Int
// Access rules
accessExpirySeconds Int?
maxDevices Int @default(3)
maxSessions Int @default(5)
// Embed settings
allowEmbed Boolean @default(true)
allowedEmbedOrigins String @default("[]") // JSON array as string for SQLite
// Customization
requireEmailReceipt Boolean @default(false)
customSuccessMessage String?
customBranding String? // JSON as string
// URL
slug String? @unique
// Relations
creator User @relation(fields: [creatorId], references: [id], onDelete: Cascade)
checkoutSessions CheckoutSession[]
accessGrants AccessGrant[]
sales Sale[]
}
model CheckoutSession {
id String @id @default(uuid())
paywallId String
createdAt DateTime @default(now())
status String @default("PENDING") // PENDING, PAID, EXPIRED, CANCELED
amountSats Int
paymentProvider String @default("lnbits")
paymentRequest String? // Lightning invoice
paymentHash String? @unique
expiresAt DateTime
buyerHint String? // IP hash + user agent hash
buyerEmail String?
// Relations
paywall Paywall @relation(fields: [paywallId], references: [id], onDelete: Cascade)
accessGrant AccessGrant?
sale Sale?
}
model Buyer {
id String @id @default(uuid())
createdAt DateTime @default(now())
email String?
emailVerified Boolean @default(false)
nostrPubkey String?
notes String?
// Relations
accessGrants AccessGrant[]
sales Sale[]
}
model AccessGrant {
id String @id @default(uuid())
paywallId String
checkoutSessionId String? @unique
buyerId String?
createdAt DateTime @default(now())
expiresAt DateTime?
status String @default("ACTIVE") // ACTIVE, REVOKED
tokenId String @unique @default(uuid())
lastUsedAt DateTime?
usageCount Int @default(0)
deviceFingerprints String @default("[]") // JSON array as string
// Relations
paywall Paywall @relation(fields: [paywallId], references: [id], onDelete: Cascade)
checkoutSession CheckoutSession? @relation(fields: [checkoutSessionId], references: [id])
buyer Buyer? @relation(fields: [buyerId], references: [id])
}
model Sale {
id String @id @default(uuid())
paywallId String
creatorId String
checkoutSessionId String? @unique
buyerId String?
createdAt DateTime @default(now())
amountSats Int
platformFeeSats Int
netSats Int
paymentProvider String
providerReference String?
status String @default("CONFIRMED") // CONFIRMED, REFUNDED, CHARGEBACK, DISPUTED
// Relations
paywall Paywall @relation(fields: [paywallId], references: [id])
creator User @relation(fields: [creatorId], references: [id])
checkoutSession CheckoutSession? @relation(fields: [checkoutSessionId], references: [id])
buyer Buyer? @relation(fields: [buyerId], references: [id])
}
model WebhookEvent {
id String @id @default(uuid())
createdAt DateTime @default(now())
provider String
eventType String
rawPayload String // JSON as string
processedAt DateTime?
status String @default("pending")
error String?
}
model AuditLog {
id String @id @default(uuid())
createdAt DateTime @default(now())
actorId String?
actorType String // creator, admin, system
action String
resourceType String
resourceId String?
ipAddress String?
metadata String? // JSON as string
actor User? @relation(fields: [actorId], references: [id])
}