重构数据权限模型并清理旧RBAC代码
核心变更: - 数据权限过滤从基于账号层级改为基于用户类型的多策略过滤 - 移除 AccountStore 中的 GetSubordinateIDs 等旧方法 - 重构认证中间件,支持 enterprise_id 和 customer_id - 更新 GORM Callback,根据用户类型自动选择过滤策略(代理/企业/个人客户) - 更新所有集成测试以适配新的 API 签名 - 添加功能总结文档和 OpenSpec 归档 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,13 +2,10 @@ package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/store"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -133,67 +130,3 @@ func (s *AccountStore) List(ctx context.Context, opts *store.QueryOptions, filte
|
||||
return accounts, total, nil
|
||||
}
|
||||
|
||||
// GetSubordinateIDs 获取账号的所有可见账号 ID(包含自己)
|
||||
// 废弃说明:账号层级关系已改为通过 Shop 表维护
|
||||
// 新的数据权限过滤应该基于 ShopID,而非账号的 ParentID
|
||||
// 使用 Redis 缓存优化性能,缓存 30 分钟
|
||||
//
|
||||
// 对于代理账号:查询该账号所属店铺及其下级店铺的所有账号
|
||||
// 对于平台用户和超级管理员:返回空(在上层跳过过滤)
|
||||
func (s *AccountStore) GetSubordinateIDs(ctx context.Context, accountID uint) ([]uint, error) {
|
||||
// 1. 尝试从 Redis 缓存读取
|
||||
cacheKey := constants.RedisAccountSubordinatesKey(accountID)
|
||||
cached, err := s.redis.Get(ctx, cacheKey).Result()
|
||||
if err == nil {
|
||||
var ids []uint
|
||||
if err := sonic.Unmarshal([]byte(cached), &ids); err == nil {
|
||||
return ids, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 查询当前账号
|
||||
account, err := s.GetByID(ctx, accountID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 3. 如果是代理账号,需要查询该店铺及下级店铺的所有账号
|
||||
var ids []uint
|
||||
if account.UserType == constants.UserTypeAgent && account.ShopID != nil {
|
||||
// 注意:这里需要 ShopStore 来查询店铺的下级
|
||||
// 但为了避免循环依赖,这个逻辑应该在 Service 层处理
|
||||
// Store 层只提供基础的数据访问能力
|
||||
// 暂时返回只包含自己的列表
|
||||
ids = []uint{accountID}
|
||||
} else {
|
||||
// 平台用户和超级管理员返回空列表(在 Service 层跳过过滤)
|
||||
ids = []uint{}
|
||||
}
|
||||
|
||||
// 4. 写入 Redis 缓存(30 分钟过期)
|
||||
data, _ := sonic.Marshal(ids)
|
||||
s.redis.Set(ctx, cacheKey, data, 30*time.Minute)
|
||||
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// ClearSubordinatesCache 清除指定账号的下级 ID 缓存
|
||||
func (s *AccountStore) ClearSubordinatesCache(ctx context.Context, accountID uint) error {
|
||||
cacheKey := constants.RedisAccountSubordinatesKey(accountID)
|
||||
return s.redis.Del(ctx, cacheKey).Err()
|
||||
}
|
||||
|
||||
// ClearSubordinatesCacheForParents 递归清除所有上级账号的缓存
|
||||
// 废弃说明:账号层级关系已改为通过 Shop 表维护
|
||||
// 新版本应该清除店铺层级的缓存,而非账号层级
|
||||
func (s *AccountStore) ClearSubordinatesCacheForParents(ctx context.Context, accountID uint) error {
|
||||
// 清除当前账号的缓存
|
||||
if err := s.ClearSubordinatesCache(ctx, accountID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: 应该清除该账号所属店铺及上级店铺的下级缓存
|
||||
// 但这需要访问 ShopStore,为了避免循环依赖,应在 Service 层处理
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user