feat: backend core - auth, user, role, permission, device, webhook, monitoring, cache, repository, service, middleware, API handlers

This commit is contained in:
2026-04-02 11:19:50 +08:00
parent e59a77bc49
commit dcc1f186f8
298 changed files with 62603 additions and 0 deletions

284
internal/service/role.go Normal file
View File

@@ -0,0 +1,284 @@
package service
import (
"context"
"errors"
"gorm.io/gorm"
"github.com/user-management-system/internal/domain"
"github.com/user-management-system/internal/repository"
)
// RoleService 角色服务
type RoleService struct {
roleRepo *repository.RoleRepository
rolePermissionRepo *repository.RolePermissionRepository
}
// NewRoleService 创建角色服务
func NewRoleService(
roleRepo *repository.RoleRepository,
rolePermissionRepo *repository.RolePermissionRepository,
) *RoleService {
return &RoleService{
roleRepo: roleRepo,
rolePermissionRepo: rolePermissionRepo,
}
}
// CreateRoleRequest 创建角色请求
type CreateRoleRequest struct {
Name string `json:"name" binding:"required"`
Code string `json:"code" binding:"required"`
Description string `json:"description"`
ParentID *int64 `json:"parent_id"`
}
// UpdateRoleRequest 更新角色请求
type UpdateRoleRequest struct {
Name string `json:"name"`
Description string `json:"description"`
ParentID *int64 `json:"parent_id"`
}
// CreateRole 创建角色
func (s *RoleService) CreateRole(ctx context.Context, req *CreateRoleRequest) (*domain.Role, error) {
// 检查角色代码是否已存在
exists, err := s.roleRepo.ExistsByCode(ctx, req.Code)
if err != nil {
return nil, err
}
if exists {
return nil, errors.New("角色代码已存在")
}
// 设置角色层级
level := 1
if req.ParentID != nil {
parentRole, err := s.roleRepo.GetByID(ctx, *req.ParentID)
if err != nil {
return nil, errors.New("父角色不存在")
}
level = parentRole.Level + 1
}
// 创建角色
role := &domain.Role{
Name: req.Name,
Code: req.Code,
Description: req.Description,
ParentID: req.ParentID,
Level: level,
Status: domain.RoleStatusEnabled,
}
if err := s.roleRepo.Create(ctx, role); err != nil {
return nil, err
}
return role, nil
}
const maxRoleDepth = 5 // 角色继承深度上限,可配置
// UpdateRole 更新角色
func (s *RoleService) UpdateRole(ctx context.Context, roleID int64, req *UpdateRoleRequest) (*domain.Role, error) {
role, err := s.roleRepo.GetByID(ctx, roleID)
if err != nil {
return nil, errors.New("角色不存在")
}
// 检查父角色是否存在
if req.ParentID != nil {
if *req.ParentID == roleID {
return nil, errors.New("不能将角色设置为自己的父角色")
}
// 检测循环继承:检查新父角色的祖先链是否包含当前角色
if err := s.checkCircularInheritance(ctx, roleID, *req.ParentID); err != nil {
return nil, err
}
// 检测继承深度:计算新父角色的深度 + 1
if err := s.checkInheritanceDepth(ctx, *req.ParentID, maxRoleDepth-1); err != nil {
return nil, err
}
role.ParentID = req.ParentID
}
// 更新字段
if req.Name != "" {
role.Name = req.Name
}
if req.Description != "" {
role.Description = req.Description
}
if err := s.roleRepo.Update(ctx, role); err != nil {
return nil, err
}
return role, nil
}
// checkCircularInheritance 检测循环继承
// 如果将 childID 的父角色设为 parentID检查 parentID 的祖先链是否包含 childID
func (s *RoleService) checkCircularInheritance(ctx context.Context, childID, parentID int64) error {
ancestorIDs, err := s.roleRepo.GetAncestorIDs(ctx, parentID)
if err != nil {
return err
}
for _, ancestorID := range ancestorIDs {
if ancestorID == childID {
return errors.New("检测到循环继承,操作被拒绝")
}
}
return nil
}
// checkInheritanceDepth 检测继承深度是否超限
func (s *RoleService) checkInheritanceDepth(ctx context.Context, roleID int64, maxDepth int) error {
if maxDepth <= 0 {
return errors.New("继承深度超限最大支持5层")
}
depth := 0
currentID := roleID
for {
role, err := s.roleRepo.GetByID(ctx, currentID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
break
}
return err
}
if role.ParentID == nil {
break
}
depth++
if depth > maxDepth {
return errors.New("继承深度超限最大支持5层")
}
currentID = *role.ParentID
}
return nil
}
// DeleteRole 删除角色
func (s *RoleService) DeleteRole(ctx context.Context, roleID int64) error {
role, err := s.roleRepo.GetByID(ctx, roleID)
if err != nil {
return errors.New("角色不存在")
}
// 系统角色不能删除
if role.IsSystem {
return errors.New("系统角色不能删除")
}
// 检查是否有子角色
children, err := s.roleRepo.ListByParentID(ctx, roleID)
if err == nil && len(children) > 0 {
return errors.New("存在子角色,无法删除")
}
// 删除角色权限关联
if err := s.rolePermissionRepo.DeleteByRoleID(ctx, roleID); err != nil {
return err
}
// 删除角色
return s.roleRepo.Delete(ctx, roleID)
}
// GetRole 获取角色信息
func (s *RoleService) GetRole(ctx context.Context, roleID int64) (*domain.Role, error) {
return s.roleRepo.GetByID(ctx, roleID)
}
// ListRoles 获取角色列表
type ListRoleRequest struct {
Page int `json:"page"`
PageSize int `json:"page_size"`
Status int `json:"status"`
Keyword string `json:"keyword"`
}
func (s *RoleService) ListRoles(ctx context.Context, req *ListRoleRequest) ([]*domain.Role, int64, error) {
if req.Page <= 0 {
req.Page = 1
}
if req.PageSize <= 0 {
req.PageSize = 20
}
offset := (req.Page - 1) * req.PageSize
if req.Keyword != "" {
return s.roleRepo.Search(ctx, req.Keyword, offset, req.PageSize)
}
// Status > 0 表示按状态过滤0 表示不过滤(查全部)
if req.Status > 0 {
return s.roleRepo.ListByStatus(ctx, domain.RoleStatus(req.Status), offset, req.PageSize)
}
return s.roleRepo.List(ctx, offset, req.PageSize)
}
// UpdateRoleStatus 更新角色状态
func (s *RoleService) UpdateRoleStatus(ctx context.Context, roleID int64, status domain.RoleStatus) error {
role, err := s.roleRepo.GetByID(ctx, roleID)
if err != nil {
return errors.New("角色不存在")
}
// 系统角色不能禁用
if role.IsSystem && status == domain.RoleStatusDisabled {
return errors.New("系统角色不能禁用")
}
return s.roleRepo.UpdateStatus(ctx, roleID, status)
}
// GetRolePermissions 获取角色权限(包含继承的父角色权限)
func (s *RoleService) GetRolePermissions(ctx context.Context, roleID int64) ([]*domain.Permission, error) {
// 收集所有角色ID包括当前角色和所有父角色
allRoleIDs := []int64{roleID}
ancestorIDs, err := s.roleRepo.GetAncestorIDs(ctx, roleID)
if err != nil {
return nil, err
}
allRoleIDs = append(allRoleIDs, ancestorIDs...)
// 批量获取所有角色的权限ID
permissionIDs, err := s.rolePermissionRepo.GetPermissionIDsByRoleIDs(ctx, allRoleIDs)
if err != nil {
return nil, err
}
// 批量获取权限详情
permissions, err := s.rolePermissionRepo.GetPermissionsByIDs(ctx, permissionIDs)
if err != nil {
return nil, err
}
return permissions, nil
}
// AssignPermissions 分配权限
func (s *RoleService) AssignPermissions(ctx context.Context, roleID int64, permissionIDs []int64) error {
// 删除原有权限
if err := s.rolePermissionRepo.DeleteByRoleID(ctx, roleID); err != nil {
return err
}
// 创建新权限关联
var rolePermissions []*domain.RolePermission
for _, permissionID := range permissionIDs {
rolePermissions = append(rolePermissions, &domain.RolePermission{
RoleID: roleID,
PermissionID: permissionID,
})
}
return s.rolePermissionRepo.BatchCreate(ctx, rolePermissions)
}