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

5.1 KiB
Raw Permalink Blame History

permission-check Specification

Purpose

TBD - created by archiving change implement-permission-check. Update Purpose after archive.

Requirements

Requirement: 权限检查核心服务

Permission Service SHALL 提供 CheckPermission 方法,用于检查用户是否拥有指定权限。

签名:

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 忽略 permCodeplatform 参数

Scenario: 有权限的普通用户

  • WHEN 调用 CheckPermission 检查普通用户权限
  • AND 用户通过角色关联拥有该权限
  • AND 权限的 permCode 匹配
  • AND 权限的 platformall 或匹配请求的 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 请求的 platformweb
  • THEN 权限匹配成功

Scenario: 精确平台匹配

  • WHEN 权限的 platform 字段为 web
  • AND 请求的 platformweb
  • THEN 权限匹配成功

Scenario: 平台不匹配

  • WHEN 权限的 platform 字段为 h5
  • AND 请求的 platformweb
  • THEN 权限不匹配
  • AND 继续检查用户的其他权限

Requirement: 权限查询链式执行

权限检查 SHALL 按照以下顺序执行查询:

  1. 检查用户类型(超级管理员跳过)
  2. 查询用户的角色 ID 列表
  3. 查询角色的权限 ID 列表(去重)
  4. 查询权限详情列表
  5. 遍历匹配 permCodeplatform

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 集成

  • WHENinternal/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 用于安全审计和问题排查