ec-nest/prisma/schema.prisma
liuyun 513688a5e6 fix(security): P0 安全越权堵漏(C1/H1-H6/H10/H11/H13/M1/M4/M6/M8-M11/M22)
- 平台管理员模型:super_admin=平台超管、tenant_super_admin=租户顶层(保留码),tenant:* 仅平台可授予
- 软删改名回收唯一键 + P2002→409
- 删除角色级联清理关联 + 聚合过滤已删/停用角色资源
- tokenVersion 会话吊销(重置密码/停用/删除即时踢下线)
- data_scope self 按 userId 过滤 + 详情数据权限校验
- 组织树防环、seed 不重置密码、日志脱敏补 phone/email
- JWT 密钥强校验、pageSize 上限、DTO 枚举校验、Prisma 错误映射、授权事务化

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-11 16:10:00 +08:00

263 lines
9.2 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 通用系统管理脚手架 (sysmgr) 数据模型
// 约定:表名 sys_ 前缀;列 snake_case(模型 camelCase + @map);业务键关联(角色/资源/组织/字典/租户用 code,用户用 id)。
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
/// 租户
model Tenant {
id String @id @default(uuid(7)) @db.VarChar(36)
code String @unique @db.VarChar(64)
name String @db.VarChar(128)
status String @default("enabled") @db.VarChar(16)
remark String? @db.VarChar(255)
createdAt DateTime @default(now()) @map("created_at")
createdBy String? @map("created_by") @db.VarChar(36)
updatedAt DateTime @updatedAt @map("updated_at")
@@map("sys_tenant")
}
/// 用户
model User {
id String @id @default(uuid(7)) @db.VarChar(36)
tenantCode String @map("tenant_code") @db.VarChar(64)
username String @db.VarChar(64)
passwordHash String @map("password_hash") @db.VarChar(255)
nickname String? @db.VarChar(64)
email String? @db.VarChar(128)
phone String? @db.VarChar(32)
avatar String? @db.VarChar(255)
status String @default("enabled") @db.VarChar(16)
tokenVersion Int @default(0) @map("token_version")
orgCode String? @map("org_code") @db.VarChar(64)
createdAt DateTime @default(now()) @map("created_at")
createdBy String? @map("created_by") @db.VarChar(36)
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
@@unique([tenantCode, username])
@@index([tenantCode])
@@index([orgCode])
@@map("sys_user")
}
/// 角色
model Role {
id String @id @default(uuid(7)) @db.VarChar(36)
tenantCode String @map("tenant_code") @db.VarChar(64)
code String @db.VarChar(64)
name String @db.VarChar(64)
dataScope String @default("all") @map("data_scope") @db.VarChar(16)
status String @default("enabled") @db.VarChar(16)
remark String? @db.VarChar(255)
createdAt DateTime @default(now()) @map("created_at")
createdBy String? @map("created_by") @db.VarChar(36)
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
@@unique([tenantCode, code])
@@index([tenantCode])
@@map("sys_role")
}
/// 资源(菜单/按钮/接口)
model Resource {
id String @id @default(uuid(7)) @db.VarChar(36)
tenantCode String @map("tenant_code") @db.VarChar(64)
parentCode String? @map("parent_code") @db.VarChar(64)
type String @db.VarChar(16)
code String @db.VarChar(128)
name String @db.VarChar(64)
path String? @db.VarChar(255)
component String? @db.VarChar(255)
method String? @db.VarChar(8)
apiPath String? @map("api_path") @db.VarChar(255)
icon String? @db.VarChar(64)
sort Int @default(0)
status String @default("enabled") @db.VarChar(16)
createdAt DateTime @default(now()) @map("created_at")
createdBy String? @map("created_by") @db.VarChar(36)
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
@@unique([tenantCode, code])
@@index([tenantCode])
@@index([parentCode])
@@map("sys_resource")
}
/// 组织
model Org {
id String @id @default(uuid(7)) @db.VarChar(36)
tenantCode String @map("tenant_code") @db.VarChar(64)
parentCode String? @map("parent_code") @db.VarChar(64)
code String @db.VarChar(64)
name String @db.VarChar(64)
leader String? @db.VarChar(64)
sort Int @default(0)
status String @default("enabled") @db.VarChar(16)
createdAt DateTime @default(now()) @map("created_at")
createdBy String? @map("created_by") @db.VarChar(36)
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
@@unique([tenantCode, code])
@@index([tenantCode])
@@index([parentCode])
@@map("sys_org")
}
/// 字典类型
model DictType {
id String @id @default(uuid(7)) @db.VarChar(36)
tenantCode String @map("tenant_code") @db.VarChar(64)
code String @db.VarChar(64)
name String @db.VarChar(64)
status String @default("enabled") @db.VarChar(16)
builtIn Boolean @default(false) @map("built_in")
remark String? @db.VarChar(255)
createdAt DateTime @default(now()) @map("created_at")
createdBy String? @map("created_by") @db.VarChar(36)
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
@@unique([tenantCode, code])
@@index([tenantCode])
@@map("sys_dict_type")
}
/// 字典项
model DictItem {
id String @id @default(uuid(7)) @db.VarChar(36)
tenantCode String @map("tenant_code") @db.VarChar(64)
dictTypeCode String @map("dict_type_code") @db.VarChar(64)
label String @db.VarChar(64)
value String @db.VarChar(64)
sort Int @default(0)
status String @default("enabled") @db.VarChar(16)
builtIn Boolean @default(false) @map("built_in")
colorType String? @map("color_type") @db.VarChar(16)
createdAt DateTime @default(now()) @map("created_at")
createdBy String? @map("created_by") @db.VarChar(36)
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
@@unique([tenantCode, dictTypeCode, value])
@@index([tenantCode, dictTypeCode])
@@map("sys_dict_item")
}
/// 参数配置
model Config {
id String @id @default(uuid(7)) @db.VarChar(36)
tenantCode String @map("tenant_code") @db.VarChar(64)
key String @db.VarChar(128)
value String? @db.Text
remark String? @db.VarChar(255)
createdAt DateTime @default(now()) @map("created_at")
createdBy String? @map("created_by") @db.VarChar(36)
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
@@unique([tenantCode, key])
@@map("sys_config")
}
/// 操作日志(只增,硬删)
model AuditLog {
id String @id @default(uuid(7)) @db.VarChar(36)
tenantCode String @map("tenant_code") @db.VarChar(64)
userId String? @map("user_id") @db.VarChar(36)
username String? @db.VarChar(64)
module String? @db.VarChar(64)
action String? @db.VarChar(64)
method String? @db.VarChar(8)
path String? @db.VarChar(255)
params String? @db.Text
result String? @db.Text
status String? @db.VarChar(16)
errorMessage String? @map("error_message") @db.Text
ip String? @db.VarChar(64)
userAgent String? @map("user_agent") @db.VarChar(255)
durationMs Int? @map("duration_ms")
createdAt DateTime @default(now()) @map("created_at")
@@index([tenantCode, createdAt])
@@map("sys_audit_log")
}
/// 登录日志(只增,硬删)
model LoginLog {
id String @id @default(uuid(7)) @db.VarChar(36)
tenantCode String @map("tenant_code") @db.VarChar(64)
username String? @db.VarChar(64)
ip String? @db.VarChar(64)
userAgent String? @map("user_agent") @db.VarChar(255)
status String @default("success") @db.VarChar(16)
message String? @db.VarChar(255)
createdAt DateTime @default(now()) @map("created_at")
@@index([tenantCode, createdAt])
@@map("sys_login_log")
}
/// 刷新令牌(会话载体,硬删)
model RefreshToken {
id String @id @default(uuid(7)) @db.VarChar(36)
tenantCode String @map("tenant_code") @db.VarChar(64)
userId String @map("user_id") @db.VarChar(36)
jti String @unique @db.VarChar(64)
tokenHash String @map("token_hash") @db.VarChar(255)
ip String? @db.VarChar(64)
userAgent String? @map("user_agent") @db.VarChar(255)
loginAt DateTime @default(now()) @map("login_at")
expireAt DateTime @map("expire_at")
revokedAt DateTime? @map("revoked_at")
createdAt DateTime @default(now()) @map("created_at")
@@index([tenantCode, userId])
@@map("sys_refresh_token")
}
/// 用户-角色关联
model UserRole {
id String @id @default(uuid(7)) @db.VarChar(36)
tenantCode String @map("tenant_code") @db.VarChar(64)
userId String @map("user_id") @db.VarChar(36)
roleCode String @map("role_code") @db.VarChar(64)
@@unique([tenantCode, userId, roleCode])
@@index([tenantCode, userId])
@@map("sys_user_role")
}
/// 角色-资源关联
model RoleResource {
id String @id @default(uuid(7)) @db.VarChar(36)
tenantCode String @map("tenant_code") @db.VarChar(64)
roleCode String @map("role_code") @db.VarChar(64)
resourceCode String @map("resource_code") @db.VarChar(128)
@@unique([tenantCode, roleCode, resourceCode])
@@index([tenantCode, roleCode])
@@map("sys_role_resource")
}
/// 角色-组织关联(数据权限「自定义」)
model RoleOrg {
id String @id @default(uuid(7)) @db.VarChar(36)
tenantCode String @map("tenant_code") @db.VarChar(64)
roleCode String @map("role_code") @db.VarChar(64)
orgCode String @map("org_code") @db.VarChar(64)
@@unique([tenantCode, roleCode, orgCode])
@@map("sys_role_org")
}