// Package permission 提供权限管理的业务逻辑服务 // 包含权限创建、查询、更新、删除、权限检查等功能 package permission import ( "context" "fmt" "regexp" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/internal/store" "github.com/break/junhong_cmp_fiber/internal/store/postgres" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/errors" "github.com/break/junhong_cmp_fiber/pkg/middleware" "gorm.io/gorm" ) // permCodeRegex 权限编码格式验证正则(module:action) var permCodeRegex = regexp.MustCompile(`^[a-z][a-z0-9_]*:[a-z][a-z0-9_]*$`) // Service 权限业务服务 type Service struct { permissionStore *postgres.PermissionStore } // New 创建权限服务 func New(permissionStore *postgres.PermissionStore) *Service { return &Service{ permissionStore: permissionStore, } } // Create 创建权限 func (s *Service) Create(ctx context.Context, req *model.CreatePermissionRequest) (*model.Permission, error) { // 获取当前用户 ID currentUserID := middleware.GetUserIDFromContext(ctx) if currentUserID == 0 { return nil, errors.New(errors.CodeUnauthorized, "未授权访问") } // 验证权限编码格式 if !permCodeRegex.MatchString(req.PermCode) { return nil, errors.New(errors.CodeInvalidPermCode, "权限编码格式不正确(应为 module:action 格式)") } // 检查权限编码唯一性 existing, err := s.permissionStore.GetByCode(ctx, req.PermCode) if err == nil && existing != nil { return nil, errors.New(errors.CodePermCodeExists, "权限编码已存在") } // 验证 parent_id 存在(如果提供) if req.ParentID != nil { parent, err := s.permissionStore.GetByID(ctx, *req.ParentID) if err != nil || parent == nil { return nil, errors.New(errors.CodeNotFound, "上级权限不存在") } } // 创建权限 permission := &model.Permission{ PermName: req.PermName, PermCode: req.PermCode, PermType: req.PermType, Platform: req.Platform, URL: req.URL, ParentID: req.ParentID, Sort: req.Sort, Status: constants.StatusEnabled, } // 如果未指定 platform,默认为 all if permission.Platform == "" { permission.Platform = constants.PlatformAll } if err := s.permissionStore.Create(ctx, permission); err != nil { return nil, fmt.Errorf("创建权限失败: %w", err) } return permission, nil } // Get 获取权限 func (s *Service) Get(ctx context.Context, id uint) (*model.Permission, error) { permission, err := s.permissionStore.GetByID(ctx, id) if err != nil { if err == gorm.ErrRecordNotFound { return nil, errors.New(errors.CodePermissionNotFound, "权限不存在") } return nil, fmt.Errorf("获取权限失败: %w", err) } return permission, nil } // Update 更新权限 func (s *Service) Update(ctx context.Context, id uint, req *model.UpdatePermissionRequest) (*model.Permission, error) { // 获取当前用户 ID currentUserID := middleware.GetUserIDFromContext(ctx) if currentUserID == 0 { return nil, errors.New(errors.CodeUnauthorized, "未授权访问") } // 获取现有权限 permission, err := s.permissionStore.GetByID(ctx, id) if err != nil { if err == gorm.ErrRecordNotFound { return nil, errors.New(errors.CodePermissionNotFound, "权限不存在") } return nil, fmt.Errorf("获取权限失败: %w", err) } // 更新字段 if req.PermName != nil { permission.PermName = *req.PermName } if req.PermCode != nil { // 验证权限编码格式 if !permCodeRegex.MatchString(*req.PermCode) { return nil, errors.New(errors.CodeInvalidPermCode, "权限编码格式不正确(应为 module:action 格式)") } // 检查新权限编码唯一性 existing, err := s.permissionStore.GetByCode(ctx, *req.PermCode) if err == nil && existing != nil && existing.ID != id { return nil, errors.New(errors.CodePermCodeExists, "权限编码已存在") } permission.PermCode = *req.PermCode } if req.Platform != nil { permission.Platform = *req.Platform } if req.URL != nil { permission.URL = *req.URL } if req.ParentID != nil { // 验证 parent_id 存在 parent, err := s.permissionStore.GetByID(ctx, *req.ParentID) if err != nil || parent == nil { return nil, errors.New(errors.CodeNotFound, "上级权限不存在") } permission.ParentID = req.ParentID } if req.Sort != nil { permission.Sort = *req.Sort } if req.Status != nil { permission.Status = *req.Status } permission.Updater = currentUserID if err := s.permissionStore.Update(ctx, permission); err != nil { return nil, fmt.Errorf("更新权限失败: %w", err) } return permission, nil } // Delete 软删除权限 func (s *Service) Delete(ctx context.Context, id uint) error { // 检查权限存在 _, err := s.permissionStore.GetByID(ctx, id) if err != nil { if err == gorm.ErrRecordNotFound { return errors.New(errors.CodePermissionNotFound, "权限不存在") } return fmt.Errorf("获取权限失败: %w", err) } if err := s.permissionStore.Delete(ctx, id); err != nil { return fmt.Errorf("删除权限失败: %w", err) } return nil } // List 查询权限列表 func (s *Service) List(ctx context.Context, req *model.PermissionListRequest) ([]*model.Permission, int64, error) { opts := &store.QueryOptions{ Page: req.Page, PageSize: req.PageSize, OrderBy: "sort ASC, id ASC", } if opts.Page == 0 { opts.Page = 1 } if opts.PageSize == 0 { opts.PageSize = constants.DefaultPageSize } filters := make(map[string]interface{}) if req.PermName != "" { filters["perm_name"] = req.PermName } if req.PermCode != "" { filters["perm_code"] = req.PermCode } if req.PermType != nil { filters["perm_type"] = *req.PermType } if req.Platform != "" { filters["platform"] = req.Platform } if req.ParentID != nil { filters["parent_id"] = *req.ParentID } if req.Status != nil { filters["status"] = *req.Status } return s.permissionStore.List(ctx, opts, filters) } // GetTree 获取权限树 func (s *Service) GetTree(ctx context.Context) ([]*model.PermissionTreeNode, error) { // 获取所有权限 permissions, err := s.permissionStore.GetAll(ctx) if err != nil { return nil, fmt.Errorf("获取权限列表失败: %w", err) } // 构建树结构 return buildPermissionTree(permissions), nil } // buildPermissionTree 构建权限树 func buildPermissionTree(permissions []*model.Permission) []*model.PermissionTreeNode { // 转换为节点映射 nodeMap := make(map[uint]*model.PermissionTreeNode) for _, p := range permissions { nodeMap[p.ID] = &model.PermissionTreeNode{ ID: p.ID, PermName: p.PermName, PermCode: p.PermCode, PermType: p.PermType, Platform: p.Platform, URL: p.URL, Sort: p.Sort, Children: make([]*model.PermissionTreeNode, 0), } } // 构建树 var roots []*model.PermissionTreeNode for _, p := range permissions { node := nodeMap[p.ID] if p.ParentID == nil || *p.ParentID == 0 { roots = append(roots, node) } else if parent, ok := nodeMap[*p.ParentID]; ok { parent.Children = append(parent.Children, node) } else { // 如果找不到父节点,作为根节点处理 roots = append(roots, node) } } return roots } // CheckPermission 检查用户是否拥有指定权限(实现 PermissionChecker 接口) // userID: 用户ID // permCode: 权限编码 // platform: 端口类型 (all/web/h5) func (s *Service) CheckPermission(ctx context.Context, userID uint, permCode string, platform string) (bool, error) { // 查询用户的所有权限(通过角色获取) // 1. 先获取用户的角色列表 // 2. 再获取角色的权限列表 // 3. 检查是否包含指定权限编码,并且 platform 匹配 // 注意:这个方法需要访问 AccountRoleStore 和 RolePermissionStore // 但为了避免循环依赖,我们可以: // 方案1: 在 Service 中注入这些 Store(推荐) // 方案2: 在 PermissionStore 中添加一个查询方法 // 方案3: 使用缓存层(Redis)来存储用户权限映射 // 这里先返回一个占位实现 // TODO: 实现完整的权限检查逻辑 // 需要在构造函数中注入 AccountRoleStore 和 RolePermissionStore return false, errors.New(errors.CodeInternalError, "权限检查功能尚未完全实现") }