generator client { provider = "prisma-client-js" binaryTargets = ["native", "debian-openssl-1.1.x"] output = "../generated/prisma" } datasource db { provider = "postgres" url = env("DATABASE_URL") } model User { id String @id @default(cuid()) name String password String? salt String? phone String? @unique email String @unique avatar String? isSystem Boolean? @map("is_system") isAdmin Boolean? @map("is_admin") lastSignTime DateTime? @map("last_sign_time") deactivatedTime DateTime? @map("deactivated_time") createdTime DateTime @default(now()) @map("created_time") deletedTime DateTime? @map("deleted_time") lastModifiedTime DateTime? @updatedAt @map("last_modified_time") @@map("users") } model Attachments { id String @id @default(cuid()) token String @unique hash String size Int mimetype String path String width Int? height Int? deletedTime DateTime? @map("deleted_time") createdTime DateTime @default(now()) @map("created_time") createdBy String @map("created_by") lastModifiedBy String? @map("last_modified_by") thumbnailPath String? @map("thumbnail_path") @@map("attachments") } model Notification { id String @id @default(cuid()) fromUserId String @map("from_user_id") toUserId String @map("to_user_id") type String @map("type") message String @map("message") urlPath String? @map("url_path") isRead Boolean @default(false) @map("is_read") createdTime DateTime @default(now()) @map("created_time") createdBy String @map("created_by") @@index([toUserId, isRead, createdTime]) @@map("notification") } model Setting { instanceId String @id @default(cuid()) @map("instance_id") disallowSignUp Boolean? @map("disallow_sign_up") disallowSpaceCreation Boolean? @map("disallow_space_creation") disallowSpaceInvitation Boolean? @map("disallow_space_invitation") enableEmailVerification Boolean? @map("enable_email_verification") aiConfig String? @map("ai_config") brandName String? @map("brand_name") brandLogo String? @map("brand_logo") @@map("setting") } model Trash { id String @id @default(cuid()) resourceType String @map("resource_type") resourceId String @map("resource_id") parentId String? @map("parent_id") deletedTime DateTime @default(now()) @map("deleted_time") deletedBy String @map("deleted_by") @@unique([resourceType, resourceId]) @@map("trash") } model UserLastVisit { id String @id @default(cuid()) userId String @map("user_id") resourceType String @map("resource_type") resourceId String @map("resource_id") parentResourceId String @map("parent_resource_id") lastVisitTime DateTime @default(now()) @map("last_visit_time") @@unique([userId, resourceType, parentResourceId]) @@index([userId, resourceType]) @@map("user_last_visit") } // OIDC 客户端相关模型 model OidcClient { id String @id @default(cuid()) clientId String @unique @map("client_id") clientSecret String? @map("client_secret") clientName String @map("client_name") clientUri String? @map("client_uri") logoUri String? @map("logo_uri") contacts String[] redirectUris String[] @map("redirect_uris") postLogoutRedirectUris String[] @map("post_logout_redirect_uris") tokenEndpointAuthMethod String @map("token_endpoint_auth_method") grantTypes String[] @map("grant_types") responseTypes String[] @map("response_types") scope String jwksUri String? @map("jwks_uri") jwks String? policyUri String? @map("policy_uri") tosUri String? @map("tos_uri") requirePkce Boolean @default(false) @map("require_pkce") active Boolean @default(true) createdBy String? @map("created_by") createdTime DateTime @default(now()) @map("created_time") lastModifiedTime DateTime? @updatedAt @map("last_modified_time") // 关联模型 consents OidcConsent[] authorizationCodes OidcCode[] tokens OidcToken[] @@map("oidc_clients") } // 用户同意记录 model OidcConsent { id String @id @default(cuid()) userId String @map("user_id") clientId String @map("client_id") scope String createdTime DateTime @default(now()) @map("created_time") expiresAt DateTime? @map("expires_at") // 关联 client OidcClient @relation(fields: [clientId], references: [id], onDelete: Cascade) @@unique([userId, clientId]) @@map("oidc_consents") } // 授权码 model OidcCode { id String @id @default(cuid()) code String @unique userId String @map("user_id") clientId String @map("client_id") scope String redirectUri String @map("redirect_uri") codeChallenge String? @map("code_challenge") codeChallengeMethod String? @map("code_challenge_method") nonce String? authTime DateTime @default(now()) @map("auth_time") expiresAt DateTime @map("expires_at") used Boolean @default(false) // 关联 client OidcClient @relation(fields: [clientId], references: [id], onDelete: Cascade) @@map("oidc_authorization_codes") } // 统一令牌表(合并access和refresh token) model OidcToken { id String @id @default(cuid()) token String @unique userId String @map("user_id") clientId String @map("client_id") tokenType String @map("token_type") // "access" 或 "refresh" scope String expiresAt DateTime @map("expires_at") createdTime DateTime @default(now()) @map("created_time") isRevoked Boolean @default(false) @map("is_revoked") parentId String? @map("parent_id") // 用于关联refresh token和对应的access token // 关联 client OidcClient @relation(fields: [clientId], references: [id], onDelete: Cascade) @@index([userId, tokenType, isRevoked]) @@map("oidc_tokens") } // Session管理 model OidcSession { id String @id @default(cuid()) sessionId String @unique @map("session_id") userId String @map("user_id") expiresAt DateTime @map("expires_at") lastActive DateTime @default(now()) @map("last_active") deviceInfo String? @map("device_info") createdTime DateTime @default(now()) @map("created_time") lastModifiedTime DateTime? @updatedAt @map("last_modified_time") @@map("oidc_sessions") } // 供应商的密钥对 model OidcKeyPair { id String @id @default(cuid()) kid String @unique privateKey String @map("private_key") publicKey String @map("public_key") algorithm String active Boolean @default(true) createdTime DateTime @default(now()) @map("created_time") expiresAt DateTime? @map("expires_at") @@map("oidc_key_pairs") }