feat: add organisations (#1820)

This commit is contained in:
David Nguyen
2025-06-10 11:49:52 +10:00
committed by GitHub
parent 0b37f19641
commit e6dc237ad2
631 changed files with 37616 additions and 25695 deletions

View File

@ -39,7 +39,6 @@ enum Role {
model User {
id Int @id @default(autoincrement())
name String?
customerId String? @unique
email String @unique
emailVerified DateTime?
password String? // Todo: (RR7) Remove after RR7 migration.
@ -53,24 +52,23 @@ model User {
avatarImageId String?
disabled Boolean @default(false)
accounts Account[]
sessions Session[]
documents Document[]
folders Folder[]
subscriptions Subscription[]
passwordResetTokens PasswordResetToken[]
ownedTeams Team[]
ownedPendingTeams TeamPending[]
teamMembers TeamMember[]
twoFactorSecret String?
twoFactorEnabled Boolean @default(false)
twoFactorBackupCodes String?
url String? @unique
accounts Account[]
sessions Session[]
passwordResetTokens PasswordResetToken[]
ownedOrganisations Organisation[]
organisationMember OrganisationMember[]
twoFactorSecret String?
twoFactorEnabled Boolean @default(false)
twoFactorBackupCodes String?
folders Folder[]
documents Document[]
templates Template[]
profile UserProfile?
verificationTokens VerificationToken[]
apiTokens ApiToken[]
templates Template[]
securityAuditLogs UserSecurityAuditLog[]
webhooks Webhook[]
siteSettings SiteSettings[]
@ -80,15 +78,6 @@ model User {
@@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)
@ -191,8 +180,8 @@ model Webhook {
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)
teamId Int
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
webhookCalls WebhookCall[]
}
@ -228,8 +217,8 @@ model ApiToken {
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)
teamId Int
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
}
enum SubscriptionStatus {
@ -244,16 +233,46 @@ model Subscription {
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)
customerId String
@@index([userId])
organisationId String @unique
organisation Organisation @relation(fields: [organisationId], references: [id], onDelete: Cascade)
@@index([organisationId])
}
/// @zod.import(["import { ZClaimFlagsSchema } from '@documenso/lib/types/subscription';"])
model SubscriptionClaim {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
name String
locked Boolean @default(false)
teamCount Int
memberCount Int
flags Json /// [ClaimFlags] @zod.custom.use(ZClaimFlagsSchema)
}
/// @zod.import(["import { ZClaimFlagsSchema } from '@documenso/lib/types/subscription';"])
model OrganisationClaim {
id String @id
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
originalSubscriptionClaimId String?
organisation Organisation?
teamCount Int
memberCount Int
flags Json /// [ClaimFlags] @zod.custom.use(ZClaimFlagsSchema)
}
model Account {
@ -323,8 +342,8 @@ model Folder {
name String
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
teamId Int?
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
teamId Int
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
pinned Boolean @default(false)
parentId String?
parent Folder? @relation("FolderToFolder", fields: [parentId], references: [id], onDelete: Cascade)
@ -344,11 +363,16 @@ model Folder {
/// @zod.import(["import { ZDocumentAuthOptionsSchema } from '@documenso/lib/types/document-auth';", "import { ZDocumentFormValuesSchema } from '@documenso/lib/types/document-form-values';"])
model Document {
id Int @id @default(autoincrement())
qrToken String? /// @zod.string.describe("The token for viewing the document using the QR code on the certificate.")
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.")
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
id Int @id @default(autoincrement())
qrToken String? /// @zod.string.describe("The token for viewing the document using the QR code on the certificate.")
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.")
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
teamId Int
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
authOptions Json? /// [DocumentAuthOptions] @zod.custom.use(ZDocumentAuthOptionsSchema)
formValues Json? /// [DocumentFormValues] @zod.custom.use(ZDocumentFormValuesSchema)
visibility DocumentVisibility @default(EVERYONE)
@ -363,14 +387,12 @@ model Document {
updatedAt DateTime @default(now()) @updatedAt
completedAt DateTime?
deletedAt DateTime?
teamId Int?
templateId Int?
source DocumentSource
useLegacyFieldInsertion Boolean @default(false)
documentData DocumentData @relation(fields: [documentDataId], references: [id], onDelete: Cascade)
team Team? @relation(fields: [teamId], references: [id])
template Template? @relation(fields: [templateId], references: [id], onDelete: SetNull)
auditLogs DocumentAuditLog[]
@ -569,20 +591,141 @@ model DocumentShareLink {
@@unique([documentId, email])
}
enum OrganisationType {
PERSONAL
ORGANISATION
}
model Organisation {
id String @id
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
type OrganisationType
name String
url String @unique
avatarImageId String?
customerId String? @unique
subscription Subscription?
organisationClaimId String @unique
organisationClaim OrganisationClaim @relation(fields: [organisationClaimId], references: [id])
members OrganisationMember[]
invites OrganisationMemberInvite[]
groups OrganisationGroup[]
teams Team[]
avatarImage AvatarImage? @relation(fields: [avatarImageId], references: [id], onDelete: SetNull)
ownerUserId Int
owner User @relation(fields: [ownerUserId], references: [id], onDelete: Cascade)
organisationGlobalSettingsId String @unique
organisationGlobalSettings OrganisationGlobalSettings @relation(fields: [organisationGlobalSettingsId], references: [id])
}
model OrganisationMember {
id String @id
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
organisationId String
organisation Organisation @relation(fields: [organisationId], references: [id], onDelete: Cascade)
organisationGroupMembers OrganisationGroupMember[]
@@unique([userId, organisationId])
}
model OrganisationMemberInvite {
id String @id
createdAt DateTime @default(now())
email String
token String @unique
status OrganisationMemberInviteStatus @default(PENDING)
organisationId String
organisation Organisation @relation(fields: [organisationId], references: [id], onDelete: Cascade)
organisationRole OrganisationMemberRole
}
model OrganisationGroup {
id String @id
name String?
type OrganisationGroupType
organisationRole OrganisationMemberRole
organisationId String
organisation Organisation @relation(fields: [organisationId], references: [id], onDelete: Cascade)
organisationGroupMembers OrganisationGroupMember[]
teamGroups TeamGroup[]
}
model OrganisationGroupMember {
id String @id
groupId String
group OrganisationGroup @relation(fields: [groupId], references: [id], onDelete: Cascade)
organisationMember OrganisationMember @relation(fields: [organisationMemberId], references: [id], onDelete: Cascade)
organisationMemberId String
@@unique([organisationMemberId, groupId])
}
model TeamGroup {
id String @id
organisationGroupId String
organisationGroup OrganisationGroup @relation(fields: [organisationGroupId], references: [id], onDelete: Cascade)
teamRole TeamMemberRole
teamId Int
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
@@unique([teamId, organisationGroupId])
}
enum OrganisationGroupType {
INTERNAL_ORGANISATION
INTERNAL_TEAM
CUSTOM
}
enum OrganisationMemberRole {
ADMIN
MANAGER
MEMBER
}
enum TeamMemberRole {
ADMIN
MANAGER
MEMBER
}
enum TeamMemberInviteStatus {
enum OrganisationMemberInviteStatus {
ACCEPTED
PENDING
DECLINED
}
model TeamGlobalSettings {
teamId Int @unique
model OrganisationGlobalSettings {
id String @id
organisation Organisation?
documentVisibility DocumentVisibility @default(EVERYONE)
documentLanguage String @default("en")
includeSenderDetails Boolean @default(true)
@ -596,11 +739,25 @@ model TeamGlobalSettings {
brandingLogo String @default("")
brandingUrl String @default("")
brandingCompanyDetails String @default("")
brandingHidePoweredBy Boolean @default(false)
}
allowEmbeddedAuthoring Boolean @default(false)
model TeamGlobalSettings {
id String @id
team Team?
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
documentVisibility DocumentVisibility?
documentLanguage String?
includeSenderDetails Boolean?
includeSigningCertificate Boolean?
typedSignatureEnabled Boolean?
uploadSignatureEnabled Boolean?
drawSignatureEnabled Boolean?
brandingEnabled Boolean?
brandingLogo String?
brandingUrl String?
brandingCompanyDetails String?
}
model Team {
@ -609,49 +766,25 @@ model Team {
url String @unique
createdAt DateTime @default(now())
avatarImageId String?
customerId String? @unique
ownerUserId Int
members TeamMember[]
invites TeamMemberInvite[]
teamEmail TeamEmail?
emailVerification TeamEmailVerification?
transferVerification TeamTransferVerification?
teamGlobalSettings TeamGlobalSettings?
avatarImage AvatarImage? @relation(fields: [avatarImageId], references: [id], onDelete: SetNull)
teamEmail TeamEmail?
emailVerification TeamEmailVerification?
avatarImage AvatarImage? @relation(fields: [avatarImageId], references: [id], onDelete: SetNull)
profile TeamProfile?
owner User @relation(fields: [ownerUserId], references: [id], onDelete: Cascade)
subscription Subscription?
profile TeamProfile?
documents Document[]
templates Template[]
folders Folder[]
apiTokens ApiToken[]
webhooks Webhook[]
}
documents Document[]
templates Template[]
folders Folder[]
apiTokens ApiToken[]
webhooks Webhook[]
teamGroups TeamGroup[]
model TeamPending {
id Int @id @default(autoincrement())
name String
url String @unique
createdAt DateTime @default(now())
customerId String @unique
ownerUserId Int
organisationId String
organisation Organisation @relation(fields: [organisationId], references: [id], onDelete: Cascade)
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])
teamGlobalSettingsId String @unique
teamGlobalSettings TeamGlobalSettings @relation(fields: [teamGlobalSettingsId], references: [id], onDelete: Cascade)
}
model TeamEmail {
@ -674,33 +807,6 @@ model TeamEmailVerification {
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
@ -735,8 +841,6 @@ model Template {
externalId String?
type TemplateType @default(PRIVATE)
title String
userId Int
teamId Int?
visibility DocumentVisibility @default(EVERYONE)
authOptions Json? /// [DocumentAuthOptions] @zod.custom.use(ZDocumentAuthOptionsSchema)
templateMeta TemplateMeta?
@ -748,17 +852,24 @@ model Template {
useLegacyFieldInsertion Boolean @default(false)
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)
recipients Recipient[]
fields Field[]
directLink TemplateDirectLink?
documents Document[]
folder Folder? @relation(fields: [folderId], references: [id], onDelete: Cascade)
folderId String?
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
teamId Int
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
templateDocumentData DocumentData @relation(fields: [templateDocumentDataId], references: [id], onDelete: Cascade)
recipients Recipient[]
fields Field[]
directLink TemplateDirectLink?
documents Document[]
folder Folder? @relation(fields: [folderId], references: [id], onDelete: Cascade)
folderId String?
@@unique([templateDocumentDataId])
@@index([userId])
}
model TemplateDirectLink {
@ -836,6 +947,7 @@ model AvatarImage {
id String @id @default(cuid())
bytes String
team Team[]
user User[]
team Team[]
user User[]
organisation Organisation[]
}