566 lines
19 KiB
Plaintext
566 lines
19 KiB
Plaintext
|
|
generator client {
|
|||
|
|
provider = "prisma-client-js"
|
|||
|
|
binaryTargets = ["native", "debian-openssl-3.0.x"]
|
|||
|
|
output = "../generated/prisma"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
datasource db {
|
|||
|
|
provider = "postgres"
|
|||
|
|
url = env("DATABASE_URL")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
model User {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
name String
|
|||
|
|
username String? @unique
|
|||
|
|
displayUsername String? @map("display_username")
|
|||
|
|
email String @unique
|
|||
|
|
emailVerified Boolean @default(false)
|
|||
|
|
image String?
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
updatedAt DateTime @updatedAt
|
|||
|
|
|
|||
|
|
password String?
|
|||
|
|
|
|||
|
|
deletedAt DateTime?
|
|||
|
|
|
|||
|
|
// 关联关系
|
|||
|
|
organizationId String? @map("organization_id")
|
|||
|
|
organization Organization? @relation(fields: [organizationId], references: [id])
|
|||
|
|
posts Post[]
|
|||
|
|
userActions UserAction[]
|
|||
|
|
roles Role[]
|
|||
|
|
resources Resource[] @relation("UserResources")
|
|||
|
|
|
|||
|
|
// 团队和组织关联
|
|||
|
|
members Member[] @relation("UserMembers")
|
|||
|
|
teamMembers TeamMember[] @relation("UserTeamMembers")
|
|||
|
|
invitations Invitation[] @relation("UserInvitations")
|
|||
|
|
|
|||
|
|
// Better Auth 关联关系
|
|||
|
|
sessions Session[]
|
|||
|
|
accounts Account[]
|
|||
|
|
|
|||
|
|
oauthAccessTokens oauthAccessToken[] @relation("UserOAuthAccessTokens")
|
|||
|
|
oauthConsents oauthConsent[] @relation("UserOAuthConsents")
|
|||
|
|
|
|||
|
|
// SSO Provider 关联关系
|
|||
|
|
ssoProviders ssoProvider[] @relation("UserSsoProviders")
|
|||
|
|
|
|||
|
|
metadata Json?
|
|||
|
|
|
|||
|
|
@@index([organizationId, deletedAt]) // 优化组织用户查询
|
|||
|
|
@@map("users")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 支持树形结构的组织模型
|
|||
|
|
model Organization {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
name String
|
|||
|
|
slug String? @unique // URL友好的标识符
|
|||
|
|
description String?
|
|||
|
|
logo String?
|
|||
|
|
// 树形结构字段
|
|||
|
|
parentId String? @map("parent_id")
|
|||
|
|
parent Organization? @relation("OrganizationHierarchy", fields: [parentId], references: [id])
|
|||
|
|
children Organization[] @relation("OrganizationHierarchy")
|
|||
|
|
|
|||
|
|
// 路径字段,用于快速查询整个路径 (例如: "1.2.3")
|
|||
|
|
path String?
|
|||
|
|
level Int @default(0) // 层级深度
|
|||
|
|
order Float @default(0) // 同级排序
|
|||
|
|
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
updatedAt DateTime @updatedAt
|
|||
|
|
deletedAt DateTime?
|
|||
|
|
|
|||
|
|
// 关联关系
|
|||
|
|
posts Post[]
|
|||
|
|
users User[]
|
|||
|
|
terms Term[]
|
|||
|
|
profiles Profile[]
|
|||
|
|
|
|||
|
|
// 团队和组织成员关联
|
|||
|
|
members Member[] @relation("OrganizationMembers")
|
|||
|
|
teams Team[] @relation("OrganizationTeams")
|
|||
|
|
invitations Invitation[] @relation("OrganizationInvitations")
|
|||
|
|
|
|||
|
|
// 活跃会话关联
|
|||
|
|
activeSessions Session[] @relation("ActiveOrganization")
|
|||
|
|
|
|||
|
|
// SSO Provider 关联关系
|
|||
|
|
ssoProviders ssoProvider[] @relation("OrganizationSsoProviders")
|
|||
|
|
|
|||
|
|
metadata Json?
|
|||
|
|
|
|||
|
|
@@index([parentId])
|
|||
|
|
@@index([path])
|
|||
|
|
@@index([level, order])
|
|||
|
|
@@index([deletedAt]) // 活跃组织查询优化
|
|||
|
|
@@map("organizations")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 支持多媒体内容和文件管理的帖子模型(多态设计)
|
|||
|
|
model Post {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
|
|||
|
|
// 基本信息
|
|||
|
|
type String
|
|||
|
|
title String
|
|||
|
|
content String? // 文本内容(可选,文件类型可能只有文件信息)
|
|||
|
|
excerpt String? // 摘要
|
|||
|
|
|
|||
|
|
// 树形结构字段(支持帖子回复、评论等层级关系,也支持文件夹结构)
|
|||
|
|
parentId String? @map("parent_id")
|
|||
|
|
parent Post? @relation("PostHierarchy", fields: [parentId], references: [id])
|
|||
|
|
children Post[] @relation("PostHierarchy")
|
|||
|
|
|
|||
|
|
// 路径字段,用于快速查询整个路径
|
|||
|
|
path String?
|
|||
|
|
level Int @default(0) // 层级深度(0为根帖子/根文件夹,1为一级回复/子文件)
|
|||
|
|
order Float @default(0) // 同级排序
|
|||
|
|
|
|||
|
|
// 状态管理
|
|||
|
|
status String // draft, published, archived, deleted
|
|||
|
|
publishedAt DateTime?
|
|||
|
|
visibility String @default("public") // public, private
|
|||
|
|
|
|||
|
|
// 统计数据
|
|||
|
|
viewCount Int @default(0) // 浏览量统计
|
|||
|
|
likeCount Int @default(0) // 点赞数统计
|
|||
|
|
startCount Int @default(0) // 收藏数统计
|
|||
|
|
commentCount Int @default(0) // 评论数统计
|
|||
|
|
|
|||
|
|
// 关联关系
|
|||
|
|
authorId String? @map("author_id")
|
|||
|
|
author User? @relation(fields: [authorId], references: [id])
|
|||
|
|
organizationId String? @map("organization_id")
|
|||
|
|
organization Organization? @relation(fields: [organizationId], references: [id])
|
|||
|
|
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
updatedAt DateTime @updatedAt
|
|||
|
|
deletedAt DateTime?
|
|||
|
|
|
|||
|
|
// 关联关系
|
|||
|
|
userActions UserAction[]
|
|||
|
|
terms Term[] // 帖子关联的标签(多对多)
|
|||
|
|
// === 元数据字段(JSONB)- 存储不经常查询的字段 ===
|
|||
|
|
metadata Json?
|
|||
|
|
|
|||
|
|
// === 优化的索引设计 ===
|
|||
|
|
@@index([type, status, deletedAt]) // 核心查询组合
|
|||
|
|
@@index([parentId, deletedAt, order]) // 目录内容查询优化
|
|||
|
|
@@index([path, deletedAt]) // 路径查询优化
|
|||
|
|
@@index([authorId, type, deletedAt, updatedAt]) // 用户文件查询优化
|
|||
|
|
@@index([organizationId, type, deletedAt, publishedAt]) // 组织文件查询优化
|
|||
|
|
@@index([metadata(ops: JsonbPathOps)], type: Gin) // GIN 索引支持 JSONB 查询
|
|||
|
|
@@map("posts")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 支持树形结构的分类体系模型
|
|||
|
|
model Taxonomy {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
name String
|
|||
|
|
slug String @unique
|
|||
|
|
description String?
|
|||
|
|
postTypes String[] @default([]) // 适用文章类型
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
updatedAt DateTime @updatedAt
|
|||
|
|
deletedAt DateTime?
|
|||
|
|
terms Term[]
|
|||
|
|
|
|||
|
|
@@index([deletedAt, slug]) // 活跃分类查询优化
|
|||
|
|
@@map("taxonomies")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 支持树形结构的术语模型
|
|||
|
|
model Term {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
name String
|
|||
|
|
slug String
|
|||
|
|
description String?
|
|||
|
|
|
|||
|
|
// 树形结构字段
|
|||
|
|
parentId String? @map("parent_id")
|
|||
|
|
parent Term? @relation("TermHierarchy", fields: [parentId], references: [id])
|
|||
|
|
children Term[] @relation("TermHierarchy")
|
|||
|
|
|
|||
|
|
// 路径字段,用于快速查询整个路径
|
|||
|
|
path String?
|
|||
|
|
level Int @default(0) // 层级深度
|
|||
|
|
order Float @default(0) // 同级排序
|
|||
|
|
|
|||
|
|
// 关联关系
|
|||
|
|
taxonomyId String @map("taxonomy_id")
|
|||
|
|
taxonomy Taxonomy @relation(fields: [taxonomyId], references: [id])
|
|||
|
|
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
updatedAt DateTime @updatedAt
|
|||
|
|
deletedAt DateTime?
|
|||
|
|
|
|||
|
|
// 关联关系
|
|||
|
|
posts Post[] // 术语关联的帖子(多对多)
|
|||
|
|
organizations Organization[] // 术语关联的组织(多对多)
|
|||
|
|
|
|||
|
|
@@unique([taxonomyId, slug]) // 同一分类体系下的slug唯一
|
|||
|
|
@@index([parentId])
|
|||
|
|
@@index([path])
|
|||
|
|
@@index([level, order])
|
|||
|
|
@@index([taxonomyId, deletedAt]) // 分类术语查询优化
|
|||
|
|
@@map("terms")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 角色模型(可运行时创建)
|
|||
|
|
model Role {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
name String @unique // 角色名称
|
|||
|
|
slug String @unique // URL友好标识符
|
|||
|
|
description String? // 角色描述
|
|||
|
|
permissions String[] // 权限代码数组,对应 SystemPermission 枚举值
|
|||
|
|
|
|||
|
|
// 角色类型
|
|||
|
|
isSystem Boolean @default(false) // 是否为系统预设角色
|
|||
|
|
isActive Boolean @default(true) // 是否启用
|
|||
|
|
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
updatedAt DateTime @updatedAt
|
|||
|
|
|
|||
|
|
// 关联关系
|
|||
|
|
users User[]
|
|||
|
|
|
|||
|
|
@@index([isSystem, isActive])
|
|||
|
|
@@map("roles")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 统一的用户行为表
|
|||
|
|
model UserAction {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
userId String? @map("user_id")
|
|||
|
|
postId String? @map("post_id")
|
|||
|
|
type String // 行为类型: 'view', 'like', 'favorite', 'download', 'share'
|
|||
|
|
description String? // 行为描述
|
|||
|
|
metadata String? // 额外数据(JSON格式)
|
|||
|
|
ipAddress String? // IP地址
|
|||
|
|
userAgent String? // 用户代理
|
|||
|
|
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|||
|
|
post Post? @relation(fields: [postId], references: [id], onDelete: Cascade)
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
updatedAt DateTime @updatedAt
|
|||
|
|
|
|||
|
|
@@unique([userId, postId, type], name: "user_post_action_unique")
|
|||
|
|
@@index([type, createdAt]) // 按行为类型和时间查询优化
|
|||
|
|
@@index([postId])
|
|||
|
|
@@index([userId, type, createdAt]) // 用户行为查询优化
|
|||
|
|
@@map("user_actions")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 系统配置模型
|
|||
|
|
model SystemConfig {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
key String @unique // 配置键
|
|||
|
|
value String // 配置值(JSON字符串)
|
|||
|
|
type String @default("string") // 配置类型: string, number, boolean, json
|
|||
|
|
description String? // 配置描述
|
|||
|
|
group String? // 配置分组
|
|||
|
|
isPublic Boolean @default(false) // 是否为公开配置
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
updatedAt DateTime @updatedAt
|
|||
|
|
|
|||
|
|
@@index([group, isPublic]) // 配置分组查询优化
|
|||
|
|
@@map("system_configs")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ===人员信息===
|
|||
|
|
model Profile {
|
|||
|
|
// 基本信息
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
name String // 姓名
|
|||
|
|
gender Int // 性别
|
|||
|
|
idNum String // 身份证号
|
|||
|
|
paperId String? // 证件号
|
|||
|
|
avatar String? // 头像
|
|||
|
|
command String? // 编制命令
|
|||
|
|
birthday DateTime? // 生日
|
|||
|
|
// 入职信息
|
|||
|
|
hireDate DateTime? // 入职时间
|
|||
|
|
relativeHireDate DateTime? // 相对入职时间
|
|||
|
|
// 身份信息
|
|||
|
|
identity String? // 身份
|
|||
|
|
level String? // 等级
|
|||
|
|
levelDate DateTime? // 等级时间
|
|||
|
|
// 职务信息
|
|||
|
|
dutyCode String // 职务代码
|
|||
|
|
dutyLevel Int // 职务级别
|
|||
|
|
dutyName String // 职务名称
|
|||
|
|
|
|||
|
|
// 关联关系
|
|||
|
|
organizationId String @map("organization_id")
|
|||
|
|
organization Organization @relation(fields: [organizationId], references: [id])
|
|||
|
|
|
|||
|
|
// 元数据 - 存储详细的、低频查询的信息
|
|||
|
|
metadata Json?
|
|||
|
|
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
updatedAt DateTime @updatedAt
|
|||
|
|
deletedAt DateTime?
|
|||
|
|
|
|||
|
|
@@index([organizationId, deletedAt]) // 组织人员查询优化
|
|||
|
|
@@index([hireDate])
|
|||
|
|
@@index([level])
|
|||
|
|
@@index([dutyCode, dutyLevel]) // 职务查询优化
|
|||
|
|
@@map("profiles")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==== 媒体库
|
|||
|
|
|
|||
|
|
model Resource {
|
|||
|
|
id String @id @default(cuid()) @map("id")
|
|||
|
|
title String? @map("title")
|
|||
|
|
description String? @map("description")
|
|||
|
|
type String? @map("type")
|
|||
|
|
fileId String? @unique
|
|||
|
|
url String?
|
|||
|
|
// 元数据
|
|||
|
|
meta Json? @map("meta")
|
|||
|
|
// 处理状态控制
|
|||
|
|
status String?
|
|||
|
|
createdAt DateTime? @default(now()) @map("created_at")
|
|||
|
|
updatedAt DateTime? @updatedAt @map("updated_at")
|
|||
|
|
createdBy String? @map("created_by")
|
|||
|
|
updatedBy String? @map("updated_by")
|
|||
|
|
deletedAt DateTime? @map("deleted_at")
|
|||
|
|
isPublic Boolean? @default(true) @map("is_public")
|
|||
|
|
|
|||
|
|
owner User? @relation("UserResources", fields: [ownerId], references: [id])
|
|||
|
|
ownerId String? @map("owner_id")
|
|||
|
|
|
|||
|
|
// 索引
|
|||
|
|
@@index([type])
|
|||
|
|
@@index([createdAt])
|
|||
|
|
@@map("resource")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 组织成员表
|
|||
|
|
model Member {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
userId String @map("user_id")
|
|||
|
|
organizationId String @map("organization_id")
|
|||
|
|
role String // 用户在组织中的角色
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
|
|||
|
|
// 关联关系
|
|||
|
|
user User @relation("UserMembers", fields: [userId], references: [id], onDelete: Cascade)
|
|||
|
|
organization Organization @relation("OrganizationMembers", fields: [organizationId], references: [id], onDelete: Cascade)
|
|||
|
|
|
|||
|
|
@@unique([userId, organizationId]) // 一个用户在一个组织中只能有一个成员记录
|
|||
|
|
@@index([organizationId, role])
|
|||
|
|
@@index([userId])
|
|||
|
|
@@map("members")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 团队表
|
|||
|
|
model Team {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
name String // 团队名称
|
|||
|
|
organizationId String @map("organization_id")
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
updatedAt DateTime @updatedAt
|
|||
|
|
|
|||
|
|
// 关联关系
|
|||
|
|
organization Organization @relation("OrganizationTeams", fields: [organizationId], references: [id], onDelete: Cascade)
|
|||
|
|
teamMembers TeamMember[] @relation("TeamMembers")
|
|||
|
|
invitations Invitation[] @relation("TeamInvitations")
|
|||
|
|
|
|||
|
|
// 活跃会话关联
|
|||
|
|
activeSessions Session[] @relation("ActiveTeam")
|
|||
|
|
|
|||
|
|
@@index([organizationId])
|
|||
|
|
@@map("teams")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 团队成员表
|
|||
|
|
model TeamMember {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
teamId String @map("team_id")
|
|||
|
|
userId String @map("user_id")
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
|
|||
|
|
// 关联关系
|
|||
|
|
team Team @relation("TeamMembers", fields: [teamId], references: [id], onDelete: Cascade)
|
|||
|
|
user User @relation("UserTeamMembers", fields: [userId], references: [id], onDelete: Cascade)
|
|||
|
|
|
|||
|
|
@@unique([teamId, userId]) // 一个用户在一个团队中只能有一个成员记录
|
|||
|
|
@@index([teamId])
|
|||
|
|
@@index([userId])
|
|||
|
|
@@map("team_members")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 邀请表
|
|||
|
|
model Invitation {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
email String // 被邀请人的邮箱地址
|
|||
|
|
inviterId String @map("inviter_id")
|
|||
|
|
organizationId String @map("organization_id")
|
|||
|
|
teamId String? @map("team_id") // 可选的团队ID
|
|||
|
|
role String // 用户在组织中的角色
|
|||
|
|
status String // 邀请状态 (pending, accepted, rejected, expired)
|
|||
|
|
expiresAt DateTime // 邀请过期时间
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
|
|||
|
|
// 关联关系
|
|||
|
|
inviter User @relation("UserInvitations", fields: [inviterId], references: [id], onDelete: Cascade)
|
|||
|
|
organization Organization @relation("OrganizationInvitations", fields: [organizationId], references: [id], onDelete: Cascade)
|
|||
|
|
team Team? @relation("TeamInvitations", fields: [teamId], references: [id], onDelete: Cascade)
|
|||
|
|
|
|||
|
|
@@index([email, status])
|
|||
|
|
@@index([organizationId, status])
|
|||
|
|
@@index([teamId, status])
|
|||
|
|
@@index([expiresAt])
|
|||
|
|
@@map("invitations")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==== Better Auth Standard Models ====
|
|||
|
|
|
|||
|
|
model Session {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
expiresAt DateTime
|
|||
|
|
token String @unique
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
updatedAt DateTime @updatedAt
|
|||
|
|
ipAddress String?
|
|||
|
|
userAgent String?
|
|||
|
|
userId String
|
|||
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|||
|
|
|
|||
|
|
// 活跃组织和团队字段
|
|||
|
|
activeOrganizationId String? @map("active_organization_id")
|
|||
|
|
activeTeamId String? @map("active_team_id")
|
|||
|
|
|
|||
|
|
// 关联关系
|
|||
|
|
activeOrganization Organization? @relation("ActiveOrganization", fields: [activeOrganizationId], references: [id])
|
|||
|
|
activeTeam Team? @relation("ActiveTeam", fields: [activeTeamId], references: [id])
|
|||
|
|
|
|||
|
|
@@map("session")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
model Account {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
accountId String
|
|||
|
|
providerId String
|
|||
|
|
userId String
|
|||
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|||
|
|
idToken String?
|
|||
|
|
accessToken String?
|
|||
|
|
refreshToken String?
|
|||
|
|
accessTokenExpiresAt DateTime?
|
|||
|
|
refreshTokenExpiresAt DateTime?
|
|||
|
|
scope String?
|
|||
|
|
password String?
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
updatedAt DateTime @updatedAt
|
|||
|
|
|
|||
|
|
@@unique([providerId, accountId])
|
|||
|
|
@@map("account")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
model Verification {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
identifier String @unique
|
|||
|
|
value String
|
|||
|
|
expiresAt DateTime
|
|||
|
|
createdAt DateTime @default(now())
|
|||
|
|
updatedAt DateTime @updatedAt
|
|||
|
|
|
|||
|
|
@@map("verification")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ==== OIDC Provider Models ====
|
|||
|
|
|
|||
|
|
// OAuth 应用程序
|
|||
|
|
model oauthApplication {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
clientId String @unique @map("client_id") // OAuth 客户端的唯一标识符
|
|||
|
|
clientSecret String? @map("client_secret") // 客户端密钥,对于使用 PKCE 的公共客户端为可选
|
|||
|
|
name String // OAuth 客户端名称
|
|||
|
|
redirectURLs String @map("redirect_urls") // 以逗号分隔的重定向 URL 列表
|
|||
|
|
metadata String? // OAuth 客户端的附加元数据
|
|||
|
|
type String // OAuth 客户端类型(例如 Web、移动)
|
|||
|
|
disabled Boolean @default(false) // 指示客户端是否被禁用
|
|||
|
|
userId String? @map("user_id") // 拥有客户端的用户 ID(可选)
|
|||
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|||
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|||
|
|
|
|||
|
|
@@index([clientId])
|
|||
|
|
@@index([userId])
|
|||
|
|
@@index([disabled])
|
|||
|
|
@@map("oauth_applications")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// OAuth 访问令牌
|
|||
|
|
model oauthAccessToken {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
accessToken String @map("access_token") // 向客户端颁发的访问令牌
|
|||
|
|
refreshToken String @map("refresh_token") // 向客户端发出的刷新令牌
|
|||
|
|
accessTokenExpiresAt DateTime @map("access_token_expires_at") // 访问令牌的到期日期
|
|||
|
|
refreshTokenExpiresAt DateTime @map("refresh_token_expires_at") // 刷新令牌的到期日期
|
|||
|
|
clientId String @map("client_id") // OAuth 客户端的 ID
|
|||
|
|
userId String @map("user_id") // 与令牌关联的用户的 ID
|
|||
|
|
scopes String // 授予范围的逗号分隔列表
|
|||
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|||
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|||
|
|
|
|||
|
|
user User @relation("UserOAuthAccessTokens", fields: [userId], references: [id], onDelete: Cascade)
|
|||
|
|
|
|||
|
|
@@index([accessToken])
|
|||
|
|
@@index([refreshToken])
|
|||
|
|
@@index([clientId])
|
|||
|
|
@@index([userId])
|
|||
|
|
@@index([accessTokenExpiresAt])
|
|||
|
|
@@index([refreshTokenExpiresAt])
|
|||
|
|
@@map("oauth_access_tokens")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// OAuth 同意
|
|||
|
|
model oauthConsent {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
userId String @map("user_id") // 同意用户的 ID
|
|||
|
|
clientId String @map("client_id") // OAuth 客户端的 ID
|
|||
|
|
scopes String // 同意的范围的逗号分隔列表
|
|||
|
|
consentGiven Boolean @map("consent_given") // 表明是否已获得同意
|
|||
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|||
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|||
|
|
// 关联关系
|
|||
|
|
user User @relation("UserOAuthConsents", fields: [userId], references: [id], onDelete: Cascade)
|
|||
|
|
|
|||
|
|
@@unique([userId, clientId]) // 一个用户对一个客户端只能有一个同意记录
|
|||
|
|
@@index([userId])
|
|||
|
|
@@index([clientId])
|
|||
|
|
@@index([consentGiven])
|
|||
|
|
@@map("oauth_consents")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// SSO 提供程序
|
|||
|
|
model ssoProvider {
|
|||
|
|
id String @id @default(cuid())
|
|||
|
|
issuer String // 发行者标识符
|
|||
|
|
domain String // 提供商的域名
|
|||
|
|
oidcConfig String? // OIDC 配置(JSON 字符串)
|
|||
|
|
samlConfig String? // SAML 配置(JSON 字符串)
|
|||
|
|
userId String? @map("user_id") // 用户 ID
|
|||
|
|
providerId String @unique @map("provider_id") // 提供商 ID,用于识别提供商并生成重定向 URL
|
|||
|
|
organizationId String? @map("organization_id") // 组织 ID,如果提供商与组织相关联
|
|||
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|||
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|||
|
|
|
|||
|
|
// 关联关系
|
|||
|
|
user User? @relation("UserSsoProviders", fields: [userId], references: [id], onDelete: Cascade)
|
|||
|
|
organization Organization? @relation("OrganizationSsoProviders", fields: [organizationId], references: [id], onDelete: Cascade)
|
|||
|
|
|
|||
|
|
@@index([providerId])
|
|||
|
|
@@index([userId])
|
|||
|
|
@@index([organizationId])
|
|||
|
|
@@index([domain])
|
|||
|
|
@@index([issuer])
|
|||
|
|
@@map("sso_providers")
|
|||
|
|
}
|