Files
junhong_cmp_fiber/internal/service/permission/service.go
huang ad946af5ee add: 提交部分表设计
update: 1.所有model嵌入gorm公用model 2.所有model嵌入BaseModel
2025-12-15 11:32:33 +08:00

245 lines
6.7 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 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,
URL: req.URL,
ParentID: req.ParentID,
Sort: req.Sort,
Status: constants.StatusEnabled,
}
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.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.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,
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
}