Merge branch 'main' into feat/document-2fa-redo

This commit is contained in:
Ephraim Atta-Duncan
2025-08-01 09:00:30 +00:00
167 changed files with 6918 additions and 1245 deletions

View File

@ -0,0 +1,94 @@
-- [CUSTOM_MIGRATION] Required to fill in missing rows for `emailDocumentSettings` column.
ALTER TABLE "OrganisationGlobalSettings" ADD COLUMN "emailDocumentSettings" JSONB;
-- [CUSTOM_CHANGE] Insert default values for `emailDocumentSettings` column.
UPDATE "OrganisationGlobalSettings"
SET "emailDocumentSettings" = '{
"recipientSigningRequest": true,
"recipientRemoved": true,
"recipientSigned": true,
"documentPending": true,
"documentCompleted": true,
"documentDeleted": true,
"ownerDocumentCompleted": true
}'::jsonb
WHERE "emailDocumentSettings" IS NULL;
-- CreateEnum
CREATE TYPE "EmailDomainStatus" AS ENUM ('PENDING', 'ACTIVE');
-- AlterTable
ALTER TABLE "DocumentMeta" ADD COLUMN "emailId" TEXT,
ADD COLUMN "emailReplyTo" TEXT;
-- AlterTable
ALTER TABLE "OrganisationGlobalSettings" ADD COLUMN "documentDateFormat" TEXT NOT NULL DEFAULT 'yyyy-MM-dd hh:mm a',
ADD COLUMN "documentTimezone" TEXT,
ADD COLUMN "emailId" TEXT,
ADD COLUMN "emailReplyTo" TEXT;
-- [CUSTOM_MIGRATION] Set the `emailDocumentSettings` column back to not null.
ALTER TABLE "OrganisationGlobalSettings" ALTER COLUMN "emailDocumentSettings" SET NOT NULL;
-- AlterTable
ALTER TABLE "TeamGlobalSettings" ADD COLUMN "documentDateFormat" TEXT,
ADD COLUMN "documentTimezone" TEXT,
ADD COLUMN "emailDocumentSettings" JSONB,
ADD COLUMN "emailId" TEXT,
ADD COLUMN "emailReplyTo" TEXT;
-- AlterTable
ALTER TABLE "TemplateMeta" ADD COLUMN "emailId" TEXT,
ADD COLUMN "emailReplyTo" TEXT;
-- CreateTable
CREATE TABLE "EmailDomain" (
"id" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"status" "EmailDomainStatus" NOT NULL DEFAULT 'PENDING',
"selector" TEXT NOT NULL,
"domain" TEXT NOT NULL,
"publicKey" TEXT NOT NULL,
"privateKey" TEXT NOT NULL,
"organisationId" TEXT NOT NULL,
CONSTRAINT "EmailDomain_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "OrganisationEmail" (
"id" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"email" TEXT NOT NULL,
"emailName" TEXT NOT NULL,
"emailDomainId" TEXT NOT NULL,
"organisationId" TEXT NOT NULL,
CONSTRAINT "OrganisationEmail_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "EmailDomain_selector_key" ON "EmailDomain"("selector");
-- CreateIndex
CREATE UNIQUE INDEX "EmailDomain_domain_key" ON "EmailDomain"("domain");
-- CreateIndex
CREATE UNIQUE INDEX "OrganisationEmail_email_key" ON "OrganisationEmail"("email");
-- AddForeignKey
ALTER TABLE "OrganisationGlobalSettings" ADD CONSTRAINT "OrganisationGlobalSettings_emailId_fkey" FOREIGN KEY ("emailId") REFERENCES "OrganisationEmail"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "TeamGlobalSettings" ADD CONSTRAINT "TeamGlobalSettings_emailId_fkey" FOREIGN KEY ("emailId") REFERENCES "OrganisationEmail"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "EmailDomain" ADD CONSTRAINT "EmailDomain_organisationId_fkey" FOREIGN KEY ("organisationId") REFERENCES "Organisation"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "OrganisationEmail" ADD CONSTRAINT "OrganisationEmail_emailDomainId_fkey" FOREIGN KEY ("emailDomainId") REFERENCES "EmailDomain"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "OrganisationEmail" ADD CONSTRAINT "OrganisationEmail_organisationId_fkey" FOREIGN KEY ("organisationId") REFERENCES "Organisation"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -469,7 +469,10 @@ model DocumentMeta {
language String @default("en")
distributionMethod DocumentDistributionMethod @default(EMAIL)
emailSettings Json? /// [DocumentEmailSettings] @zod.custom.use(ZDocumentEmailSettingsSchema)
emailSettings Json? /// [DocumentEmailSettings] @zod.custom.use(ZDocumentEmailSettingsSchema)
emailReplyTo String?
emailId String?
}
enum ReadStatus {
@ -620,6 +623,9 @@ model Organisation {
teams Team[]
emailDomains EmailDomain[]
organisationEmails OrganisationEmail[]
avatarImage AvatarImage? @relation(fields: [avatarImageId], references: [id], onDelete: SetNull)
ownerUserId Int
@ -724,31 +730,46 @@ enum OrganisationMemberInviteStatus {
DECLINED
}
/// @zod.import(["import { ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email';"])
model OrganisationGlobalSettings {
id String @id
organisation Organisation?
documentVisibility DocumentVisibility @default(EVERYONE)
documentLanguage String @default("en")
includeSenderDetails Boolean @default(true)
includeSigningCertificate Boolean @default(true)
documentVisibility DocumentVisibility @default(EVERYONE)
documentLanguage String @default("en")
documentTimezone String? // Nullable to allow using local timezones if not set.
documentDateFormat String @default("yyyy-MM-dd hh:mm a")
includeSenderDetails Boolean @default(true)
includeSigningCertificate Boolean @default(true)
typedSignatureEnabled Boolean @default(true)
uploadSignatureEnabled Boolean @default(true)
drawSignatureEnabled Boolean @default(true)
emailId String?
email OrganisationEmail? @relation(fields: [emailId], references: [id])
emailReplyTo String?
// emailReplyToName String? // Placeholder for future feature.
emailDocumentSettings Json /// [DocumentEmailSettings] @zod.custom.use(ZDocumentEmailSettingsSchema)
brandingEnabled Boolean @default(false)
brandingLogo String @default("")
brandingUrl String @default("")
brandingCompanyDetails String @default("")
}
/// @zod.import(["import { ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email';"])
model TeamGlobalSettings {
id String @id
team Team?
documentVisibility DocumentVisibility?
documentLanguage String?
documentVisibility DocumentVisibility?
documentLanguage String?
documentTimezone String?
documentDateFormat String?
includeSenderDetails Boolean?
includeSigningCertificate Boolean?
@ -756,6 +777,13 @@ model TeamGlobalSettings {
uploadSignatureEnabled Boolean?
drawSignatureEnabled Boolean?
emailId String?
email OrganisationEmail? @relation(fields: [emailId], references: [id])
emailReplyTo String?
// emailReplyToName String? // Placeholder for future feature.
emailDocumentSettings Json? /// [DocumentEmailSettingsNullable] @zod.custom.use(ZDocumentEmailSettingsSchema)
brandingEnabled Boolean?
brandingLogo String?
brandingUrl String?
@ -830,11 +858,14 @@ model TemplateMeta {
uploadSignatureEnabled Boolean @default(true)
drawSignatureEnabled Boolean @default(true)
templateId Int @unique
template Template @relation(fields: [templateId], references: [id], onDelete: Cascade)
redirectUrl String?
language String @default("en")
templateId Int @unique
template Template @relation(fields: [templateId], references: [id], onDelete: Cascade)
redirectUrl String?
language String @default("en")
emailSettings Json? /// [DocumentEmailSettings] @zod.custom.use(ZDocumentEmailSettingsSchema)
emailReplyTo String?
emailId String?
}
/// @zod.import(["import { ZDocumentAuthOptionsSchema } from '@documenso/lib/types/document-auth';"])
@ -962,3 +993,45 @@ model UserTwoFactorEmailVerification {
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
enum EmailDomainStatus {
PENDING
ACTIVE
}
model EmailDomain {
id String @id
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
status EmailDomainStatus @default(PENDING)
selector String @unique
domain String @unique
publicKey String
privateKey String
organisationId String
organisation Organisation @relation(fields: [organisationId], references: [id], onDelete: Cascade)
emails OrganisationEmail[]
}
model OrganisationEmail {
id String @id
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
email String @unique
emailName String
// replyTo String?
emailDomainId String
emailDomain EmailDomain @relation(fields: [emailDomainId], references: [id], onDelete: Cascade)
organisationId String
organisation Organisation @relation(fields: [organisationId], references: [id], onDelete: Cascade)
organisationGlobalSettings OrganisationGlobalSettings[]
teamGlobalSettings TeamGlobalSettings[]
}

View File

@ -207,7 +207,9 @@ export const seedTeamTemplateWithMeta = async (team: Team) => {
const ownerUser = organisation.owner;
const template = await createTemplate({
title: `[TEST] Template ${nanoid(8)} - Draft`,
data: {
title: `[TEST] Template ${nanoid(8)} - Draft`,
},
userId: ownerUser.id,
teamId: team.id,
templateDocumentDataId: documentData.id,

View File

@ -18,6 +18,7 @@ declare global {
type DocumentFormValues = TDocumentFormValues;
type DocumentAuthOptions = TDocumentAuthOptions;
type DocumentEmailSettings = TDocumentEmailSettings;
type DocumentEmailSettingsNullable = TDocumentEmailSettings | null;
type RecipientAuthOptions = TRecipientAuthOptions;