mirror of
https://github.com/documenso/documenso.git
synced 2025-11-12 07:43:16 +10:00
## Description Added the ability for recipients to see fields from other recipients who have completed the document when they are signing the document Added the ability for the document owner to see fields from recipients who have completed the field on the document page view (only visible when the document is pending) ## 🚨🚨 Migrations🚨🚨 - Drop all `Fields` that do not have a `Recipient` set (not sure how it was possible in the first place) - Remove optional `Recipient` field on `Field` which doesn't make sense <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit - **New Features** - Enhanced document viewing by adding read-only fields based on document status. - Improved signing page by fetching and displaying completed fields for tokens. - Updated avatar component to show recipient status with tooltips for better user interaction. - **Bug Fixes** - Made `recipientId` a required field in the database to ensure data consistency. - **Refactor** - Optimized popover functionality in UI components for better performance and user experience. - **Documentation** - Added detailed component and function descriptions for new features in the system. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
569 lines
16 KiB
Plaintext
569 lines
16 KiB
Plaintext
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
|
|
}
|
|
|
|
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)
|
|
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
|
|
|
|
userProfile UserProfile?
|
|
VerificationToken VerificationToken[]
|
|
ApiToken ApiToken[]
|
|
Template Template[]
|
|
securityAuditLogs UserSecurityAuditLog[]
|
|
Webhooks Webhook[]
|
|
siteSettings SiteSettings[]
|
|
passkeys Passkey[]
|
|
|
|
@@index([email])
|
|
}
|
|
|
|
model UserProfile {
|
|
id Int @id
|
|
bio String?
|
|
|
|
User User? @relation(fields: [id], 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
|
|
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?
|
|
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
|
|
}
|
|
|
|
model Document {
|
|
id Int @id @default(autoincrement())
|
|
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])
|
|
|
|
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
|
|
}
|
|
|
|
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?
|
|
}
|
|
|
|
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?
|
|
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
|
|
NAME
|
|
EMAIL
|
|
DATE
|
|
TEXT
|
|
}
|
|
|
|
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?
|
|
|
|
@@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
|
|
}
|
|
|
|
model Team {
|
|
id Int @id @default(autoincrement())
|
|
name String
|
|
url String @unique
|
|
createdAt DateTime @default(now())
|
|
customerId String? @unique
|
|
ownerUserId Int
|
|
members TeamMember[]
|
|
invites TeamMemberInvite[]
|
|
teamEmail TeamEmail?
|
|
emailVerification TeamEmailVerification?
|
|
transferVerification TeamTransferVerification?
|
|
|
|
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
|
|
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
|
|
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 Template {
|
|
id Int @id @default(autoincrement())
|
|
type TemplateType @default(PRIVATE)
|
|
title String
|
|
userId Int
|
|
teamId Int?
|
|
templateDocumentDataId String
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @default(now()) @updatedAt
|
|
|
|
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[]
|
|
|
|
@@unique([templateDocumentDataId])
|
|
}
|
|
|
|
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)
|
|
}
|