mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-13 21:01:21 +08:00
* add gitlab oauth * updated docs format * updated error message * Code formatting --------- Co-authored-by: Zai Shi <zaishi00@outlook.com>
605 lines
17 KiB
Plaintext
605 lines
17 KiB
Plaintext
// This is your Prisma schema file,
|
|
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
|
|
|
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("STACK_DATABASE_CONNECTION_STRING")
|
|
directUrl = env("STACK_DIRECT_DATABASE_CONNECTION_STRING")
|
|
}
|
|
|
|
model Project {
|
|
// Note that the project with ID `internal` is handled as a special case.
|
|
id String @id
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
displayName String
|
|
description String? @default("")
|
|
configId String @db.Uuid
|
|
config ProjectConfig @relation(fields: [configId], references: [id], onDelete: Cascade)
|
|
configOverride ProjectConfigOverride?
|
|
isProductionMode Boolean
|
|
|
|
users ProjectUser[] @relation("ProjectUsers")
|
|
teams Team[]
|
|
apiKeySets ApiKeySet[]
|
|
}
|
|
|
|
// Contains all the configuration for a project.
|
|
// More specifically, "configuration" is what we call those settings that only depend on environment variables and overrides between different deployments.
|
|
model ProjectConfig {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
allowLocalhost Boolean
|
|
signUpEnabled Boolean @default(true)
|
|
credentialEnabled Boolean
|
|
magicLinkEnabled Boolean
|
|
createTeamOnSignUp Boolean
|
|
clientTeamCreationEnabled Boolean
|
|
|
|
projects Project[]
|
|
oauthProviderConfigs OAuthProviderConfig[]
|
|
emailServiceConfig EmailServiceConfig?
|
|
domains ProjectDomain[]
|
|
permissions Permission[]
|
|
|
|
teamCreateDefaultSystemPermissions TeamSystemPermission[]
|
|
teamMemberDefaultSystemPermissions TeamSystemPermission[]
|
|
}
|
|
|
|
model ProjectDomain {
|
|
projectConfigId String @db.Uuid
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
domain String
|
|
handlerPath String
|
|
|
|
projectConfig ProjectConfig @relation(fields: [projectConfigId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([projectConfigId, domain])
|
|
}
|
|
|
|
// Environment-specific overrides for a configuration.
|
|
//
|
|
// This is a quick and dirty way to allow for environment-specific overrides of the configuration.
|
|
//
|
|
// For most cases, you should prefer to use environment variables.
|
|
//
|
|
// Note: Overrides (and environment variables) are currently unimplemented, so this model is empty.
|
|
model ProjectConfigOverride {
|
|
projectId String @id
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model Team {
|
|
projectId String
|
|
teamId String @default(uuid()) @db.Uuid
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
displayName String
|
|
profileImageUrl String?
|
|
clientMetadata Json?
|
|
clientReadOnlyMetadata Json?
|
|
serverMetadata Json?
|
|
|
|
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
permissions Permission[]
|
|
teamMembers TeamMember[]
|
|
|
|
@@id([projectId, teamId])
|
|
}
|
|
|
|
// This is used for fields that are boolean but only the true value is part of a unique constraint.
|
|
// For example if you want to allow only one selected team per user, you can make an optional field with this type and add a unique constraint.
|
|
// Only the true value is considered for the unique constraint, the null value is not.
|
|
enum BooleanTrue {
|
|
TRUE
|
|
}
|
|
|
|
model TeamMember {
|
|
projectId String
|
|
projectUserId String @db.Uuid
|
|
teamId String @db.Uuid
|
|
|
|
// This will override the displayName of the user in this team.
|
|
displayName String?
|
|
// This will override the profileImageUrl of the user in this team.
|
|
profileImageUrl String?
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
projectUser ProjectUser @relation(fields: [projectId, projectUserId], references: [projectId, projectUserId], onDelete: Cascade)
|
|
team Team @relation(fields: [projectId, teamId], references: [projectId, teamId], onDelete: Cascade)
|
|
isSelected BooleanTrue?
|
|
|
|
directPermissions TeamMemberDirectPermission[]
|
|
|
|
@@id([projectId, projectUserId, teamId])
|
|
@@unique([projectId, projectUserId, isSelected])
|
|
}
|
|
|
|
model TeamMemberDirectPermission {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
projectId String
|
|
projectUserId String @db.Uuid
|
|
teamId String @db.Uuid
|
|
permissionDbId String? @db.Uuid
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
teamMember TeamMember @relation(fields: [projectId, projectUserId, teamId], references: [projectId, projectUserId, teamId], onDelete: Cascade)
|
|
|
|
// exactly one of [permissionId && permission] or [systemPermission] must be set
|
|
permission Permission? @relation(fields: [permissionDbId], references: [dbId], onDelete: Cascade)
|
|
systemPermission TeamSystemPermission?
|
|
|
|
@@unique([projectId, projectUserId, teamId, permissionDbId])
|
|
@@unique([projectId, projectUserId, teamId, systemPermission])
|
|
}
|
|
|
|
model Permission {
|
|
// The ID of this permission, as is chosen by and exposed to the user. It is different from the database ID, which is randomly generated and only used internally.
|
|
queryableId String
|
|
// The database ID of this permission. This is never exposed to any client and is only used to make sure the database has an ID column.
|
|
dbId String @id @default(uuid()) @db.Uuid
|
|
// exactly one of [projectConfigId && projectConfig] or [projectId && teamId && team] must be set
|
|
projectConfigId String? @db.Uuid
|
|
projectId String?
|
|
teamId String? @db.Uuid
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
description String?
|
|
|
|
// The scope of the permission. If projectConfigId is set, may be GLOBAL or TEAM; if teamId is set, must be TEAM.
|
|
scope PermissionScope
|
|
projectConfig ProjectConfig? @relation(fields: [projectConfigId], references: [id], onDelete: Cascade)
|
|
team Team? @relation(fields: [projectId, teamId], references: [projectId, teamId], onDelete: Cascade)
|
|
|
|
parentEdges PermissionEdge[] @relation("ChildPermission")
|
|
childEdges PermissionEdge[] @relation("ParentPermission")
|
|
teamMemberDirectPermission TeamMemberDirectPermission[]
|
|
|
|
isDefaultTeamCreatorPermission Boolean @default(false)
|
|
isDefaultTeamMemberPermission Boolean @default(false)
|
|
|
|
@@unique([projectConfigId, queryableId])
|
|
@@unique([projectId, teamId, queryableId])
|
|
}
|
|
|
|
enum PermissionScope {
|
|
GLOBAL
|
|
TEAM
|
|
}
|
|
|
|
enum TeamSystemPermission {
|
|
UPDATE_TEAM
|
|
DELETE_TEAM
|
|
READ_MEMBERS
|
|
REMOVE_MEMBERS
|
|
INVITE_MEMBERS
|
|
}
|
|
|
|
model PermissionEdge {
|
|
edgeId String @id @default(uuid()) @db.Uuid
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
// exactly one of [parentPermissionDbId && parentPermission] or [parentTeamSystemPermission] must be set
|
|
parentPermissionDbId String? @db.Uuid
|
|
parentPermission Permission? @relation("ParentPermission", fields: [parentPermissionDbId], references: [dbId], onDelete: Cascade)
|
|
parentTeamSystemPermission TeamSystemPermission?
|
|
|
|
childPermissionDbId String @db.Uuid
|
|
childPermission Permission @relation("ChildPermission", fields: [childPermissionDbId], references: [dbId], onDelete: Cascade)
|
|
}
|
|
|
|
model ProjectUser {
|
|
projectId String
|
|
projectUserId String @default(uuid()) @db.Uuid
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
project Project @relation("ProjectUsers", fields: [projectId], references: [id], onDelete: Cascade)
|
|
projectUserRefreshTokens ProjectUserRefreshToken[]
|
|
projectUserAuthorizationCodes ProjectUserAuthorizationCode[]
|
|
projectUserOAuthAccounts ProjectUserOAuthAccount[]
|
|
teamMembers TeamMember[]
|
|
|
|
// @deprecated
|
|
projectUserEmailVerificationCode ProjectUserEmailVerificationCode[]
|
|
// @deprecated
|
|
projectUserPasswordResetCode ProjectUserPasswordResetCode[]
|
|
// @deprecated
|
|
projectUserMagicLinkCode ProjectUserMagicLinkCode[]
|
|
|
|
primaryEmail String?
|
|
primaryEmailVerified Boolean
|
|
profileImageUrl String?
|
|
displayName String?
|
|
passwordHash String?
|
|
authWithEmail Boolean
|
|
|
|
requiresTotpMfa Boolean @default(false)
|
|
totpSecret Bytes?
|
|
|
|
clientMetadata Json?
|
|
clientReadOnlyMetadata Json?
|
|
serverMetadata Json?
|
|
|
|
@@id([projectId, projectUserId])
|
|
}
|
|
|
|
model ProjectUserOAuthAccount {
|
|
projectId String
|
|
projectUserId String @db.Uuid
|
|
projectConfigId String @db.Uuid
|
|
oauthProviderConfigId String
|
|
providerAccountId String
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
providerConfig OAuthProviderConfig @relation(fields: [projectConfigId, oauthProviderConfigId], references: [projectConfigId, id], onDelete: Cascade)
|
|
projectUser ProjectUser @relation(fields: [projectId, projectUserId], references: [projectId, projectUserId], onDelete: Cascade)
|
|
oauthTokens OAuthToken[]
|
|
oauthAccessToken OAuthAccessToken[]
|
|
|
|
email String?
|
|
|
|
@@id([projectId, oauthProviderConfigId, providerAccountId])
|
|
}
|
|
|
|
model OAuthToken {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
|
|
projectId String
|
|
oAuthProviderConfigId String
|
|
providerAccountId String
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
projectUserOAuthAccount ProjectUserOAuthAccount @relation(fields: [projectId, oAuthProviderConfigId, providerAccountId], references: [projectId, oauthProviderConfigId, providerAccountId], onDelete: Cascade)
|
|
|
|
refreshToken String
|
|
scopes String[]
|
|
}
|
|
|
|
model OAuthAccessToken {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
|
|
projectId String
|
|
oAuthProviderConfigId String
|
|
providerAccountId String
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
projectUserOAuthAccount ProjectUserOAuthAccount @relation(fields: [projectId, oAuthProviderConfigId, providerAccountId], references: [projectId, oauthProviderConfigId, providerAccountId], onDelete: Cascade)
|
|
|
|
accessToken String
|
|
scopes String[]
|
|
expiresAt DateTime
|
|
}
|
|
|
|
model OAuthOuterInfo {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
|
|
info Json
|
|
innerState String @unique
|
|
expiresAt DateTime
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model ProjectUserRefreshToken {
|
|
projectId String
|
|
projectUserId String @db.Uuid
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
refreshToken String @unique
|
|
expiresAt DateTime?
|
|
|
|
projectUser ProjectUser @relation(fields: [projectId, projectUserId], references: [projectId, projectUserId], onDelete: Cascade)
|
|
|
|
@@id([projectId, refreshToken])
|
|
}
|
|
|
|
model ProjectUserAuthorizationCode {
|
|
projectId String
|
|
projectUserId String @db.Uuid
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
authorizationCode String @unique
|
|
redirectUri String
|
|
expiresAt DateTime
|
|
|
|
codeChallenge String
|
|
codeChallengeMethod String
|
|
|
|
newUser Boolean
|
|
afterCallbackRedirectUrl String?
|
|
|
|
projectUser ProjectUser @relation(fields: [projectId, projectUserId], references: [projectId, projectUserId], onDelete: Cascade)
|
|
|
|
@@id([projectId, authorizationCode])
|
|
}
|
|
|
|
model VerificationCode {
|
|
projectId String
|
|
id String @default(uuid()) @db.Uuid
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
type VerificationCodeType
|
|
code String
|
|
expiresAt DateTime
|
|
usedAt DateTime?
|
|
redirectUrl String?
|
|
|
|
method Json @default("null")
|
|
|
|
data Json
|
|
|
|
@@id([projectId, id])
|
|
@@unique([projectId, code])
|
|
}
|
|
|
|
enum VerificationCodeType {
|
|
ONE_TIME_PASSWORD
|
|
PASSWORD_RESET
|
|
CONTACT_CHANNEL_VERIFICATION
|
|
TEAM_INVITATION
|
|
MFA_ATTEMPT
|
|
}
|
|
|
|
// @deprecated
|
|
model ProjectUserEmailVerificationCode {
|
|
projectId String
|
|
projectUserId String @db.Uuid
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
code String @unique
|
|
expiresAt DateTime
|
|
usedAt DateTime?
|
|
redirectUrl String
|
|
|
|
projectUser ProjectUser @relation(fields: [projectId, projectUserId], references: [projectId, projectUserId], onDelete: Cascade)
|
|
|
|
@@id([projectId, code])
|
|
}
|
|
|
|
// @deprecated
|
|
model ProjectUserPasswordResetCode {
|
|
projectId String
|
|
projectUserId String @db.Uuid
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
code String @unique
|
|
expiresAt DateTime
|
|
usedAt DateTime?
|
|
redirectUrl String
|
|
|
|
projectUser ProjectUser @relation(fields: [projectId, projectUserId], references: [projectId, projectUserId], onDelete: Cascade)
|
|
|
|
@@id([projectId, code])
|
|
}
|
|
|
|
// @deprecated
|
|
model ProjectUserMagicLinkCode {
|
|
projectId String
|
|
projectUserId String @db.Uuid
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
code String @unique
|
|
expiresAt DateTime
|
|
usedAt DateTime?
|
|
redirectUrl String
|
|
newUser Boolean
|
|
|
|
projectUser ProjectUser @relation(fields: [projectId, projectUserId], references: [projectId, projectUserId], onDelete: Cascade)
|
|
|
|
@@id([projectId, code])
|
|
}
|
|
|
|
//#region API keys
|
|
|
|
model ApiKeySet {
|
|
projectId String
|
|
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
id String @default(uuid()) @db.Uuid
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
description String
|
|
expiresAt DateTime
|
|
manuallyRevokedAt DateTime?
|
|
publishableClientKey String? @unique
|
|
secretServerKey String? @unique
|
|
superSecretAdminKey String? @unique
|
|
|
|
@@id([projectId, id])
|
|
}
|
|
|
|
model EmailServiceConfig {
|
|
projectConfigId String @id @db.Uuid
|
|
projectConfig ProjectConfig @relation(fields: [projectConfigId], references: [id], onDelete: Cascade)
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
proxiedEmailServiceConfig ProxiedEmailServiceConfig?
|
|
standardEmailServiceConfig StandardEmailServiceConfig?
|
|
|
|
emailTemplates EmailTemplate[]
|
|
}
|
|
|
|
enum EmailTemplateType {
|
|
EMAIL_VERIFICATION
|
|
PASSWORD_RESET
|
|
MAGIC_LINK
|
|
TEAM_INVITATION
|
|
}
|
|
|
|
model EmailTemplate {
|
|
projectConfigId String @db.Uuid
|
|
emailServiceConfig EmailServiceConfig @relation(fields: [projectConfigId], references: [projectConfigId], onDelete: Cascade)
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
content Json
|
|
type EmailTemplateType
|
|
subject String
|
|
|
|
@@id([projectConfigId, type])
|
|
}
|
|
|
|
model ProxiedEmailServiceConfig {
|
|
projectConfigId String @id @db.Uuid
|
|
emailServiceConfig EmailServiceConfig @relation(fields: [projectConfigId], references: [projectConfigId], onDelete: Cascade)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model StandardEmailServiceConfig {
|
|
projectConfigId String @id @db.Uuid
|
|
emailServiceConfig EmailServiceConfig @relation(fields: [projectConfigId], references: [projectConfigId], onDelete: Cascade)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
senderName String
|
|
senderEmail String
|
|
host String
|
|
port Int
|
|
username String
|
|
password String
|
|
}
|
|
|
|
//#endregion
|
|
|
|
//#region OAuth
|
|
|
|
// Exactly one of the xyzOAuthConfig variables should be set.
|
|
model OAuthProviderConfig {
|
|
projectConfigId String @db.Uuid
|
|
projectConfig ProjectConfig @relation(fields: [projectConfigId], references: [id], onDelete: Cascade)
|
|
id String
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
enabled Boolean @default(true)
|
|
|
|
proxiedOAuthConfig ProxiedOAuthProviderConfig?
|
|
standardOAuthConfig StandardOAuthProviderConfig?
|
|
projectUserOAuthAccounts ProjectUserOAuthAccount[]
|
|
|
|
@@id([projectConfigId, id])
|
|
}
|
|
|
|
model ProxiedOAuthProviderConfig {
|
|
projectConfigId String @db.Uuid
|
|
providerConfig OAuthProviderConfig @relation(fields: [projectConfigId, id], references: [projectConfigId, id], onDelete: Cascade)
|
|
id String
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
type ProxiedOAuthProviderType
|
|
|
|
@@id([projectConfigId, id])
|
|
@@unique([projectConfigId, type])
|
|
}
|
|
|
|
enum ProxiedOAuthProviderType {
|
|
GITHUB
|
|
FACEBOOK
|
|
GOOGLE
|
|
MICROSOFT
|
|
SPOTIFY
|
|
}
|
|
|
|
model StandardOAuthProviderConfig {
|
|
projectConfigId String @db.Uuid
|
|
providerConfig OAuthProviderConfig @relation(fields: [projectConfigId, id], references: [projectConfigId, id], onDelete: Cascade)
|
|
id String
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
type StandardOAuthProviderType
|
|
clientId String
|
|
clientSecret String
|
|
|
|
// optional extra parameters for specific oauth providers
|
|
// Facebook business integration requires a config_id
|
|
facebookConfigId String?
|
|
|
|
@@id([projectConfigId, id])
|
|
}
|
|
|
|
enum StandardOAuthProviderType {
|
|
GITHUB
|
|
FACEBOOK
|
|
GOOGLE
|
|
MICROSOFT
|
|
SPOTIFY
|
|
DISCORD
|
|
GITLAB
|
|
}
|
|
|
|
//#endregion
|
|
|
|
//#region Events
|
|
|
|
model Event {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
// if isWide == false, then eventEndedAt is always equal to eventStartedAt
|
|
isWide Boolean
|
|
eventStartedAt DateTime
|
|
eventEndedAt DateTime
|
|
|
|
// TODO: add event_type, and at least one of either system_event_type or event_type is always set
|
|
systemEventTypeIds String[]
|
|
data Json
|
|
}
|
|
|
|
//#endregion
|