Files
huang 028cfaa7aa feat: 实现权限检查功能并添加Redis缓存优化
- 完成 CheckPermission 方法的完整实现(账号→角色→权限查询链)
- 实现 Redis 缓存机制,大幅提升权限查询性能(~12倍提升)
- 自动缓存失效:角色/权限变更时清除相关用户缓存
- 新增完整的单元测试和集成测试(10个测试用例全部通过)
- 添加权限检查使用文档和缓存机制说明
- 归档 implement-permission-check OpenSpec 提案

性能优化:
- 首次查询: ~18ms(3次DB查询 + 1次Redis写入)
- 缓存命中: ~1.5ms(1次Redis查询)
- TTL: 30分钟,自动失效机制保证数据一致性
2026-01-16 18:15:32 +08:00

166 lines
5.1 KiB
Markdown
Raw Permalink 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.
# permission-check Specification
## Purpose
TBD - created by archiving change implement-permission-check. Update Purpose after archive.
## Requirements
### Requirement: 权限检查核心服务
Permission Service SHALL 提供 `CheckPermission` 方法,用于检查用户是否拥有指定权限。
**签名**:
```go
CheckPermission(ctx context.Context, userID uint, permCode string, platform string) (bool, error)
```
**参数**:
- `ctx`: 上下文(可选包含用户类型信息)
- `userID`: 用户 ID
- `permCode`: 权限编码(格式:`module:action`,如 `user:create`
- `platform`: 端口类型(`all`/`web`/`h5`
**返回值**:
- `bool`: 是否拥有权限true = 有权限false = 无权限)
- `error`: 错误信息(查询失败时)
#### Scenario: 超级管理员权限检查
- **WHEN** 调用 `CheckPermission` 检查超级管理员user_type = 1的权限
- **THEN** 直接返回 `(true, nil)`
- **AND** 不执行任何数据库查询
- **AND** 忽略 `permCode``platform` 参数
#### Scenario: 有权限的普通用户
- **WHEN** 调用 `CheckPermission` 检查普通用户权限
- **AND** 用户通过角色关联拥有该权限
- **AND** 权限的 `permCode` 匹配
- **AND** 权限的 `platform``all` 或匹配请求的 `platform`
- **THEN** 返回 `(true, nil)`
#### Scenario: 无权限的普通用户
- **WHEN** 调用 `CheckPermission` 检查普通用户权限
- **AND** 用户的所有角色都不包含该权限
- **THEN** 返回 `(false, nil)`
#### Scenario: 用户无角色
- **WHEN** 调用 `CheckPermission` 检查用户权限
- **AND** 用户未分配任何角色
- **THEN** 返回 `(false, nil)`
#### Scenario: 角色无权限
- **WHEN** 调用 `CheckPermission` 检查用户权限
- **AND** 用户已分配角色
- **AND** 所有角色都未分配任何权限
- **THEN** 返回 `(false, nil)`
#### Scenario: 数据库查询失败
- **WHEN** 调用 `CheckPermission` 过程中数据库查询失败
- **THEN** 返回 `(false, error)`
- **AND** error 包含详细的失败原因
### Requirement: Platform 参数匹配
权限检查 SHALL 支持 `platform` 参数过滤,实现端口隔离。
**匹配规则**:
- 权限的 `platform` 字段为 `all` → 任意 `platform` 参数都匹配
- 权限的 `platform` 字段与请求的 `platform` 相同 → 匹配
- 其他情况 → 不匹配
#### Scenario: 全平台权限匹配
- **WHEN** 权限的 `platform` 字段为 `all`
- **AND** 请求的 `platform``web`
- **THEN** 权限匹配成功
#### Scenario: 精确平台匹配
- **WHEN** 权限的 `platform` 字段为 `web`
- **AND** 请求的 `platform``web`
- **THEN** 权限匹配成功
#### Scenario: 平台不匹配
- **WHEN** 权限的 `platform` 字段为 `h5`
- **AND** 请求的 `platform``web`
- **THEN** 权限不匹配
- **AND** 继续检查用户的其他权限
### Requirement: 权限查询链式执行
权限检查 SHALL 按照以下顺序执行查询:
1. 检查用户类型(超级管理员跳过)
2. 查询用户的角色 ID 列表
3. 查询角色的权限 ID 列表(去重)
4. 查询权限详情列表
5. 遍历匹配 `permCode``platform`
#### Scenario: 正常查询流程
- **WHEN** 调用 `CheckPermission` 检查普通用户权限
- **THEN** 按顺序执行以下查询:
1. `AccountRoleStore.GetRoleIDsByAccountID(ctx, userID)` 获取角色 ID 列表
2. `RolePermissionStore.GetPermIDsByRoleIDs(ctx, roleIDs)` 获取权限 ID 列表
3. `PermissionStore.GetByIDs(ctx, permIDs)` 获取权限详情
- **AND** 遍历权限列表进行匹配
- **AND** 找到匹配权限后立即返回 `true`(短路优化)
#### Scenario: 空结果短路
- **WHEN** 任意查询步骤返回空列表(如用户无角色)
- **THEN** 立即返回 `(false, nil)`
- **AND** 不执行后续查询
### Requirement: Service 依赖注入
Permission Service SHALL 在初始化时注入所需的 Store 依赖。
**依赖**:
- `PermissionStore` - 查询权限详情
- `AccountRoleStore` - 查询用户角色关联
- `RolePermissionStore` - 查询角色权限关联
#### Scenario: Service 初始化
- **WHEN** 创建 Permission Service 实例
- **THEN** 构造函数接收以下参数:
- `permissionStore *postgres.PermissionStore`
- `accountRoleStore *postgres.AccountRoleStore`
- `rolePermStore *postgres.RolePermissionStore`
- **AND** 存储在结构体字段中供 `CheckPermission` 使用
#### Scenario: Bootstrap 集成
- **WHEN** 在 `internal/bootstrap/services.go` 初始化 Permission Service
- **THEN** 传入所有必需的 Store 依赖
- **AND** Store 依赖已在 `initStores()` 中初始化
### Requirement: 错误处理和日志
权限检查 SHALL 提供详细的错误处理和日志记录。
#### Scenario: 数据库查询错误日志
- **WHEN** 数据库查询失败(如角色查询失败)
- **THEN** 记录错误日志,包含:
- 用户 ID
- 失败的查询类型(角色/权限)
- 错误详情
- **AND** 返回包装后的错误(使用 `fmt.Errorf`
#### Scenario: 权限检查成功日志(可选)
- **WHEN** 权限检查成功
- **THEN** 可选记录 debug 级别日志:
- 用户 ID
- 权限编码
- 平台类型
- 检查结果
- **AND** 用于安全审计和问题排查