Files
junhong_cmp_fiber/internal/store/postgres/permission_store.go
huang 1b9080e3ab 实现角色权限体系重构
本次提交完成了角色权限体系的重构,主要包括:

1. 数据库迁移
   - 添加 tb_permission.platform 字段(all/web/h5)
   - 更新 tb_role.role_type 注释(1=平台角色,2=客户角色)

2. GORM 模型更新
   - Permission 模型添加 Platform 字段
   - Role 模型更新 RoleType 注释

3. 常量定义
   - 新增角色类型常量(RoleTypePlatform, RoleTypeCustomer)
   - 新增权限端口常量(PlatformAll, PlatformWeb, PlatformH5)
   - 添加角色类型与用户类型匹配规则函数

4. Store 层实现
   - Permission Store 支持按 platform 过滤
   - Account Role Store 添加 CountByAccountID 方法

5. Service 层实现
   - 角色分配支持类型匹配校验
   - 角色分配支持数量限制(超级管理员0个,平台用户无限制,代理/企业1个)
   - Permission Service 支持 platform 过滤

6. 权限校验中间件
   - 实现 RequirePermission、RequireAnyPermission、RequireAllPermissions
   - 支持 platform 字段过滤
   - 支持跳过超级管理员检查

7. 测试用例
   - 角色类型匹配规则单元测试
   - 角色分配数量限制单元测试
   - 权限 platform 过滤单元测试
   - 权限校验中间件集成测试(占位)

8. 代码清理
   - 删除过时的 subordinate 测试文件
   - 移除 Account.ParentID 相关引用
   - 更新 DTO 验证规则

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-10 09:51:52 +08:00

143 lines
4.2 KiB
Go
Raw 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.
package postgres
import (
"context"
"gorm.io/gorm"
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/break/junhong_cmp_fiber/internal/store"
)
// PermissionStore 权限数据访问层
type PermissionStore struct {
db *gorm.DB
}
// NewPermissionStore 创建权限 Store
func NewPermissionStore(db *gorm.DB) *PermissionStore {
return &PermissionStore{db: db}
}
// Create 创建权限
func (s *PermissionStore) Create(ctx context.Context, permission *model.Permission) error {
return s.db.WithContext(ctx).Create(permission).Error
}
// GetByID 根据 ID 获取权限
func (s *PermissionStore) GetByID(ctx context.Context, id uint) (*model.Permission, error) {
var permission model.Permission
if err := s.db.WithContext(ctx).First(&permission, id).Error; err != nil {
return nil, err
}
return &permission, nil
}
// GetByCode 根据权限编码获取权限
func (s *PermissionStore) GetByCode(ctx context.Context, code string) (*model.Permission, error) {
var permission model.Permission
if err := s.db.WithContext(ctx).Where("perm_code = ?", code).First(&permission).Error; err != nil {
return nil, err
}
return &permission, nil
}
// Update 更新权限
func (s *PermissionStore) Update(ctx context.Context, permission *model.Permission) error {
return s.db.WithContext(ctx).Save(permission).Error
}
// Delete 软删除权限
func (s *PermissionStore) Delete(ctx context.Context, id uint) error {
return s.db.WithContext(ctx).Delete(&model.Permission{}, id).Error
}
// List 查询权限列表
func (s *PermissionStore) List(ctx context.Context, opts *store.QueryOptions, filters map[string]interface{}) ([]*model.Permission, int64, error) {
var permissions []*model.Permission
var total int64
query := s.db.WithContext(ctx).Model(&model.Permission{})
// 应用过滤条件
if name, ok := filters["perm_name"].(string); ok && name != "" {
query = query.Where("perm_name LIKE ?", "%"+name+"%")
}
if code, ok := filters["perm_code"].(string); ok && code != "" {
query = query.Where("perm_code LIKE ?", "%"+code+"%")
}
if permType, ok := filters["perm_type"].(int); ok {
query = query.Where("perm_type = ?", permType)
}
if platform, ok := filters["platform"].(string); ok && platform != "" {
query = query.Where("platform = ?", platform)
}
if parentID, ok := filters["parent_id"].(uint); ok {
query = query.Where("parent_id = ?", parentID)
}
if status, ok := filters["status"].(int); ok {
query = query.Where("status = ?", status)
}
// 计算总数
if err := query.Count(&total).Error; err != nil {
return nil, 0, err
}
// 分页
if opts == nil {
opts = store.DefaultQueryOptions()
}
offset := (opts.Page - 1) * opts.PageSize
query = query.Offset(offset).Limit(opts.PageSize)
// 排序
if opts.OrderBy != "" {
query = query.Order(opts.OrderBy)
} else {
query = query.Order("sort ASC, id ASC")
}
// 执行查询
if err := query.Find(&permissions).Error; err != nil {
return nil, 0, err
}
return permissions, total, nil
}
// GetByIDs 根据 ID 列表获取权限
func (s *PermissionStore) GetByIDs(ctx context.Context, ids []uint) ([]*model.Permission, error) {
var permissions []*model.Permission
if err := s.db.WithContext(ctx).Where("id IN ?", ids).Find(&permissions).Error; err != nil {
return nil, err
}
return permissions, nil
}
// GetAll 获取所有权限(用于构建权限树)
func (s *PermissionStore) GetAll(ctx context.Context) ([]*model.Permission, error) {
var permissions []*model.Permission
if err := s.db.WithContext(ctx).Order("sort ASC, id ASC").Find(&permissions).Error; err != nil {
return nil, err
}
return permissions, nil
}
// GetByPlatform 根据端口获取权限列表
// platform: 端口类型all/web/h5如果为空则返回所有权限
func (s *PermissionStore) GetByPlatform(ctx context.Context, platform string) ([]*model.Permission, error) {
var permissions []*model.Permission
query := s.db.WithContext(ctx).Where("status = ?", 1) // 只获取启用的权限
if platform != "" {
// 获取指定端口的权限或通用权限platform='all'
query = query.Where("platform = ? OR platform = ?", platform, "all")
}
if err := query.Order("sort ASC, id ASC").Find(&permissions).Error; err != nil {
return nil, err
}
return permissions, nil
}