198 lines
5.9 KiB
Plaintext
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])
|
|
}
|