Browse Source

准备前后台同步修改前暂存

master
hejl 8 hours ago
parent
commit
ca01dcf0d1
  1. 27
      gofaster/backend/internal/auth/controller/menus_controller.go
  2. 27
      gofaster/backend/internal/auth/controller/permission_controller.go
  3. 20
      gofaster/backend/internal/auth/model/auth_resources.go
  4. 15
      gofaster/backend/internal/auth/model/menus.go
  5. 14
      gofaster/backend/internal/auth/model/permission.go
  6. 6
      gofaster/backend/internal/auth/module.go
  7. 26
      gofaster/backend/internal/auth/repository/auth_resources_repo.go
  8. 7
      gofaster/backend/internal/auth/repository/menus_repo.go
  9. 36
      gofaster/backend/internal/auth/repository/permission_repo.go
  10. 17
      gofaster/backend/internal/auth/routes/menus_routes.go
  11. 13
      gofaster/backend/internal/auth/routes/permission_routes.go
  12. 95
      gofaster/backend/internal/auth/service/auth_resources_service.go
  13. 67
      gofaster/backend/internal/auth/service/menus_service.go
  14. 5
      gofaster/backend/internal/auth/service/permission_service.go
  15. 178
      gofaster/backend/internal/auth/service/permission_sync_service.go
  16. BIN
      gofaster/backend/main.exe

27
gofaster/backend/internal/auth/controller/menus_controller.go

@ -147,6 +147,33 @@ func (c *MenusController) GetMenusByModule(ctx *gin.Context) { @@ -147,6 +147,33 @@ func (c *MenusController) GetMenusByModule(ctx *gin.Context) {
response.Success(ctx, "根据模块获取菜单成功", menus)
}
// GetMenusByMenuGroupID 根据菜单分组ID获取菜单
// @Summary 根据菜单分组ID获取菜单
// @Description 根据菜单分组ID获取菜单列表
// @Tags 菜单
// @Produce json
// @Param menuGroupId path int true "菜单分组ID"
// @Success 200 {object} response.Response
// @Router /api/menus/by-menu-group/{menuGroupId} [get]
func (c *MenusController) GetMenusByMenuGroupID(ctx *gin.Context) {
idStr := ctx.Param("menuGroupId")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
c.logger.Error("解析菜单分组ID失败", zap.Error(err))
response.Error(ctx, http.StatusBadRequest, "无效的菜单分组ID", err.Error())
return
}
menus, err := c.menusService.GetMenusByMenuGroupID(uint(id))
if err != nil {
c.logger.Error("根据菜单分组ID获取菜单失败", zap.Error(err))
response.Error(ctx, http.StatusInternalServerError, "根据菜单分组ID获取菜单失败", err.Error())
return
}
response.Success(ctx, "根据菜单分组ID获取菜单成功", menus)
}
// GetRouteRelations 获取路由关联关系
// @Summary 获取路由关联关系
// @Description 获取菜单与后台路由的关联关系

27
gofaster/backend/internal/auth/controller/permission_controller.go

@ -168,6 +168,33 @@ func (c *PermissionController) GetPermissionsByMenuGroupID(ctx *gin.Context) { @@ -168,6 +168,33 @@ func (c *PermissionController) GetPermissionsByMenuGroupID(ctx *gin.Context) {
response.Success(ctx, "获取权限成功", permissions)
}
// GetPermissionsByAuthResourceID 根据认证资源ID获取权限
// @Summary 根据认证资源ID获取权限
// @Description 根据认证资源ID获取相关权限
// @Tags 权限管理
// @Accept json
// @Produce json
// @Param authResourceId path int true "认证资源ID"
// @Success 200 {object} response.Response{data=[]model.Permission}
// @Failure 400 {object} response.Response
// @Router /api/auth/permissions/auth-resource/{authResourceId} [get]
func (c *PermissionController) GetPermissionsByAuthResourceID(ctx *gin.Context) {
idStr := ctx.Param("authResourceId")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.Error(ctx, http.StatusBadRequest, "无效的认证资源ID", err.Error())
return
}
permissions, err := c.permissionService.GetPermissionsByAuthResourceID(ctx.Request.Context(), uint(id))
if err != nil {
response.Error(ctx, http.StatusInternalServerError, "获取权限失败", err.Error())
return
}
response.Success(ctx, "获取权限成功", permissions)
}
// GetUserPermissions 获取用户权限
// @Summary 获取用户权限
// @Description 根据用户ID获取用户的所有权限

20
gofaster/backend/internal/auth/model/auth_resources.go

@ -6,16 +6,16 @@ import ( @@ -6,16 +6,16 @@ import (
// AuthResources 认证资源模型(原前后台路由关系模型)
type AuthResources struct {
ID uint `gorm:"primarykey" json:"id"`
UpdatedAt time.Time `json:"updated_at"`
FrontendRouteID uint `gorm:"uniqueIndex:idx_auth_resources_unique" json:"frontend_route_id"` // 前台路由ID
BackendRoute string `gorm:"uniqueIndex:idx_auth_resources_unique" json:"backend_route"` // 后台API路径
HTTPMethod string `json:"http_method"` // HTTP方法
Component string `json:"component"` // 前端组件名称
Module string `json:"module"` // 所属模块
Description string `json:"description"` // 描述
Sort int `gorm:"default:0" json:"sort"` // 排序
Status int `gorm:"default:1" json:"status"` // 状态:1-启用,0-禁用
ID uint `gorm:"primarykey" json:"id"`
UpdatedAt time.Time `json:"updated_at"`
MenuID uint `gorm:"uniqueIndex:idx_auth_resources_unique" json:"menu_id"` // 菜单ID
BackendRoute string `gorm:"uniqueIndex:idx_auth_resources_unique" json:"backend_route"` // 后台API路径
HTTPMethod string `json:"http_method"` // HTTP方法
Component string `json:"component"` // 前端组件名称
Module string `json:"module"` // 所属模块
Description string `json:"description"` // 描述
Sort int `gorm:"default:0" json:"sort"` // 排序
Status int `gorm:"default:1" json:"status"` // 状态:1-启用,0-禁用
}
// TableName 指定表名

15
gofaster/backend/internal/auth/model/menus.go

@ -8,13 +8,14 @@ import ( @@ -8,13 +8,14 @@ import (
type Menus struct {
ID uint `gorm:"primarykey" json:"id"`
UpdatedAt time.Time `json:"updated_at"`
Path string `json:"path"` // 前台路由路径
Name string `json:"name"` // 路由名称
Component string `json:"component"` // 组件名称
Module string `json:"module"` // 所属模块
Description string `json:"description"` // 描述
Sort int `gorm:"default:0" json:"sort"` // 排序
Status int `gorm:"default:1" json:"status"` // 状态:1-启用,0-禁用
Path string `json:"path"` // 前台路由路径
Name string `json:"name"` // 路由名称
Component string `json:"component"` // 组件名称
Module string `json:"module"` // 所属模块
MenuGroupID *uint `gorm:"index" json:"menu_group_id"` // 菜单分组ID
Description string `json:"description"` // 描述
Sort int `gorm:"default:0" json:"sort"` // 排序
Status int `gorm:"default:1" json:"status"` // 状态:1-启用,0-禁用
}
// TableName 指定表名

14
gofaster/backend/internal/auth/model/permission.go

@ -1,13 +1,15 @@ @@ -1,13 +1,15 @@
package model
import (
"gofaster/internal/shared/model"
"time"
)
type Permission struct {
model.BaseModel
Description string `gorm:"size:200" json:"description"` // 权限描述
BackendRoute string `gorm:"size:200" json:"backend_route"` // 后端路由
FrontendRouteID *uint `gorm:"index" json:"frontend_route_id"` // 前端路由ID
MenuGroupID *uint `gorm:"index" json:"menu_group_id"` // 菜单分组ID
ID uint `gorm:"primarykey" json:"id"`
UpdatedAt time.Time `json:"updated_at"`
Name string `gorm:"size:100;not null" json:"name"` // 权限名称
Description string `gorm:"size:200" json:"description"` // 权限描述
AuthResourceID *uint `gorm:"index" json:"auth_resource_id"` // 认证资源ID
MenuID *uint `gorm:"index" json:"menu_id"` // 菜单ID
MenuGroupID *uint `gorm:"index" json:"menu_group_id"` // 菜单分组ID
}

6
gofaster/backend/internal/auth/module.go

@ -68,6 +68,10 @@ func (m *Module) Init(cfg *config.Config, logger *zap.Logger, db *gorm.DB, redis @@ -68,6 +68,10 @@ func (m *Module) Init(cfg *config.Config, logger *zap.Logger, db *gorm.DB, redis
menuGroupRepo := repository.NewMenuGroupRepository(db)
frontendRouteRepo := repository.NewMenusRepository(db)
authResourcesRepo := repository.NewAuthResourcesRepository(db)
permissionRepo := repository.NewPermissionRepository(db)
// 初始化同步服务
permissionSyncService := service.NewPermissionSyncService(permissionRepo, frontendRouteRepo, authResourcesRepo, logger)
// 初始化服务
userService := service.NewUserService(userRepo, db)
@ -80,7 +84,7 @@ func (m *Module) Init(cfg *config.Config, logger *zap.Logger, db *gorm.DB, redis @@ -80,7 +84,7 @@ func (m *Module) Init(cfg *config.Config, logger *zap.Logger, db *gorm.DB, redis
passwordResetRepo,
)
menuGroupService := service.NewMenuGroupService(menuGroupRepo, logger)
menusService := service.NewMenusService(frontendRouteRepo, authResourcesRepo, logger)
menusService := service.NewMenusService(frontendRouteRepo, authResourcesRepo, permissionSyncService, logger)
m.routeSyncService = service.NewRouteSyncService(authResourcesRepo, logger)
// 初始化控制器

26
gofaster/backend/internal/auth/repository/auth_resources_repo.go

@ -31,10 +31,10 @@ func (r *AuthResourcesRepository) FindByID(id uint) (*model.AuthResources, error @@ -31,10 +31,10 @@ func (r *AuthResourcesRepository) FindByID(id uint) (*model.AuthResources, error
return &resource, nil
}
// FindByFrontendRouteID 根据前台路由ID查找资源
func (r *AuthResourcesRepository) FindByFrontendRouteID(frontendRouteID uint) ([]*model.AuthResources, error) {
// FindByMenuID 根据菜单ID查找资源
func (r *AuthResourcesRepository) FindByMenuID(menuID uint) ([]*model.AuthResources, error) {
var resources []*model.AuthResources
err := r.db.Where("frontend_route_id = ?", frontendRouteID).Order("sort ASC").Find(&resources).Error
err := r.db.Where("menu_id = ?", menuID).Order("sort ASC").Find(&resources).Error
return resources, err
}
@ -76,9 +76,9 @@ func (r *AuthResourcesRepository) Delete(id uint) error { @@ -76,9 +76,9 @@ func (r *AuthResourcesRepository) Delete(id uint) error {
return r.db.Delete(&model.AuthResources{}, id).Error
}
// DeleteByFrontendRouteID 根据前台路由ID删除资源
func (r *AuthResourcesRepository) DeleteByFrontendRouteID(frontendRouteID uint) error {
return r.db.Where("frontend_route_id = ?", frontendRouteID).Delete(&model.AuthResources{}).Error
// DeleteByMenuID 根据菜单ID删除资源
func (r *AuthResourcesRepository) DeleteByMenuID(menuID uint) error {
return r.db.Where("menu_id = ?", menuID).Delete(&model.AuthResources{}).Error
}
// Upsert 更新或插入认证资源
@ -86,9 +86,9 @@ func (r *AuthResourcesRepository) Upsert(resource *model.AuthResources) error { @@ -86,9 +86,9 @@ func (r *AuthResourcesRepository) Upsert(resource *model.AuthResources) error {
// 使用 PostgreSQL 的 ON CONFLICT 语法处理唯一索引冲突
sql := `
INSERT INTO auth_resources
(frontend_route_id, backend_route, http_method, component, module, description, sort, status, updated_at)
(menu_id, backend_route, http_method, component, module, description, sort, status, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())
ON CONFLICT (frontend_route_id, backend_route)
ON CONFLICT (menu_id, backend_route)
DO UPDATE SET
http_method = EXCLUDED.http_method,
component = EXCLUDED.component,
@ -102,7 +102,7 @@ func (r *AuthResourcesRepository) Upsert(resource *model.AuthResources) error { @@ -102,7 +102,7 @@ func (r *AuthResourcesRepository) Upsert(resource *model.AuthResources) error {
var id uint
err := r.db.Raw(sql,
resource.FrontendRouteID,
resource.MenuID,
resource.BackendRoute,
resource.HTTPMethod,
resource.Component,
@ -158,12 +158,12 @@ func (r *AuthResourcesRepository) GetStats() (map[string]interface{}, error) { @@ -158,12 +158,12 @@ func (r *AuthResourcesRepository) GetStats() (map[string]interface{}, error) {
}, nil
}
// GetWithFrontendRoute 获取资源并包含前台路由信息
func (r *AuthResourcesRepository) GetWithFrontendRoute() ([]map[string]interface{}, error) {
// GetWithMenu 获取资源并包含菜单信息
func (r *AuthResourcesRepository) GetWithMenu() ([]map[string]interface{}, error) {
var results []map[string]interface{}
err := r.db.Table("auth_resources").
Select("auth_resources.*, menus.path as frontend_path, menus.name as frontend_name").
Joins("LEFT JOIN menus ON auth_resources.frontend_route_id = menus.id").
Select("auth_resources.*, menus.path as menu_path, menus.name as menu_name").
Joins("LEFT JOIN menus ON auth_resources.menu_id = menus.id").
Order("auth_resources.sort ASC").
Scan(&results).Error
return results, err

7
gofaster/backend/internal/auth/repository/menus_repo.go

@ -48,6 +48,13 @@ func (r *MenusRepository) FindByModule(module string) ([]*model.Menus, error) { @@ -48,6 +48,13 @@ func (r *MenusRepository) FindByModule(module string) ([]*model.Menus, error) {
return routes, err
}
// FindByMenuGroupID 根据菜单分组ID查找前台路由
func (r *MenusRepository) FindByMenuGroupID(menuGroupID uint) ([]*model.Menus, error) {
var routes []*model.Menus
err := r.db.Where("menu_group_id = ?", menuGroupID).Order("sort ASC").Find(&routes).Error
return routes, err
}
// List 获取前台路由列表
func (r *MenusRepository) List() ([]*model.Menus, error) {
var routes []*model.Menus

36
gofaster/backend/internal/auth/repository/permission_repo.go

@ -9,11 +9,15 @@ import ( @@ -9,11 +9,15 @@ import (
)
type PermissionRepository interface {
Create(ctx context.Context, permission *model.Permission) error
Update(ctx context.Context, permission *model.Permission) error
Delete(ctx context.Context, id uint) error
GetByID(ctx context.Context, id uint) (*model.Permission, error)
List(ctx context.Context, offset, limit int) ([]*model.Permission, int64, error)
GetByBackendRoute(ctx context.Context, backendRoute string) ([]*model.Permission, error)
GetByMenuID(ctx context.Context, menuID uint) ([]*model.Permission, error)
GetByMenuGroupID(ctx context.Context, menuGroupID uint) ([]*model.Permission, error)
GetByAuthResourceID(ctx context.Context, authResourceID uint) ([]*model.Permission, error)
GetByUserID(ctx context.Context, userID uint) ([]*model.Permission, error)
}
@ -58,7 +62,11 @@ func (r *permissionRepository) List(ctx context.Context, offset, limit int) ([]* @@ -58,7 +62,11 @@ func (r *permissionRepository) List(ctx context.Context, offset, limit int) ([]*
func (r *permissionRepository) GetByBackendRoute(ctx context.Context, backendRoute string) ([]*model.Permission, error) {
var permissions []*model.Permission
err := r.DB().WithContext(ctx).Where("backend_route = ?", backendRoute).Find(&permissions).Error
// 通过auth_resources表关联查询
err := r.DB().WithContext(ctx).
Joins("JOIN auth_resources ON permissions.auth_resource_id = auth_resources.id").
Where("auth_resources.backend_route = ?", backendRoute).
Find(&permissions).Error
if err != nil {
return nil, err
}
@ -67,7 +75,7 @@ func (r *permissionRepository) GetByBackendRoute(ctx context.Context, backendRou @@ -67,7 +75,7 @@ func (r *permissionRepository) GetByBackendRoute(ctx context.Context, backendRou
func (r *permissionRepository) GetByMenuID(ctx context.Context, menuID uint) ([]*model.Permission, error) {
var permissions []*model.Permission
err := r.DB().WithContext(ctx).Where("frontend_route_id = ?", menuID).Find(&permissions).Error
err := r.DB().WithContext(ctx).Where("menu_id = ?", menuID).Find(&permissions).Error
if err != nil {
return nil, err
}
@ -83,6 +91,15 @@ func (r *permissionRepository) GetByMenuGroupID(ctx context.Context, menuGroupID @@ -83,6 +91,15 @@ func (r *permissionRepository) GetByMenuGroupID(ctx context.Context, menuGroupID
return permissions, nil
}
func (r *permissionRepository) GetByAuthResourceID(ctx context.Context, authResourceID uint) ([]*model.Permission, error) {
var permissions []*model.Permission
err := r.DB().WithContext(ctx).Where("auth_resource_id = ?", authResourceID).Find(&permissions).Error
if err != nil {
return nil, err
}
return permissions, nil
}
func (r *permissionRepository) GetByUserID(ctx context.Context, userID uint) ([]*model.Permission, error) {
var permissions []*model.Permission
@ -100,3 +117,18 @@ func (r *permissionRepository) GetByUserID(ctx context.Context, userID uint) ([] @@ -100,3 +117,18 @@ func (r *permissionRepository) GetByUserID(ctx context.Context, userID uint) ([]
return permissions, nil
}
// Create 创建权限
func (r *permissionRepository) Create(ctx context.Context, permission *model.Permission) error {
return r.DB().WithContext(ctx).Create(permission).Error
}
// Update 更新权限
func (r *permissionRepository) Update(ctx context.Context, permission *model.Permission) error {
return r.DB().WithContext(ctx).Save(permission).Error
}
// Delete 删除权限
func (r *permissionRepository) Delete(ctx context.Context, id uint) error {
return r.DB().WithContext(ctx).Delete(&model.Permission{}, id).Error
}

17
gofaster/backend/internal/auth/routes/menus_routes.go

@ -15,7 +15,9 @@ func RegisterMenusRoutes(router *gin.RouterGroup, db *gorm.DB, logger *zap.Logge @@ -15,7 +15,9 @@ func RegisterMenusRoutes(router *gin.RouterGroup, db *gorm.DB, logger *zap.Logge
// 初始化依赖
menusRepo := repository.NewMenusRepository(db)
authResourcesRepo := repository.NewAuthResourcesRepository(db)
menusService := service.NewMenusService(menusRepo, authResourcesRepo, logger)
permissionRepo := repository.NewPermissionRepository(db)
permissionSyncService := service.NewPermissionSyncService(permissionRepo, menusRepo, authResourcesRepo, logger)
menusService := service.NewMenusService(menusRepo, authResourcesRepo, permissionSyncService, logger)
menusController := controller.NewMenusController(menusService, logger)
// 菜单路由组
@ -29,12 +31,13 @@ func RegisterMenusRoutes(router *gin.RouterGroup, db *gorm.DB, logger *zap.Logge @@ -29,12 +31,13 @@ func RegisterMenusRoutes(router *gin.RouterGroup, db *gorm.DB, logger *zap.Logge
// 菜单查询(需要认证)
{
menusGroup.GET("", menusController.GetMenus) // 获取菜单列表
menusGroup.GET("/:id", menusController.GetMenuByID) // 根据ID获取菜单
menusGroup.GET("/by-module", menusController.GetMenusByModule) // 根据模块获取菜单
menusGroup.GET("/relations", menusController.GetRouteRelations) // 获取路由关联关系
menusGroup.GET("/:id/relations", menusController.GetRouteRelationsByMenuID) // 根据菜单ID获取关联关系
menusGroup.GET("/stats", menusController.GetStats) // 获取统计信息
menusGroup.GET("", menusController.GetMenus) // 获取菜单列表
menusGroup.GET("/:id", menusController.GetMenuByID) // 根据ID获取菜单
menusGroup.GET("/by-module", menusController.GetMenusByModule) // 根据模块获取菜单
menusGroup.GET("/by-menu-group/:menuGroupId", menusController.GetMenusByMenuGroupID) // 根据菜单分组ID获取菜单
menusGroup.GET("/relations", menusController.GetRouteRelations) // 获取路由关联关系
menusGroup.GET("/:id/relations", menusController.GetRouteRelationsByMenuID) // 根据菜单ID获取关联关系
menusGroup.GET("/stats", menusController.GetStats) // 获取统计信息
}
}
}

13
gofaster/backend/internal/auth/routes/permission_routes.go

@ -23,12 +23,13 @@ func RegisterPermissionRoutes(router *gin.RouterGroup, db *gorm.DB, jwtSecret st @@ -23,12 +23,13 @@ func RegisterPermissionRoutes(router *gin.RouterGroup, db *gorm.DB, jwtSecret st
permissionGroup.Use(middleware.JWTAuth()) // 暂时只检查JWT,不检查权限
{
// 权限查询操作
permissionGroup.GET("", permissionController.ListPermissions) // 获取权限列表
permissionGroup.GET("/:id", permissionController.GetPermission) // 获取权限详情
permissionGroup.GET("/backend-route", permissionController.GetPermissionsByBackendRoute) // 根据后端路由获取权限
permissionGroup.GET("/menu/:menuId", permissionController.GetPermissionsByMenuID) // 根据菜单ID获取权限
permissionGroup.GET("/menu-group/:menuGroupId", permissionController.GetPermissionsByMenuGroupID) // 根据菜单分组ID获取权限
permissionGroup.GET("/user/:userId", permissionController.GetUserPermissions) // 获取用户权限
permissionGroup.GET("", permissionController.ListPermissions) // 获取权限列表
permissionGroup.GET("/:id", permissionController.GetPermission) // 获取权限详情
permissionGroup.GET("/backend-route", permissionController.GetPermissionsByBackendRoute) // 根据后端路由获取权限
permissionGroup.GET("/menu/:menuId", permissionController.GetPermissionsByMenuID) // 根据菜单ID获取权限
permissionGroup.GET("/menu-group/:menuGroupId", permissionController.GetPermissionsByMenuGroupID) // 根据菜单分组ID获取权限
permissionGroup.GET("/auth-resource/:authResourceId", permissionController.GetPermissionsByAuthResourceID) // 根据认证资源ID获取权限
permissionGroup.GET("/user/:userId", permissionController.GetUserPermissions) // 获取用户权限
}
}
}

95
gofaster/backend/internal/auth/service/auth_resources_service.go

@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
package service
import (
"fmt"
"gofaster/internal/auth/model"
"gofaster/internal/auth/repository"
"go.uber.org/zap"
)
// AuthResourcesService 认证资源服务
type AuthResourcesService struct {
authResourcesRepo *repository.AuthResourcesRepository
permissionSyncService *PermissionSyncService
logger *zap.Logger
}
// NewAuthResourcesService 创建认证资源服务实例
func NewAuthResourcesService(
authResourcesRepo *repository.AuthResourcesRepository,
permissionSyncService *PermissionSyncService,
logger *zap.Logger,
) *AuthResourcesService {
return &AuthResourcesService{
authResourcesRepo: authResourcesRepo,
permissionSyncService: permissionSyncService,
logger: logger,
}
}
// CreateAuthResource 创建认证资源并同步权限
func (s *AuthResourcesService) CreateAuthResource(resource *model.AuthResources) error {
// 创建认证资源
if err := s.authResourcesRepo.Create(resource); err != nil {
s.logger.Error("创建认证资源失败", zap.Error(err))
return fmt.Errorf("创建认证资源失败: %w", err)
}
// 同步创建权限
if err := s.permissionSyncService.SyncPermissionForAuthResource(resource, "create"); err != nil {
s.logger.Error("同步创建权限失败", zap.Error(err), zap.Uint("authResourceID", resource.ID))
// 注意:这里可以选择回滚认证资源的创建,或者记录错误继续执行
// 为了简化,这里只记录错误
}
return nil
}
// UpdateAuthResource 更新认证资源并同步权限
func (s *AuthResourcesService) UpdateAuthResource(resource *model.AuthResources) error {
// 更新认证资源
if err := s.authResourcesRepo.Update(resource); err != nil {
s.logger.Error("更新认证资源失败", zap.Error(err))
return fmt.Errorf("更新认证资源失败: %w", err)
}
// 同步更新权限
if err := s.permissionSyncService.SyncPermissionForAuthResource(resource, "update"); err != nil {
s.logger.Error("同步更新权限失败", zap.Error(err), zap.Uint("authResourceID", resource.ID))
// 注意:这里可以选择回滚认证资源的更新,或者记录错误继续执行
}
return nil
}
// DeleteAuthResource 删除认证资源并同步权限
func (s *AuthResourcesService) DeleteAuthResource(id uint) error {
// 先同步删除权限
if err := s.permissionSyncService.SyncPermissionForAuthResource(&model.AuthResources{ID: id}, "delete"); err != nil {
s.logger.Error("同步删除权限失败", zap.Error(err), zap.Uint("authResourceID", id))
// 注意:这里可以选择不删除认证资源,或者记录错误继续执行
}
// 删除认证资源
if err := s.authResourcesRepo.Delete(id); err != nil {
s.logger.Error("删除认证资源失败", zap.Error(err))
return fmt.Errorf("删除认证资源失败: %w", err)
}
return nil
}
// UpsertAuthResource 更新或插入认证资源并同步权限
func (s *AuthResourcesService) UpsertAuthResource(resource *model.AuthResources) error {
// 检查资源是否已存在
existingResource, err := s.authResourcesRepo.FindByID(resource.ID)
if err != nil {
// 如果不存在,则创建
return s.CreateAuthResource(resource)
} else {
// 如果存在,则更新
resource.ID = existingResource.ID
return s.UpdateAuthResource(resource)
}
}

67
gofaster/backend/internal/auth/service/menus_service.go

@ -10,21 +10,24 @@ import ( @@ -10,21 +10,24 @@ import (
// MenusService 菜单服务
type MenusService struct {
menusRepo *repository.MenusRepository
authResourcesRepo *repository.AuthResourcesRepository
logger *zap.Logger
menusRepo *repository.MenusRepository
authResourcesRepo *repository.AuthResourcesRepository
permissionSyncService *PermissionSyncService
logger *zap.Logger
}
// NewMenusService 创建菜单服务实例
func NewMenusService(
menusRepo *repository.MenusRepository,
authResourcesRepo *repository.AuthResourcesRepository,
permissionSyncService *PermissionSyncService,
logger *zap.Logger,
) *MenusService {
return &MenusService{
menusRepo: menusRepo,
authResourcesRepo: authResourcesRepo,
logger: logger,
menusRepo: menusRepo,
authResourcesRepo: authResourcesRepo,
permissionSyncService: permissionSyncService,
logger: logger,
}
}
@ -58,7 +61,7 @@ func (s *MenusService) SyncMenu(menuData map[string]interface{}) error { @@ -58,7 +61,7 @@ func (s *MenusService) SyncMenu(menuData map[string]interface{}) error {
// 3. 处理后台路由关联
if backendRoutes, ok := menuData["backend_routes"].([]interface{}); ok {
// 先删除现有的关联
if err := s.authResourcesRepo.DeleteByFrontendRouteID(existingMenu.ID); err != nil {
if err := s.authResourcesRepo.DeleteByMenuID(existingMenu.ID); err != nil {
s.logger.Error("删除现有关联失败", zap.Error(err))
return fmt.Errorf("删除现有关联失败: %w", err)
}
@ -67,14 +70,14 @@ func (s *MenusService) SyncMenu(menuData map[string]interface{}) error { @@ -67,14 +70,14 @@ func (s *MenusService) SyncMenu(menuData map[string]interface{}) error {
for i, backendRouteData := range backendRoutes {
backendRoute := backendRouteData.(map[string]interface{})
relation := &model.AuthResources{
FrontendRouteID: existingMenu.ID,
BackendRoute: backendRoute["backend_route"].(string),
HTTPMethod: backendRoute["http_method"].(string),
Component: menuData["component"].(string), // 使用菜单的组件名称
Module: backendRoute["module"].(string),
Description: backendRoute["description"].(string),
Sort: i,
Status: 1,
MenuID: existingMenu.ID,
BackendRoute: backendRoute["backend_route"].(string),
HTTPMethod: backendRoute["http_method"].(string),
Component: menuData["component"].(string), // 使用菜单的组件名称
Module: backendRoute["module"].(string),
Description: backendRoute["description"].(string),
Sort: i,
Status: 1,
}
if err := s.authResourcesRepo.Upsert(relation); err != nil {
@ -126,14 +129,44 @@ func (s *MenusService) GetMenusByModule(module string) ([]*model.Menus, error) { @@ -126,14 +129,44 @@ func (s *MenusService) GetMenusByModule(module string) ([]*model.Menus, error) {
return s.menusRepo.FindByModule(module)
}
// GetMenusByMenuGroupID 根据菜单分组ID获取菜单
func (s *MenusService) GetMenusByMenuGroupID(menuGroupID uint) ([]*model.Menus, error) {
return s.menusRepo.FindByMenuGroupID(menuGroupID)
}
// UpdateMenuGroupID 更新菜单的分组ID并同步权限
func (s *MenusService) UpdateMenuGroupID(menuID uint, newMenuGroupID *uint) error {
// 获取当前菜单信息
menu, err := s.menusRepo.FindByID(menuID)
if err != nil {
s.logger.Error("查找菜单失败", zap.Error(err), zap.Uint("menuID", menuID))
return fmt.Errorf("查找菜单失败: %w", err)
}
// 更新菜单的分组ID
menu.MenuGroupID = newMenuGroupID
if err := s.menusRepo.Update(menu); err != nil {
s.logger.Error("更新菜单分组ID失败", zap.Error(err), zap.Uint("menuID", menuID))
return fmt.Errorf("更新菜单分组ID失败: %w", err)
}
// 同步更新相关权限的MenuGroupID
if err := s.permissionSyncService.SyncPermissionForMenuGroupChange(menuID, newMenuGroupID); err != nil {
s.logger.Error("同步权限的菜单分组ID失败", zap.Error(err), zap.Uint("menuID", menuID))
// 注意:这里可以选择回滚菜单的更新,或者记录错误继续执行
}
return nil
}
// GetRouteRelations 获取路由关联关系
func (s *MenusService) GetRouteRelations() ([]map[string]interface{}, error) {
return s.authResourcesRepo.GetWithFrontendRoute()
return s.authResourcesRepo.GetWithMenu()
}
// GetRouteRelationsByMenuID 根据菜单ID获取关联关系
func (s *MenusService) GetRouteRelationsByMenuID(menuID uint) ([]*model.AuthResources, error) {
return s.authResourcesRepo.FindByFrontendRouteID(menuID)
return s.authResourcesRepo.FindByMenuID(menuID)
}
// GetStats 获取统计信息

5
gofaster/backend/internal/auth/service/permission_service.go

@ -41,6 +41,11 @@ func (s *PermissionService) GetPermissionsByMenuGroupID(ctx context.Context, men @@ -41,6 +41,11 @@ func (s *PermissionService) GetPermissionsByMenuGroupID(ctx context.Context, men
return s.permissionRepo.GetByMenuGroupID(ctx, menuGroupID)
}
// GetPermissionsByAuthResourceID 根据认证资源ID获取权限
func (s *PermissionService) GetPermissionsByAuthResourceID(ctx context.Context, authResourceID uint) ([]*model.Permission, error) {
return s.permissionRepo.GetByAuthResourceID(ctx, authResourceID)
}
// GetUserPermissions 获取用户权限
func (s *PermissionService) GetUserPermissions(ctx context.Context, userID uint) ([]*model.Permission, error) {
return s.permissionRepo.GetByUserID(ctx, userID)

178
gofaster/backend/internal/auth/service/permission_sync_service.go

@ -0,0 +1,178 @@ @@ -0,0 +1,178 @@
package service
import (
"fmt"
"gofaster/internal/auth/model"
"gofaster/internal/auth/repository"
"go.uber.org/zap"
)
// PermissionSyncService 权限同步服务
type PermissionSyncService struct {
permissionRepo repository.PermissionRepository
menusRepo *repository.MenusRepository
authResourcesRepo *repository.AuthResourcesRepository
logger *zap.Logger
}
// NewPermissionSyncService 创建权限同步服务实例
func NewPermissionSyncService(
permissionRepo repository.PermissionRepository,
menusRepo *repository.MenusRepository,
authResourcesRepo *repository.AuthResourcesRepository,
logger *zap.Logger,
) *PermissionSyncService {
return &PermissionSyncService{
permissionRepo: permissionRepo,
menusRepo: menusRepo,
authResourcesRepo: authResourcesRepo,
logger: logger,
}
}
// SyncPermissionForAuthResource 为认证资源同步权限
func (s *PermissionSyncService) SyncPermissionForAuthResource(authResource *model.AuthResources, operation string) error {
switch operation {
case "create":
return s.createPermissionForAuthResource(authResource)
case "update":
return s.updatePermissionForAuthResource(authResource)
case "delete":
return s.deletePermissionForAuthResource(authResource.ID)
default:
return fmt.Errorf("不支持的操作类型: %s", operation)
}
}
// createPermissionForAuthResource 为认证资源创建权限
func (s *PermissionSyncService) createPermissionForAuthResource(authResource *model.AuthResources) error {
// 获取菜单信息以获取MenuGroupID
menu, err := s.menusRepo.FindByID(authResource.MenuID)
if err != nil {
s.logger.Error("查找菜单失败", zap.Error(err), zap.Uint("menuID", authResource.MenuID))
return fmt.Errorf("查找菜单失败: %w", err)
}
// 创建权限记录
permission := &model.Permission{
Name: fmt.Sprintf("%s-%s", authResource.Component, authResource.HTTPMethod),
Description: fmt.Sprintf("%s %s 权限", authResource.HTTPMethod, authResource.BackendRoute),
AuthResourceID: &authResource.ID,
MenuID: &authResource.MenuID,
MenuGroupID: menu.MenuGroupID,
}
// 创建权限记录
if err := s.permissionRepo.Create(nil, permission); err != nil {
s.logger.Error("创建权限记录失败", zap.Error(err), zap.Uint("authResourceID", authResource.ID))
return fmt.Errorf("创建权限记录失败: %w", err)
}
s.logger.Info("创建权限记录成功",
zap.Uint("authResourceID", authResource.ID),
zap.Uint("menuID", authResource.MenuID),
zap.Any("menuGroupID", menu.MenuGroupID))
return nil
}
// updatePermissionForAuthResource 更新认证资源对应的权限
func (s *PermissionSyncService) updatePermissionForAuthResource(authResource *model.AuthResources) error {
// 获取菜单信息以获取MenuGroupID
menu, err := s.menusRepo.FindByID(authResource.MenuID)
if err != nil {
s.logger.Error("查找菜单失败", zap.Error(err), zap.Uint("menuID", authResource.MenuID))
return fmt.Errorf("查找菜单失败: %w", err)
}
// 查找对应的权限记录
permissions, err := s.permissionRepo.GetByAuthResourceID(nil, authResource.ID)
if err != nil {
s.logger.Error("查找权限记录失败", zap.Error(err), zap.Uint("authResourceID", authResource.ID))
return fmt.Errorf("查找权限记录失败: %w", err)
}
// 更新权限记录
for _, permission := range permissions {
permission.Name = fmt.Sprintf("%s-%s", authResource.Component, authResource.HTTPMethod)
permission.Description = fmt.Sprintf("%s %s 权限", authResource.HTTPMethod, authResource.BackendRoute)
permission.MenuID = &authResource.MenuID
permission.MenuGroupID = menu.MenuGroupID
// 更新权限记录
if err := s.permissionRepo.Update(nil, permission); err != nil {
s.logger.Error("更新权限记录失败", zap.Error(err), zap.Uint("permissionID", permission.ID))
return fmt.Errorf("更新权限记录失败: %w", err)
}
s.logger.Info("更新权限记录成功",
zap.Uint("permissionID", permission.ID),
zap.Uint("authResourceID", authResource.ID),
zap.Uint("menuID", authResource.MenuID),
zap.Any("menuGroupID", menu.MenuGroupID))
}
return nil
}
// deletePermissionForAuthResource 删除认证资源对应的权限
func (s *PermissionSyncService) deletePermissionForAuthResource(authResourceID uint) error {
// 查找对应的权限记录
permissions, err := s.permissionRepo.GetByAuthResourceID(nil, authResourceID)
if err != nil {
s.logger.Error("查找权限记录失败", zap.Error(err), zap.Uint("authResourceID", authResourceID))
return fmt.Errorf("查找权限记录失败: %w", err)
}
// 删除权限记录
for _, permission := range permissions {
// 删除权限记录
if err := s.permissionRepo.Delete(nil, permission.ID); err != nil {
s.logger.Error("删除权限记录失败", zap.Error(err), zap.Uint("permissionID", permission.ID))
return fmt.Errorf("删除权限记录失败: %w", err)
}
s.logger.Info("删除权限记录成功",
zap.Uint("permissionID", permission.ID),
zap.Uint("authResourceID", authResourceID))
}
return nil
}
// SyncPermissionForMenuGroupChange 同步菜单分组变更到权限
func (s *PermissionSyncService) SyncPermissionForMenuGroupChange(menuID uint, newMenuGroupID *uint) error {
// 查找该菜单下的所有认证资源
authResources, err := s.authResourcesRepo.FindByMenuID(menuID)
if err != nil {
s.logger.Error("查找认证资源失败", zap.Error(err), zap.Uint("menuID", menuID))
return fmt.Errorf("查找认证资源失败: %w", err)
}
// 更新每个认证资源对应的权限记录
for _, authResource := range authResources {
permissions, err := s.permissionRepo.GetByAuthResourceID(nil, authResource.ID)
if err != nil {
s.logger.Error("查找权限记录失败", zap.Error(err), zap.Uint("authResourceID", authResource.ID))
continue
}
// 更新权限记录的MenuGroupID
for _, permission := range permissions {
permission.MenuGroupID = newMenuGroupID
// 更新权限记录
if err := s.permissionRepo.Update(nil, permission); err != nil {
s.logger.Error("更新权限的菜单分组ID失败", zap.Error(err), zap.Uint("permissionID", permission.ID))
return fmt.Errorf("更新权限的菜单分组ID失败: %w", err)
}
s.logger.Info("更新权限的菜单分组ID成功",
zap.Uint("permissionID", permission.ID),
zap.Uint("authResourceID", authResource.ID),
zap.Any("newMenuGroupID", newMenuGroupID))
}
}
return nil
}

BIN
gofaster/backend/main.exe

Binary file not shown.
Loading…
Cancel
Save