Files
sign/packages/prisma/schema.prisma
Ephraim Duncan 3d644db286 feat: signing order (#1290)
Adds the ability to specify an optional signing order for documents.
When specified a document will be considered sequential with recipients
only being allowed to sign in the order that they were specified in.
2024-09-16 22:36:45 +10:00

713 lines
19 KiB
Plaintext

generator kysely {
provider = "prisma-kysely"
}
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("NEXT_PRIVATE_DATABASE_URL")
directUrl = env("NEXT_PRIVATE_DIRECT_DATABASE_URL")
}
enum IdentityProvider {
DOCUMENSO
GOOGLE
OIDC
}
enum Role {
ADMIN
USER
}
model User {
id Int @id @default(autoincrement())
name String?
customerId String? @unique
email String @unique
emailVerified DateTime?
password String?
source String?
signature String?
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
lastSignedIn DateTime @default(now())
roles Role[] @default([USER])
identityProvider IdentityProvider @default(DOCUMENSO)
avatarImageId String?
accounts Account[]
sessions Session[]
Document Document[]
Subscription Subscription[]
PasswordResetToken PasswordResetToken[]
ownedTeams Team[]
ownedPendingTeams TeamPending[]
teamMembers TeamMember[]
twoFactorSecret String?
twoFactorEnabled Boolean @default(false)
twoFactorBackupCodes String?
url String? @unique
profile UserProfile?
VerificationToken VerificationToken[]
ApiToken ApiToken[]
Template Template[]
securityAuditLogs UserSecurityAuditLog[]
Webhooks Webhook[]
siteSettings SiteSettings[]
passkeys Passkey[]
avatarImage AvatarImage? @relation(fields: [avatarImageId], references: [id], onDelete: SetNull)
@@index([email])
}
model UserProfile {
id String @id @default(cuid())
enabled Boolean @default(false)
userId Int @unique
bio String?
User User? @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model TeamProfile {
id String @id @default(cuid())
enabled Boolean @default(false)
teamId Int @unique
bio String?
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
}
enum UserSecurityAuditLogType {
ACCOUNT_PROFILE_UPDATE
ACCOUNT_SSO_LINK
AUTH_2FA_DISABLE
AUTH_2FA_ENABLE
PASSKEY_CREATED
PASSKEY_DELETED
PASSKEY_UPDATED
PASSWORD_RESET
PASSWORD_UPDATE
SIGN_OUT
SIGN_IN
SIGN_IN_FAIL
SIGN_IN_2FA_FAIL
SIGN_IN_PASSKEY_FAIL
}
model UserSecurityAuditLog {
id Int @id @default(autoincrement())
userId Int
createdAt DateTime @default(now())
type UserSecurityAuditLogType
userAgent String?
ipAddress String?
User User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model PasswordResetToken {
id Int @id @default(autoincrement())
token String @unique
createdAt DateTime @default(now())
expiry DateTime
userId Int
User User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model Passkey {
id String @id @default(cuid())
userId Int
name String
createdAt DateTime @default(now())
updatedAt DateTime @default(now())
lastUsedAt DateTime?
credentialId Bytes
credentialPublicKey Bytes
counter BigInt
credentialDeviceType String
credentialBackedUp Boolean
transports String[]
User User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model AnonymousVerificationToken {
id String @id @unique @default(cuid())
token String @unique
expiresAt DateTime
createdAt DateTime @default(now())
}
model VerificationToken {
id Int @id @default(autoincrement())
secondaryId String @unique @default(cuid())
identifier String
token String @unique
completed Boolean @default(false)
expires DateTime
createdAt DateTime @default(now())
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
enum WebhookTriggerEvents {
DOCUMENT_CREATED
DOCUMENT_SENT
DOCUMENT_OPENED
DOCUMENT_SIGNED
DOCUMENT_COMPLETED
}
model Webhook {
id String @id @default(cuid())
webhookUrl String
eventTriggers WebhookTriggerEvents[]
secret String?
enabled Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
userId Int
User User @relation(fields: [userId], references: [id], onDelete: Cascade)
teamId Int?
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
WebhookCall WebhookCall[]
}
enum WebhookCallStatus {
SUCCESS
FAILED
}
model WebhookCall {
id String @id @default(cuid())
status WebhookCallStatus
url String
event WebhookTriggerEvents
requestBody Json
responseCode Int
responseHeaders Json?
responseBody Json?
createdAt DateTime @default(now())
webhookId String
webhook Webhook @relation(fields: [webhookId], references: [id], onDelete: Cascade)
}
enum ApiTokenAlgorithm {
SHA512
}
model ApiToken {
id Int @id @default(autoincrement())
name String
token String @unique
algorithm ApiTokenAlgorithm @default(SHA512)
expires DateTime?
createdAt DateTime @default(now())
userId Int?
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
teamId Int?
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
}
enum SubscriptionStatus {
ACTIVE
PAST_DUE
INACTIVE
}
model Subscription {
id Int @id @default(autoincrement())
status SubscriptionStatus @default(INACTIVE)
planId String @unique
priceId String
periodEnd DateTime?
userId Int?
teamId Int? @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
cancelAtPeriodEnd Boolean @default(false)
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
User User? @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
}
model Account {
id String @id @default(cuid())
userId Int
type String
provider String
providerAccountId String
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
// Some providers return created_at so we need to make it optional
created_at Int?
// Stops next-auth from crashing when dealing with AzureAD
ext_expires_in Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId Int
expires DateTime
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
}
enum DocumentStatus {
DRAFT
PENDING
COMPLETED
}
enum DocumentSource {
DOCUMENT
TEMPLATE
TEMPLATE_DIRECT_LINK
}
model Document {
id Int @id @default(autoincrement())
externalId String?
userId Int
User User @relation(fields: [userId], references: [id], onDelete: Cascade)
authOptions Json?
formValues Json?
title String
status DocumentStatus @default(DRAFT)
Recipient Recipient[]
Field Field[]
ShareLink DocumentShareLink[]
documentDataId String
documentData DocumentData @relation(fields: [documentDataId], references: [id], onDelete: Cascade)
documentMeta DocumentMeta?
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
completedAt DateTime?
deletedAt DateTime?
teamId Int?
team Team? @relation(fields: [teamId], references: [id])
templateId Int?
template Template? @relation(fields: [templateId], references: [id], onDelete: SetNull)
source DocumentSource
auditLogs DocumentAuditLog[]
@@unique([documentDataId])
@@index([userId])
@@index([status])
}
model DocumentAuditLog {
id String @id @default(cuid())
documentId Int
createdAt DateTime @default(now())
type String
data Json
// Details of the person who performed the action which caused the audit log.
name String?
email String?
userId Int?
userAgent String?
ipAddress String?
Document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
}
enum DocumentDataType {
S3_PATH
BYTES
BYTES_64
}
enum DocumentSigningOrder {
PARALLEL
SEQUENTIAL
}
model DocumentData {
id String @id @default(cuid())
type DocumentDataType
data String
initialData String
Document Document?
Template Template?
}
model DocumentMeta {
id String @id @default(cuid())
subject String?
message String?
timezone String? @default("Etc/UTC") @db.Text
password String?
dateFormat String? @default("yyyy-MM-dd hh:mm a") @db.Text
documentId Int @unique
document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
redirectUrl String?
signingOrder DocumentSigningOrder @default(PARALLEL)
}
enum ReadStatus {
NOT_OPENED
OPENED
}
enum SendStatus {
NOT_SENT
SENT
}
enum SigningStatus {
NOT_SIGNED
SIGNED
}
enum RecipientRole {
CC
SIGNER
VIEWER
APPROVER
}
model Recipient {
id Int @id @default(autoincrement())
documentId Int?
templateId Int?
email String @db.VarChar(255)
name String @default("") @db.VarChar(255)
token String
documentDeletedAt DateTime?
expired DateTime?
signedAt DateTime?
authOptions Json?
signingOrder Int?
role RecipientRole @default(SIGNER)
readStatus ReadStatus @default(NOT_OPENED)
signingStatus SigningStatus @default(NOT_SIGNED)
sendStatus SendStatus @default(NOT_SENT)
Document Document? @relation(fields: [documentId], references: [id], onDelete: Cascade)
Template Template? @relation(fields: [templateId], references: [id], onDelete: Cascade)
Field Field[]
Signature Signature[]
@@unique([documentId, email])
@@unique([templateId, email])
@@index([documentId])
@@index([templateId])
@@index([token])
}
enum FieldType {
SIGNATURE
FREE_SIGNATURE
INITIALS
NAME
EMAIL
DATE
TEXT
NUMBER
RADIO
CHECKBOX
DROPDOWN
}
model Field {
id Int @id @default(autoincrement())
secondaryId String @unique @default(cuid())
documentId Int?
templateId Int?
recipientId Int
type FieldType
page Int
positionX Decimal @default(0)
positionY Decimal @default(0)
width Decimal @default(-1)
height Decimal @default(-1)
customText String
inserted Boolean
Document Document? @relation(fields: [documentId], references: [id], onDelete: Cascade)
Template Template? @relation(fields: [templateId], references: [id], onDelete: Cascade)
Recipient Recipient @relation(fields: [recipientId], references: [id], onDelete: Cascade)
Signature Signature?
fieldMeta Json?
@@index([documentId])
@@index([templateId])
@@index([recipientId])
}
model Signature {
id Int @id @default(autoincrement())
created DateTime @default(now())
recipientId Int
fieldId Int @unique
signatureImageAsBase64 String?
typedSignature String?
Recipient Recipient @relation(fields: [recipientId], references: [id], onDelete: Cascade)
Field Field @relation(fields: [fieldId], references: [id], onDelete: Cascade)
@@index([recipientId])
}
model DocumentShareLink {
id Int @id @default(autoincrement())
email String
slug String @unique
documentId Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
@@unique([documentId, email])
}
enum TeamMemberRole {
ADMIN
MANAGER
MEMBER
}
enum TeamMemberInviteStatus {
ACCEPTED
PENDING
DECLINED
}
model Team {
id Int @id @default(autoincrement())
name String
url String @unique
createdAt DateTime @default(now())
avatarImageId String?
customerId String? @unique
ownerUserId Int
members TeamMember[]
invites TeamMemberInvite[]
teamEmail TeamEmail?
emailVerification TeamEmailVerification?
transferVerification TeamTransferVerification?
avatarImage AvatarImage? @relation(fields: [avatarImageId], references: [id], onDelete: SetNull)
profile TeamProfile?
owner User @relation(fields: [ownerUserId], references: [id], onDelete: Cascade)
subscription Subscription?
document Document[]
templates Template[]
ApiToken ApiToken[]
Webhook Webhook[]
}
model TeamPending {
id Int @id @default(autoincrement())
name String
url String @unique
createdAt DateTime @default(now())
customerId String @unique
ownerUserId Int
owner User @relation(fields: [ownerUserId], references: [id], onDelete: Cascade)
}
model TeamMember {
id Int @id @default(autoincrement())
teamId Int
createdAt DateTime @default(now())
role TeamMemberRole
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
@@unique([userId, teamId])
}
model TeamEmail {
teamId Int @id @unique
createdAt DateTime @default(now())
name String
email String @unique
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
}
model TeamEmailVerification {
teamId Int @id @unique
name String
email String
token String @unique
completed Boolean @default(false)
expiresAt DateTime
createdAt DateTime @default(now())
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
}
model TeamTransferVerification {
teamId Int @id @unique
userId Int
name String
email String
token String @unique
completed Boolean @default(false)
expiresAt DateTime
createdAt DateTime @default(now())
clearPaymentMethods Boolean @default(false)
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
}
model TeamMemberInvite {
id Int @id @default(autoincrement())
teamId Int
createdAt DateTime @default(now())
email String
status TeamMemberInviteStatus @default(PENDING)
role TeamMemberRole
token String @unique
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
@@unique([teamId, email])
}
enum TemplateType {
PUBLIC
PRIVATE
}
model TemplateMeta {
id String @id @default(cuid())
subject String?
message String?
timezone String? @default("Etc/UTC") @db.Text
password String?
dateFormat String? @default("yyyy-MM-dd hh:mm a") @db.Text
signingOrder DocumentSigningOrder? @default(PARALLEL)
templateId Int @unique
template Template @relation(fields: [templateId], references: [id], onDelete: Cascade)
redirectUrl String?
}
model Template {
id Int @id @default(autoincrement())
externalId String?
type TemplateType @default(PRIVATE)
title String
userId Int
teamId Int?
authOptions Json?
templateMeta TemplateMeta?
templateDocumentDataId String
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
publicTitle String @default("")
publicDescription String @default("")
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
templateDocumentData DocumentData @relation(fields: [templateDocumentDataId], references: [id], onDelete: Cascade)
User User @relation(fields: [userId], references: [id], onDelete: Cascade)
Recipient Recipient[]
Field Field[]
directLink TemplateDirectLink?
documents Document[]
@@unique([templateDocumentDataId])
}
model TemplateDirectLink {
id String @id @unique @default(cuid())
templateId Int @unique
token String @unique
createdAt DateTime @default(now())
enabled Boolean
directTemplateRecipientId Int
template Template @relation(fields: [templateId], references: [id], onDelete: Cascade)
}
model SiteSettings {
id String @id
enabled Boolean @default(false)
data Json
lastModifiedByUserId Int?
lastModifiedAt DateTime @default(now())
lastModifiedByUser User? @relation(fields: [lastModifiedByUserId], references: [id], onDelete: SetNull)
}
enum BackgroundJobStatus {
PENDING
PROCESSING
COMPLETED
FAILED
}
model BackgroundJob {
id String @id @default(cuid())
status BackgroundJobStatus @default(PENDING)
payload Json?
retried Int @default(0)
maxRetries Int @default(3)
// Taken from the job definition
jobId String
name String
version String
submittedAt DateTime @default(now())
updatedAt DateTime @updatedAt
completedAt DateTime?
lastRetriedAt DateTime?
tasks BackgroundJobTask[]
}
enum BackgroundJobTaskStatus {
PENDING
COMPLETED
FAILED
}
model BackgroundJobTask {
id String @id
name String
status BackgroundJobTaskStatus @default(PENDING)
result Json?
retried Int @default(0)
maxRetries Int @default(3)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
completedAt DateTime?
jobId String
backgroundJob BackgroundJob @relation(fields: [jobId], references: [id], onDelete: Cascade)
}
model AvatarImage {
id String @id @default(cuid())
bytes String
team Team[]
user User[]
}