--- description: 多租户数据隔离规范(所有涉及数据库操作的代码必须遵守) globs: alwaysApply: true --- # 多租户处理规范 ⚠️ **极其重要**:所有业务数据查询必须包含 `tenantId` 条件! ## 核心原则 ### 1. 数据库查询 - **必须**:所有业务表查询必须包含 `tenantId` 条件 - 超级租户(`isSuper = 1`)可以访问所有租户数据 ```typescript // ✅ 正确示例 const users = await this.prisma.user.findMany({ where: { tenantId, validState: 1, }, }); // ❌ 错误示例 - 缺少 tenantId const users = await this.prisma.user.findMany({ where: { validState: 1, }, }); ``` ### 2. 获取租户ID 在控制器中使用 `@CurrentTenantId()` 装饰器: ```typescript @Get() async findAll(@CurrentTenantId() tenantId: number) { return this.service.findAll(tenantId); } ``` ### 3. 创建数据 创建数据时自动设置 `tenantId`: ```typescript async create(createDto: CreateDto, tenantId: number) { return this.prisma.model.create({ data: { ...createDto, tenantId, }, }); } ``` ### 4. 更新/删除数据 更新或删除前验证数据属于当前租户: ```typescript async update(id: number, updateDto: UpdateDto, tenantId: number) { // 先验证数据属于当前租户 const existing = await this.prisma.model.findFirst({ where: { id, tenantId }, }); if (!existing) { throw new NotFoundException('数据不存在或不属于当前租户'); } return this.prisma.model.update({ where: { id }, data: updateDto, }); } ``` ## 数据库表设计 所有业务表必须包含: - `tenantId`: Int - 租户ID(必填) - `creator`: Int? - 创建人ID - `modifier`: Int? - 修改人ID - `createTime`: DateTime @default(now()) - `modifyTime`: DateTime @updatedAt - `validState`: Int @default(1) - 有效状态(1-有效,2-失效) ## 审查清单 在代码审查时,重点检查: - [ ] 所有 `findMany`、`findFirst`、`findUnique` 包含 `tenantId` 条件 - [ ] 创建操作设置了 `tenantId` - [ ] 更新/删除操作验证了 `tenantId` - [ ] 新的 Prisma 模型包含了 `tenantId` 字段