# Epic-006: Shared-CRUD 数据权限控制增强 - Brownfield Enhancement

## Epic Goal

增强 shared-crud 包的数据权限控制能力，支持基于用户ID的数据访问权限控制，使业务模块能够轻松实现"用户只能操作自己的数据"的安全需求，同时保持向后兼容性和配置灵活性。

## Epic Description

### Existing System Context

**Current relevant functionality:**
- shared-crud 包已提供基础的 CRUD 操作和用户跟踪字段自动填充
- 现有 `userTracking` 配置支持创建和更新时自动设置用户ID字段
- 认证系统通过 JWT token 在上下文中提供用户信息
- 业务模块使用 shared-crud 作为数据访问层基础设施

**Current limitations:**
- 查询操作没有基于用户ID的数据过滤
- 删除操作没有权限验证
- 创建操作没有权限限制（用户可以创建不属于自己的数据）
- 更新操作没有权限验证（用户可以更新不属于自己的数据）
- 缺乏统一的数据权限控制配置
- 业务模块需要手动实现数据权限逻辑

**Technology stack:**
- Backend: Node.js, TypeScript, Hono, TypeORM, PostgreSQL
- Authentication: JWT, Redis session management
- Database: PostgreSQL with user tracking fields
- Package: shared-crud, shared-types, shared-utils

**Integration points:**
- 现有认证中间件提供用户上下文
- 业务模块实体中的用户关联字段（userId, createdBy, updatedBy）
- 现有的 CRUD 路由和服务层
- 现有的用户跟踪字段自动填充机制

### Enhancement Details

**What's being added/changed:**
- 数据权限控制配置选项，支持基于用户ID的数据过滤
- 查询操作的自动权限过滤
- 创建操作的权限限制（防止创建不属于自己的数据）
- 更新操作的权限验证
- 删除操作的权限验证
- 管理员权限覆盖机制
- 向后兼容的权限控制配置

**Enhanced architecture:**
```
shared-crud/
├── src/
│   ├── services/
│   │   ├── generic-crud.service.ts (增强权限控制)
│   │   └── concrete-crud.service.ts
│   ├── routes/
│   │   └── generic-crud.routes.ts (增强权限中间件)
│   ├── types/
│   │   └── data-permission.types.ts (新增权限类型定义)
│   └── middleware/
│       └── data-permission.middleware.ts (新增权限中间件)
```

**How it integrates:**
- 扩展现有的 `CrudOptions` 接口，添加数据权限配置
- 复用现有的用户跟踪字段配置
- 保持现有 API 不变，新增配置为可选
- 与现有认证系统无缝集成
- 提供灵活的权限控制粒度

**Success criteria:**
- 现有功能不受影响，保持向后兼容
- 业务模块可以轻松启用数据权限控制
- 查询、创建、更新、删除操作自动进行权限验证
- 创建操作防止用户创建不属于自己的数据
- 提供管理员权限覆盖机制
- 完整的单元测试和集成测试覆盖
- 清晰的配置文档和使用示例

## Stories

### 阶段 1: 核心权限控制功能
1. **Story 1:** Shared-CRUD 数据权限控制完整实现 - 实现完整的数据权限控制功能，包括：
   - 数据权限控制类型定义和配置接口
   - 查询操作的自动权限过滤（getList 和 getById）
   - 创建操作的权限限制（防止创建不属于自己的数据）
   - 更新操作的权限验证
   - 删除操作的权限验证
   - 权限控制中间件
   - 管理员权限覆盖机制
   - 完整的单元测试和集成测试

### 阶段 2: 高级功能和集成
2. **Story 2:** 高级权限功能和业务模块集成 - 实现高级权限功能和集成示例：
   - 多租户数据隔离支持
   - 自定义权限验证钩子
   - 业务模块集成示例（用户模块）
   - 性能优化和基准测试
   - 完整的使用文档和迁移指南

## Compatibility Requirements

- [x] 现有 APIs 保持不变，权限控制为可选配置
- [x] 现有业务模块无需修改即可继续使用
- [x] 数据库 schema 保持不变
- [x] 性能影响最小化，权限过滤使用数据库索引
- [x] 配置向后兼容，现有 userTracking 配置继续有效

## Risk Mitigation

**Primary Risk:** 权限控制影响现有查询性能
**Mitigation:** 使用数据库索引优化权限过滤查询，提供性能基准测试
**Rollback Plan:** 权限控制为可选配置，可随时禁用

**Primary Risk:** 复杂的权限配置影响开发体验
**Mitigation:** 提供简化的默认配置和清晰的文档
**Rollback Plan:** 保持现有配置方式不变，新增配置可选

**Primary Risk:** 权限验证逻辑与业务逻辑耦合
**Mitigation:** 权限控制作为基础设施层，与业务逻辑分离
**Rollback Plan:** 权限验证可独立禁用

## Definition of Done

- [ ] Story 1 完成且验收标准满足
- [ ] 现有功能通过回归测试验证
- [ ] 权限控制配置灵活且易于使用
- [ ] 性能基准测试通过，无明显性能下降
- [ ] 完整的单元测试和集成测试覆盖
- [ ] 使用文档和示例代码完整
- [ ] 向后兼容性验证通过

## 架构设计详情

### 权限控制配置设计

```typescript
// 扩展现有的 CrudOptions
export interface DataPermissionOptions {
  enabled: boolean;
  userIdField: string; // 用户ID字段名，如 'userId', 'createdBy'
  adminOverride?: {
    enabled: boolean;
    adminRole?: string; // 管理员角色标识
    userIdField?: string; // 管理员用户ID字段
  };
  multiTenant?: {
    enabled: boolean;
    tenantIdField: string; // 租户ID字段名
  };
  customValidator?: (userId: string | number, entity: any) => Promise<boolean>;
}

// 扩展 CrudOptions
export type CrudOptions<T extends ObjectLiteral, ...> = {
  // ... 现有配置
  userTracking?: UserTrackingOptions;
  dataPermission?: DataPermissionOptions; // 新增权限控制配置
  // ...
};
```

### 权限控制实现设计

#### 查询权限过滤
```typescript
// 在 getList 方法中添加权限过滤
async getList(
  page: number = 1,
  pageSize: number = 10,
  keyword?: string,
  searchFields?: string[],
  where?: Partial<T>,
  relations: string[] = [],
  order: { [P in keyof T]?: 'ASC' | 'DESC' } = {},
  filters?: { [key: string]: any },
  userId?: string | number // 新增用户ID参数
): Promise<[T[], number]> {
  // 构建基础查询
  const query = this.repository.createQueryBuilder('entity');

  // 添加权限过滤条件
  if (this.dataPermissionOptions?.enabled && userId) {
    const userIdField = this.dataPermissionOptions.userIdField;
    query.andWhere(`entity.${userIdField} = :userId`, { userId });
  }

  // ... 现有查询逻辑
}
```

#### 创建权限限制
```typescript
async create(data: DeepPartial<T>, userId?: string | number): Promise<T> {
  // 权限验证：防止用户创建不属于自己的数据
  if (this.dataPermissionOptions?.enabled && userId) {
    const userIdField = this.dataPermissionOptions.userIdField;

    // 如果数据中已经包含用户ID字段，验证是否与当前用户匹配
    if (data[userIdField] && data[userIdField] !== userId) {
      throw new Error('无权创建该资源');
    }
  }

  const entityData = { ...data };
  this.setUserFields(entityData, userId, true);

  // ... 现有创建逻辑
}
```

#### 更新权限验证
```typescript
async update(id: number, data: Partial<T>, userId?: string | number): Promise<T | null> {
  // 权限验证
  if (this.dataPermissionOptions?.enabled && userId) {
    const entity = await this.getById(id);
    if (!entity) return null;

    const userIdField = this.dataPermissionOptions.userIdField;
    const entityUserId = (entity as any)[userIdField];

    if (entityUserId !== userId) {
      throw new Error('无权更新该资源');
    }
  }

  const updateData = { ...data };
  this.setUserFields(updateData, userId, false);

  // ... 现有更新逻辑
}
```

#### 删除权限验证
```typescript
async delete(id: number, userId?: string | number): Promise<boolean> {
  // 权限验证
  if (this.dataPermissionOptions?.enabled && userId) {
    const entity = await this.getById(id);
    if (!entity) return false;

    const userIdField = this.dataPermissionOptions.userIdField;
    const entityUserId = (entity as any)[userIdField];

    if (entityUserId !== userId) {
      throw new Error('无权删除该资源');
    }
  }

  // 执行删除
  const result = await this.repository.delete(id);
  return result.affected === 1;
}
```

### 路由层集成设计

#### 权限控制中间件
```typescript
export function dataPermissionMiddleware(
  options: DataPermissionOptions
): MiddlewareHandler<AuthContext> {
  return async (c, next) => {
    if (!options.enabled) {
      return next();
    }

    const user = c.get('user');
    if (!user?.id) {
      return c.json({ code: 401, message: '未授权访问' }, 401);
    }

    // 设置用户ID到上下文，供服务层使用
    c.set('dataPermissionUserId', user.id);

    await next();
  };
}
```

#### 路由配置示例
```typescript
// 现有配置方式（保持兼容）
createCrudRoutes({
  entity: UserEntity,
  createSchema: CreateUserSchema,
  updateSchema: UpdateUserSchema,
  getSchema: GetUserSchema,
  listSchema: ListUserSchema,
  userTracking: { userIdField: 'userId' },
  // 新增权限控制配置
  dataPermission: {
    enabled: true,
    userIdField: 'userId',
    adminOverride: {
      enabled: true,
      adminRole: 'admin'
    }
  }
});
```

### 管理员权限覆盖机制

```typescript
// 在权限验证中添加管理员检查
private async checkPermission(
  entity: any,
  userId: string | number
): Promise<boolean> {
  const options = this.dataPermissionOptions;
  if (!options?.enabled) return true;

  // 管理员权限覆盖
  if (options.adminOverride?.enabled) {
    const user = await this.getCurrentUser(userId);
    if (user?.role === options.adminOverride.adminRole) {
      return true;
    }
  }

  // 普通用户权限验证
  const userIdField = options.userIdField;
  const entityUserId = (entity as any)[userIdField];
  return entityUserId === userId;
}
```

## 使用示例

### 基础权限控制配置
```typescript
// 用户只能操作自己的数据
createCrudRoutes({
  entity: UserProfileEntity,
  // ... 其他配置
  userTracking: { userIdField: 'userId' },
  dataPermission: {
    enabled: true,
    userIdField: 'userId'
  }
});
```

### 管理员权限覆盖配置
```typescript
// 管理员可以查看所有用户数据
createCrudRoutes({
  entity: UserProfileEntity,
  // ... 其他配置
  userTracking: { userIdField: 'userId' },
  dataPermission: {
    enabled: true,
    userIdField: 'userId',
    adminOverride: {
      enabled: true,
      adminRole: 'admin'
    }
  }
});
```

### 多租户数据隔离
```typescript
// 支持多租户数据隔离
createCrudRoutes({
  entity: TenantDataEntity,
  // ... 其他配置
  dataPermission: {
    enabled: true,
    userIdField: 'createdBy',
    multiTenant: {
      enabled: true,
      tenantIdField: 'tenantId'
    }
  }
});
```

### 自定义权限验证
```typescript
// 自定义复杂的权限验证逻辑
createCrudRoutes({
  entity: ComplexEntity,
  // ... 其他配置
  dataPermission: {
    enabled: true,
    userIdField: 'ownerId',
    customValidator: async (userId, entity) => {
      // 自定义权限验证逻辑
      return await someComplexPermissionCheck(userId, entity);
    }
  }
});
```

## 技术实现要点

### 向后兼容性保证
1. **配置可选**: 数据权限控制为可选配置，默认禁用
2. **API 不变**: 现有 API 接口和行为保持不变
3. **性能优化**: 权限过滤使用数据库索引，性能影响最小化
4. **错误处理**: 权限验证失败返回明确的错误信息

### 安全性考虑
1. **默认安全**: 启用权限控制后，默认遵循最小权限原则
2. **输入验证**: 所有用户输入进行严格的验证和转义
3. **SQL 注入防护**: 使用参数化查询防止 SQL 注入
4. **错误信息**: 权限错误信息不泄露敏感数据

### 性能优化
1. **数据库索引**: 确保用户ID字段有合适的索引
2. **查询优化**: 权限过滤条件与现有查询条件合并
3. **缓存策略**: 考虑权限验证结果的缓存
4. **批量操作**: 支持批量操作的权限验证优化

## 测试策略

### 单元测试
- 权限配置验证测试
- 查询权限过滤测试
- 创建权限限制测试
- 更新权限验证测试
- 删除权限验证测试
- 管理员权限覆盖测试
- 自定义权限验证测试

### 集成测试
- 完整 CRUD 操作的权限控制测试（创建、查询、更新、删除）
- 多用户场景的权限隔离测试
- 创建操作权限限制场景测试
- 更新操作权限验证场景测试
- 管理员权限覆盖场景测试
- 性能基准测试

### 回归测试
- 现有功能回归测试
- 向后兼容性验证测试
- 配置迁移测试

---

## Story Manager Handoff

"请为这个brownfield epic开发详细的用户故事。关键考虑因素：

- 这是一个对现有 shared-crud 包的增强，运行在 Node.js + TypeScript + Hono + TypeORM + PostgreSQL 技术栈上
- 集成点：现有认证系统、用户跟踪字段、CRUD 服务层、路由配置
- 需要遵循的现有模式：TypeORM 查询构建、Hono 中间件、配置驱动开发
- 关键兼容性要求：现有配置和 API 保持不变、性能影响最小化、错误处理一致
- 故事必须包含验证现有功能保持完整的回归测试

该epic应该保持系统完整性，同时实现 shared-crud 包的数据权限控制增强，为业务模块提供安全、灵活的数据访问控制能力。"