2024-03-20 15:42:17 +02:00
generator kysely {
provider = "prisma-kysely"
2023-01-07 15:10:26 +01:00
}
generator client {
2023-08-25 17:51:58 +10:00
provider = "prisma-client-js"
2023-01-07 15:10:26 +01:00
}
2025-01-15 13:46:45 +11:00
generator json {
provider = "prisma-json-types-generator"
}
2024-12-05 22:14:47 +09:00
generator zod {
2025-01-14 00:43:35 +11:00
provider = "zod-prisma-types"
createInputTypes = false
2025-01-02 15:33:37 +11:00
writeBarrelFiles = false
2025-01-14 00:43:35 +11:00
useMultipleFiles = true
2024-12-05 22:14:47 +09:00
}
2023-01-07 15:10:26 +01:00
datasource db {
2023-08-25 17:51:58 +10:00
provider = "postgresql"
url = env("NEXT_PRIVATE_DATABASE_URL")
directUrl = env("NEXT_PRIVATE_DIRECT_DATABASE_URL")
2023-01-07 15:10:26 +01:00
}
2025-02-19 16:07:04 +11:00
// Todo: (RR7) Remove after RR7 migration.
2023-02-19 12:49:09 +01:00
enum IdentityProvider {
DOCUMENSO
GOOGLE
2024-04-13 20:46:08 -04:00
OIDC
2023-01-07 15:10:26 +01:00
}
2023-09-08 09:16:31 +03:00
enum Role {
ADMIN
USER
}
2023-01-07 15:10:26 +01:00
model User {
2024-06-27 21:50:42 +10:00
id Int @id @default(autoincrement())
name String?
customerId String? @unique
email String @unique
emailVerified DateTime?
2025-02-19 16:07:04 +11:00
password String? // Todo: (RR7) Remove after RR7 migration.
2024-06-27 21:50:42 +10:00
source String?
signature String?
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
lastSignedIn DateTime @default(now())
roles Role[] @default([USER])
2025-02-19 16:07:04 +11:00
identityProvider IdentityProvider @default(DOCUMENSO) // Todo: (RR7) Remove after RR7 migration.
2024-06-27 21:50:42 +10:00
avatarImageId String?
2024-12-17 13:35:59 +02:00
disabled Boolean @default(false)
2024-06-27 21:50:42 +10:00
2023-12-01 05:52:16 +05:30
accounts Account[]
sessions Session[]
2025-01-13 13:41:53 +11:00
documents Document[]
subscriptions Subscription[]
passwordResetTokens PasswordResetToken[]
2024-02-06 16:16:10 +11:00
ownedTeams Team[]
ownedPendingTeams TeamPending[]
teamMembers TeamMember[]
2023-12-01 05:52:16 +05:30
twoFactorSecret String?
2024-02-22 01:57:46 +05:30
twoFactorEnabled Boolean @default(false)
2023-12-01 05:52:16 +05:30
twoFactorBackupCodes String?
2024-02-28 14:43:09 +11:00
url String? @unique
2024-02-22 01:57:46 +05:30
2025-01-13 13:41:53 +11:00
profile UserProfile?
verificationTokens VerificationToken[]
apiTokens ApiToken[]
templates Template[]
securityAuditLogs UserSecurityAuditLog[]
webhooks Webhook[]
siteSettings SiteSettings[]
passkeys Passkey[]
avatarImage AvatarImage? @relation(fields: [avatarImageId], references: [id], onDelete: SetNull)
2023-11-23 15:21:13 +02:00
2023-10-30 16:58:51 +11:00
@@index([email])
2023-09-18 06:47:03 +00:00
}
2024-02-22 01:57:46 +05:30
model UserProfile {
2024-06-06 14:46:48 +10:00
id String @id @default(cuid())
enabled Boolean @default(false)
userId Int @unique
bio String?
2024-02-22 01:57:46 +05:30
2024-06-06 14:46:48 +10:00
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)
2024-02-22 01:57:46 +05:30
}
2024-01-30 17:31:27 +11:00
enum UserSecurityAuditLogType {
ACCOUNT_PROFILE_UPDATE
ACCOUNT_SSO_LINK
AUTH_2FA_DISABLE
AUTH_2FA_ENABLE
2024-03-26 21:11:59 +08:00
PASSKEY_CREATED
PASSKEY_DELETED
PASSKEY_UPDATED
2024-01-30 17:31:27 +11:00
PASSWORD_RESET
PASSWORD_UPDATE
SIGN_OUT
SIGN_IN
2024-01-31 12:27:40 +11:00
SIGN_IN_FAIL
SIGN_IN_2FA_FAIL
2024-03-26 21:11:59 +08:00
SIGN_IN_PASSKEY_FAIL
2024-01-30 17:31:27 +11:00
}
model UserSecurityAuditLog {
id Int @id @default(autoincrement())
userId Int
createdAt DateTime @default(now())
type UserSecurityAuditLogType
userAgent String?
ipAddress String?
2025-01-13 13:41:53 +11:00
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
2024-01-30 17:31:27 +11:00
}
2023-09-18 06:47:03 +00:00
model PasswordResetToken {
id Int @id @default(autoincrement())
token String @unique
createdAt DateTime @default(now())
expiry DateTime
userId Int
2025-01-13 13:41:53 +11:00
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
2023-05-05 19:29:42 +10:00
}
2024-03-26 21:11:59 +08:00
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[]
2025-01-13 13:41:53 +11:00
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
2024-03-26 21:11:59 +08:00
}
model AnonymousVerificationToken {
id String @id @unique @default(cuid())
token String @unique
expiresAt DateTime
createdAt DateTime @default(now())
}
2023-11-21 06:42:29 +02:00
model VerificationToken {
2024-03-31 15:49:12 +08:00
id Int @id @default(autoincrement())
secondaryId String @unique @default(cuid())
identifier String
token String @unique
2024-08-28 14:08:35 +10:00
completed Boolean @default(false)
2024-03-31 15:49:12 +08:00
expires DateTime
createdAt DateTime @default(now())
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
2023-11-21 06:42:29 +02:00
}
2024-02-06 16:00:28 +02:00
enum WebhookTriggerEvents {
DOCUMENT_CREATED
2024-02-24 11:18:58 +02:00
DOCUMENT_SENT
DOCUMENT_OPENED
2024-02-06 16:00:28 +02:00
DOCUMENT_SIGNED
2024-02-24 11:18:58 +02:00
DOCUMENT_COMPLETED
2024-12-04 14:35:20 +11:00
DOCUMENT_REJECTED
2025-01-28 06:34:22 +02:00
DOCUMENT_CANCELLED
2024-02-06 16:00:28 +02:00
}
model Webhook {
2024-02-27 12:13:56 +11:00
id String @id @default(cuid())
2024-02-06 16:00:28 +02:00
webhookUrl String
eventTriggers WebhookTriggerEvents[]
secret String?
enabled Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
userId Int
2025-01-13 13:41:53 +11:00
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
2024-02-27 13:38:12 +11:00
teamId Int?
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
2025-01-13 13:41:53 +11:00
webhookCalls WebhookCall[]
2024-02-27 12:54:37 +11:00
}
enum WebhookCallStatus {
SUCCESS
FAILED
}
model WebhookCall {
2024-02-27 15:16:14 +11:00
id String @id @default(cuid())
2024-02-27 12:54:37 +11:00
status WebhookCallStatus
url String
2024-02-27 15:16:14 +11:00
event WebhookTriggerEvents
2024-02-27 12:54:37 +11:00
requestBody Json
responseCode Int
responseHeaders Json?
responseBody Json?
2024-02-27 15:16:14 +11:00
createdAt DateTime @default(now())
2024-02-27 12:54:37 +11:00
webhookId String
2024-02-27 15:16:14 +11:00
webhook Webhook @relation(fields: [webhookId], references: [id], onDelete: Cascade)
2024-02-06 16:00:28 +02:00
}
2023-11-23 15:21:13 +02:00
enum ApiTokenAlgorithm {
SHA512
}
model ApiToken {
id Int @id @default(autoincrement())
name String
token String @unique
algorithm ApiTokenAlgorithm @default(SHA512)
2024-02-09 11:32:54 +02:00
expires DateTime?
2023-11-23 15:21:13 +02:00
createdAt DateTime @default(now())
2024-02-22 13:39:34 +11:00
userId Int?
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
teamId Int?
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
2023-11-23 15:21:13 +02:00
}
2023-05-05 19:29:42 +10:00
enum SubscriptionStatus {
ACTIVE
PAST_DUE
INACTIVE
}
model Subscription {
2023-09-18 22:33:07 +10:00
id Int @id @default(autoincrement())
status SubscriptionStatus @default(INACTIVE)
2023-12-14 15:22:54 +11:00
planId String @unique
priceId String
2023-09-18 22:33:07 +10:00
periodEnd DateTime?
2024-02-06 16:16:10 +11:00
userId Int?
teamId Int? @unique
2023-09-18 22:33:07 +10:00
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
cancelAtPeriodEnd Boolean @default(false)
2023-05-05 19:29:42 +10:00
2024-02-06 16:16:10 +11:00
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
2025-01-13 13:41:53 +11:00
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
2023-05-05 19:29:42 +10:00
@@index([userId])
2023-01-10 18:52:04 +01:00
}
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?
2024-05-30 22:15:45 +10:00
// 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?
2023-01-10 18:52:04 +01:00
token_type String?
scope String?
id_token String? @db.Text
session_state String?
2025-01-02 15:33:37 +11:00
password String?
2023-01-10 18:52:04 +01:00
2025-01-02 15:33:37 +11:00
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
2023-01-10 18:52:04 +01:00
@@unique([provider, providerAccountId])
}
model Session {
2025-01-02 15:33:37 +11:00
id String @id @default(cuid())
sessionToken String @unique
2023-01-10 18:52:04 +01:00
userId Int
2025-01-02 15:33:37 +11:00
ipAddress String?
userAgent String?
expiresAt DateTime
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
2023-01-10 18:52:04 +01:00
}
2023-02-19 12:49:09 +01:00
enum DocumentStatus {
DRAFT
PENDING
COMPLETED
2023-02-13 19:33:26 +01:00
}
2024-06-02 15:49:09 +10:00
enum DocumentSource {
DOCUMENT
TEMPLATE
TEMPLATE_DIRECT_LINK
}
2024-09-16 17:14:16 +03:00
enum DocumentVisibility {
EVERYONE
MANAGER_AND_ABOVE
ADMIN
}
2025-01-15 13:46:45 +11:00
/// @zod.import(["import { ZDocumentAuthOptionsSchema } from '@documenso/lib/types/document-auth';", "import { ZDocumentFormValuesSchema } from '@documenso/lib/types/document-form-values';"])
2023-02-19 12:49:09 +01:00
model Document {
2023-09-21 00:51:02 +00:00
id Int @id @default(autoincrement())
2025-01-14 00:43:35 +11:00
externalId String? /// @zod.string.describe("A custom external ID you can use to identify the document.")
userId Int /// @zod.number.describe("The ID of the user that created this document.")
2025-01-13 13:41:53 +11:00
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
2025-01-15 13:46:45 +11:00
authOptions Json? /// [DocumentAuthOptions] @zod.custom.use(ZDocumentAuthOptionsSchema)
formValues Json? /// [DocumentFormValues] @zod.custom.use(ZDocumentFormValuesSchema)
2024-09-16 17:14:16 +03:00
visibility DocumentVisibility @default(EVERYONE)
2023-09-21 00:51:02 +00:00
title String
status DocumentStatus @default(DRAFT)
2025-01-13 13:41:53 +11:00
recipients Recipient[]
fields Field[]
shareLinks DocumentShareLink[]
2023-09-21 00:51:02 +00:00
documentDataId String
2023-10-28 20:57:26 +11:00
documentData DocumentData @relation(fields: [documentDataId], references: [id], onDelete: Cascade)
2023-09-22 12:27:54 +00:00
documentMeta DocumentMeta?
2023-10-28 20:57:26 +11:00
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
2023-11-03 15:48:19 +11:00
completedAt DateTime?
2023-12-06 05:41:51 +05:30
deletedAt DateTime?
2024-02-06 16:16:10 +11:00
teamId Int?
team Team? @relation(fields: [teamId], references: [id])
2024-06-02 15:49:09 +10:00
templateId Int?
template Template? @relation(fields: [templateId], references: [id], onDelete: SetNull)
source DocumentSource
2023-09-20 08:57:50 +00:00
2024-02-12 12:04:53 +11:00
auditLogs DocumentAuditLog[]
2023-09-21 00:51:02 +00:00
@@unique([documentDataId])
2023-10-30 16:58:51 +11:00
@@index([userId])
@@index([status])
2023-09-21 00:51:02 +00:00
}
2024-02-12 12:04:53 +11:00
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)
}
2023-09-21 00:51:02 +00:00
enum DocumentDataType {
S3_PATH
BYTES
BYTES_64
}
2024-09-16 12:36:45 +00:00
enum DocumentSigningOrder {
PARALLEL
SEQUENTIAL
}
2023-09-21 00:51:02 +00:00
model DocumentData {
id String @id @default(cuid())
type DocumentDataType
data String
initialData String
2025-01-13 13:41:53 +11:00
document Document?
template Template?
2023-01-07 15:10:26 +01:00
}
2024-11-08 13:32:13 +09:00
enum DocumentDistributionMethod {
EMAIL
NONE
}
2025-01-15 13:46:45 +11:00
/// @zod.import(["import { ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email';"])
2023-09-20 08:57:50 +00:00
model DocumentMeta {
2024-11-08 13:32:13 +09:00
id String @id @default(cuid())
2024-10-18 04:25:19 +01:00
subject String?
message String?
2024-11-08 13:32:13 +09:00
timezone String? @default("Etc/UTC") @db.Text
2024-10-18 04:25:19 +01:00
password String?
2024-11-08 13:32:13 +09:00
dateFormat String? @default("yyyy-MM-dd hh:mm a") @db.Text
documentId Int @unique
document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
2024-10-18 04:25:19 +01:00
redirectUrl String?
2024-11-08 13:32:13 +09:00
signingOrder DocumentSigningOrder @default(PARALLEL)
2024-11-26 12:03:44 +02:00
typedSignatureEnabled Boolean @default(true)
2024-11-08 13:32:13 +09:00
language String @default("en")
distributionMethod DocumentDistributionMethod @default(EMAIL)
2025-01-15 13:46:45 +11:00
emailSettings Json? /// [DocumentEmailSettings] @zod.custom.use(ZDocumentEmailSettingsSchema)
2023-09-20 08:57:50 +00:00
}
2023-01-07 15:10:26 +01:00
enum ReadStatus {
NOT_OPENED
OPENED
}
enum SendStatus {
NOT_SENT
SENT
}
enum SigningStatus {
NOT_SIGNED
SIGNED
2024-11-14 21:37:42 +11:00
REJECTED
2023-01-07 15:10:26 +01:00
}
2023-01-27 20:14:32 +01:00
2024-02-01 18:45:02 -05:00
enum RecipientRole {
CC
SIGNER
VIEWER
APPROVER
2025-02-01 03:31:18 +00:00
ASSISTANT
2024-02-01 18:45:02 -05:00
}
2025-01-14 00:43:35 +11:00
/// @zod.import(["import { ZRecipientAuthOptionsSchema } from '@documenso/lib/types/document-auth';"])
2023-02-19 12:49:09 +01:00
model Recipient {
2024-04-19 17:37:38 +07:00
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?
2025-01-15 13:46:45 +11:00
authOptions Json? /// [RecipientAuthOptions] @zod.custom.use(ZRecipientAuthOptionsSchema)
2025-01-14 00:43:35 +11:00
signingOrder Int? /// @zod.number.describe("The order in which the recipient should sign the document. Only works if the document is set to sequential signing.")
2024-11-14 21:37:42 +11:00
rejectionReason String?
2024-04-19 17:37:38 +07:00
role RecipientRole @default(SIGNER)
readStatus ReadStatus @default(NOT_OPENED)
signingStatus SigningStatus @default(NOT_SIGNED)
sendStatus SendStatus @default(NOT_SENT)
2025-01-13 13:41:53 +11:00
document Document? @relation(fields: [documentId], references: [id], onDelete: Cascade)
template Template? @relation(fields: [templateId], references: [id], onDelete: Cascade)
fields Field[]
signatures Signature[]
2023-06-21 23:49:23 +10:00
@@unique([documentId, email])
2023-10-06 22:54:24 +00:00
@@unique([templateId, email])
2023-10-30 16:58:51 +11:00
@@index([documentId])
2023-10-06 22:54:24 +00:00
@@index([templateId])
2023-10-30 16:58:51 +11:00
@@index([token])
2023-02-19 12:49:09 +01:00
}
enum FieldType {
SIGNATURE
2023-02-24 16:12:56 +01:00
FREE_SIGNATURE
2024-08-12 15:29:32 +02:00
INITIALS
2023-06-21 23:49:23 +10:00
NAME
EMAIL
2023-02-19 12:49:09 +01:00
DATE
TEXT
2024-07-18 16:45:44 +03:00
NUMBER
RADIO
CHECKBOX
DROPDOWN
2023-02-19 12:49:09 +01:00
}
2025-01-15 13:46:45 +11:00
/// @zod.import(["import { ZFieldMetaNotOptionalSchema } from '@documenso/lib/types/field-meta';"])
2023-02-19 12:49:09 +01:00
model Field {
id Int @id @default(autoincrement())
2024-02-12 12:04:53 +11:00
secondaryId String @unique @default(cuid())
2023-10-06 22:54:24 +00:00
documentId Int?
templateId Int?
2024-04-18 21:56:31 +07:00
recipientId Int
2023-02-19 12:49:09 +01:00
type FieldType
2025-01-14 00:43:35 +11:00
page Int /// @zod.number.describe("The page number of the field on the document. Starts from 1.")
2023-06-23 12:20:49 +00:00
positionX Decimal @default(0)
positionY Decimal @default(0)
width Decimal @default(-1)
height Decimal @default(-1)
2023-02-28 19:36:21 +01:00
customText String
2023-03-09 13:43:05 +01:00
inserted Boolean
2025-01-13 13:41:53 +11:00
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?
2025-01-15 13:46:45 +11:00
fieldMeta Json? /// [FieldMeta] @zod.custom.use(ZFieldMetaNotOptionalSchema)
2023-10-30 16:58:51 +11:00
@@index([documentId])
2023-10-06 22:54:24 +00:00
@@index([templateId])
2023-10-30 16:58:51 +11:00
@@index([recipientId])
2023-02-19 12:49:09 +01:00
}
model Signature {
id Int @id @default(autoincrement())
created DateTime @default(now())
recipientId Int
fieldId Int @unique
2023-02-20 18:14:52 +01:00
signatureImageAsBase64 String?
typedSignature String?
2023-02-19 12:49:09 +01:00
2025-01-13 13:41:53 +11:00
recipient Recipient @relation(fields: [recipientId], references: [id], onDelete: Cascade)
field Field @relation(fields: [fieldId], references: [id], onDelete: Cascade)
2023-10-30 16:58:51 +11:00
@@index([recipientId])
2023-01-27 20:14:32 +01:00
}
2023-06-05 12:23:52 +00:00
2023-09-21 00:51:02 +00:00
model DocumentShareLink {
id Int @id @default(autoincrement())
email String
slug String @unique
documentId Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
2023-10-13 12:45:39 +11:00
document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
2023-09-21 00:51:02 +00:00
@@unique([documentId, email])
2023-06-05 12:23:52 +00:00
}
2023-10-06 22:54:24 +00:00
2024-02-06 16:16:10 +11:00
enum TeamMemberRole {
ADMIN
MANAGER
MEMBER
}
enum TeamMemberInviteStatus {
ACCEPTED
PENDING
2024-07-25 04:27:19 +00:00
DECLINED
2024-02-06 16:16:10 +11:00
}
feat: add global settings for teams (#1391)
## Description
This PR introduces global settings for teams. At the moment, it allows
team admins to configure the following:
* The default visibility of the documents uploaded to the team account
* Whether to include the document owner (sender) details when sending
emails to the recipients.
### Include Sender Details
If the Sender Details setting is enabled, the emails sent by the team
will include the sender's name:
> "Example User" on behalf of "Example Team" has invited you to sign
"document.pdf"
Otherwise, the email will say:
> "Example Team" has invited you to sign "document.pdf"
### Default Document Visibility
This new option allows users to set the default visibility for the
documents uploaded to the team account. It can have the following
values:
* Everyone
* Manager and above
* Admins only
If the default document visibility isn't set, the document will be set
to the role of the user who created the document:
* If a user with the "User" role creates a document, the document's
visibility is set to "Everyone".
* Manager role -> "Manager and above"
* Admin role -> "Admins only"
Otherwise, if there is a default document visibility value, it uses that
value.
#### Gotcha
To avoid issues, the `document owner` and the `recipient` can access the
document irrespective of their role. For example:
* If a team member with the role "Member" uploads a document and the
default document visibility is "Admins", only the document owner and
admins can access the document.
* Similar to the other scenarios.
* If an admin uploads a document and the default document visibility is
"Admins", the recipient can access the document.
* The admins have access to all the documents.
* Managers have access to documents with the visibility set to
"Everyone" and "Manager and above"
* Members have access only to the documents with the visibility set to
"Everyone".
## Testing Performed
Tested it locally.
2024-11-08 13:50:49 +02:00
model TeamGlobalSettings {
2024-11-25 06:47:26 +02:00
teamId Int @unique
documentVisibility DocumentVisibility @default(EVERYONE)
documentLanguage String @default("en")
includeSenderDetails Boolean @default(true)
2024-11-26 12:03:44 +02:00
typedSignatureEnabled Boolean @default(true)
2024-11-25 06:47:26 +02:00
includeSigningCertificate Boolean @default(true)
feat: add global settings for teams (#1391)
## Description
This PR introduces global settings for teams. At the moment, it allows
team admins to configure the following:
* The default visibility of the documents uploaded to the team account
* Whether to include the document owner (sender) details when sending
emails to the recipients.
### Include Sender Details
If the Sender Details setting is enabled, the emails sent by the team
will include the sender's name:
> "Example User" on behalf of "Example Team" has invited you to sign
"document.pdf"
Otherwise, the email will say:
> "Example Team" has invited you to sign "document.pdf"
### Default Document Visibility
This new option allows users to set the default visibility for the
documents uploaded to the team account. It can have the following
values:
* Everyone
* Manager and above
* Admins only
If the default document visibility isn't set, the document will be set
to the role of the user who created the document:
* If a user with the "User" role creates a document, the document's
visibility is set to "Everyone".
* Manager role -> "Manager and above"
* Admin role -> "Admins only"
Otherwise, if there is a default document visibility value, it uses that
value.
#### Gotcha
To avoid issues, the `document owner` and the `recipient` can access the
document irrespective of their role. For example:
* If a team member with the role "Member" uploads a document and the
default document visibility is "Admins", only the document owner and
admins can access the document.
* Similar to the other scenarios.
* If an admin uploads a document and the default document visibility is
"Admins", the recipient can access the document.
* The admins have access to all the documents.
* Managers have access to documents with the visibility set to
"Everyone" and "Manager and above"
* Members have access only to the documents with the visibility set to
"Everyone".
## Testing Performed
Tested it locally.
2024-11-08 13:50:49 +02:00
brandingEnabled Boolean @default(false)
brandingLogo String @default("")
brandingUrl String @default("")
brandingCompanyDetails String @default("")
brandingHidePoweredBy Boolean @default(false)
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
}
2024-02-06 16:16:10 +11:00
model Team {
2024-06-27 21:50:42 +10:00
id Int @id @default(autoincrement())
name String
url String @unique
createdAt DateTime @default(now())
avatarImageId String?
customerId String? @unique
ownerUserId Int
2024-02-06 16:16:10 +11:00
members TeamMember[]
invites TeamMemberInvite[]
teamEmail TeamEmail?
emailVerification TeamEmailVerification?
transferVerification TeamTransferVerification?
feat: add global settings for teams (#1391)
## Description
This PR introduces global settings for teams. At the moment, it allows
team admins to configure the following:
* The default visibility of the documents uploaded to the team account
* Whether to include the document owner (sender) details when sending
emails to the recipients.
### Include Sender Details
If the Sender Details setting is enabled, the emails sent by the team
will include the sender's name:
> "Example User" on behalf of "Example Team" has invited you to sign
"document.pdf"
Otherwise, the email will say:
> "Example Team" has invited you to sign "document.pdf"
### Default Document Visibility
This new option allows users to set the default visibility for the
documents uploaded to the team account. It can have the following
values:
* Everyone
* Manager and above
* Admins only
If the default document visibility isn't set, the document will be set
to the role of the user who created the document:
* If a user with the "User" role creates a document, the document's
visibility is set to "Everyone".
* Manager role -> "Manager and above"
* Admin role -> "Admins only"
Otherwise, if there is a default document visibility value, it uses that
value.
#### Gotcha
To avoid issues, the `document owner` and the `recipient` can access the
document irrespective of their role. For example:
* If a team member with the role "Member" uploads a document and the
default document visibility is "Admins", only the document owner and
admins can access the document.
* Similar to the other scenarios.
* If an admin uploads a document and the default document visibility is
"Admins", the recipient can access the document.
* The admins have access to all the documents.
* Managers have access to documents with the visibility set to
"Everyone" and "Manager and above"
* Members have access only to the documents with the visibility set to
"Everyone".
## Testing Performed
Tested it locally.
2024-11-08 13:50:49 +02:00
teamGlobalSettings TeamGlobalSettings?
2024-06-27 21:50:42 +10:00
avatarImage AvatarImage? @relation(fields: [avatarImageId], references: [id], onDelete: SetNull)
2024-02-06 16:16:10 +11:00
2024-06-06 14:46:48 +10:00
profile TeamProfile?
2024-04-24 17:32:11 +10:00
owner User @relation(fields: [ownerUserId], references: [id], onDelete: Cascade)
2024-02-06 16:16:10 +11:00
subscription Subscription?
2025-01-13 13:41:53 +11:00
documents Document[]
2024-02-08 12:33:20 +11:00
templates Template[]
2025-01-13 13:41:53 +11:00
apiTokens ApiToken[]
webhooks Webhook[]
2024-02-06 16:16:10 +11:00
}
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
2024-04-24 17:32:11 +10:00
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
2024-02-06 16:16:10 +11:00
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
2024-08-28 14:08:35 +10:00
completed Boolean @default(false)
2024-02-06 16:16:10 +11:00
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
2024-08-28 14:08:35 +10:00
completed Boolean @default(false)
2024-02-06 16:16:10 +11:00
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)
}
2023-10-06 22:54:24 +00:00
enum TemplateType {
PUBLIC
PRIVATE
}
2025-01-15 13:46:45 +11:00
/// @zod.import(["import { ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email';"])
2024-05-10 19:45:19 +07:00
model TemplateMeta {
2024-11-26 12:03:44 +02:00
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)
typedSignatureEnabled Boolean @default(true)
distributionMethod DocumentDistributionMethod @default(EMAIL)
templateId Int @unique
template Template @relation(fields: [templateId], references: [id], onDelete: Cascade)
redirectUrl String?
language String @default("en")
2025-01-15 13:46:45 +11:00
emailSettings Json? /// [DocumentEmailSettings] @zod.custom.use(ZDocumentEmailSettingsSchema)
2024-05-10 19:45:19 +07:00
}
2025-01-15 13:46:45 +11:00
/// @zod.import(["import { ZDocumentAuthOptionsSchema } from '@documenso/lib/types/document-auth';"])
2023-10-06 22:54:24 +00:00
model Template {
2025-01-09 01:14:24 +02:00
id Int @id @default(autoincrement())
2024-07-13 16:45:09 +10:00
externalId String?
2025-01-09 01:14:24 +02:00
type TemplateType @default(PRIVATE)
2023-12-15 22:07:27 +11:00
title String
userId Int
2024-02-08 12:33:20 +11:00
teamId Int?
2025-01-09 01:14:24 +02:00
visibility DocumentVisibility @default(EVERYONE)
2025-01-15 13:46:45 +11:00
authOptions Json? /// [DocumentAuthOptions] @zod.custom.use(ZDocumentAuthOptionsSchema)
2024-05-10 19:45:19 +07:00
templateMeta TemplateMeta?
2023-10-06 22:54:24 +00:00
templateDocumentDataId String
2025-01-09 01:14:24 +02:00
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
publicTitle String @default("")
publicDescription String @default("")
2023-12-15 22:07:27 +11:00
2024-06-02 15:49:09 +10:00
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
templateDocumentData DocumentData @relation(fields: [templateDocumentDataId], references: [id], onDelete: Cascade)
2025-01-13 13:41:53 +11:00
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
recipients Recipient[]
fields Field[]
2024-06-02 15:49:09 +10:00
directLink TemplateDirectLink?
documents Document[]
2023-10-06 22:54:24 +00:00
@@unique([templateDocumentDataId])
}
2024-02-22 20:13:17 +00:00
2024-06-02 15:49:09 +10:00
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)
}
2024-02-23 10:47:01 +00:00
model SiteSettings {
id String @id
enabled Boolean @default(false)
data Json
lastModifiedByUserId Int?
lastModifiedAt DateTime @default(now())
2024-04-24 17:32:11 +10:00
lastModifiedByUser User? @relation(fields: [lastModifiedByUserId], references: [id], onDelete: SetNull)
2024-02-22 20:13:17 +00:00
}
2024-05-16 15:44:39 +10:00
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)
}
2024-06-27 21:50:42 +10:00
model AvatarImage {
id String @id @default(cuid())
bytes String
team Team[]
user User[]
}