|
|
|
package controller
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
"strconv"
|
|
|
|
|
|
|
|
"gofaster/internal/auth/model"
|
|
|
|
"gofaster/internal/auth/repository"
|
|
|
|
"gofaster/internal/auth/service"
|
|
|
|
"gofaster/internal/shared/response"
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
)
|
|
|
|
|
|
|
|
type ResourceController struct {
|
|
|
|
resourceService *service.ResourceService
|
|
|
|
routeMappingRepo *repository.RouteMappingRepository
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewResourceController(resourceService *service.ResourceService, routeMappingRepo *repository.RouteMappingRepository) *ResourceController {
|
|
|
|
return &ResourceController{
|
|
|
|
resourceService: resourceService,
|
|
|
|
routeMappingRepo: routeMappingRepo,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateResource 创建资源
|
|
|
|
// @Summary 创建资源
|
|
|
|
// @Description 创建新的资源记录
|
|
|
|
// @Tags 资源管理
|
|
|
|
// @Accept json
|
|
|
|
// @Produce json
|
|
|
|
// @Param resource body model.Resource true "资源信息"
|
|
|
|
// @Success 200 {object} response.Response{data=model.Resource}
|
|
|
|
// @Failure 400 {object} response.Response
|
|
|
|
// @Failure 500 {object} response.Response
|
|
|
|
// @Router /api/auth/resources [post]
|
|
|
|
func (c *ResourceController) CreateResource(ctx *gin.Context) {
|
|
|
|
var resource model.Resource
|
|
|
|
if err := ctx.ShouldBindJSON(&resource); err != nil {
|
|
|
|
response.Error(ctx, http.StatusBadRequest, "请求参数错误", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := c.resourceService.CreateResource(ctx.Request.Context(), &resource); err != nil {
|
|
|
|
response.Error(ctx, http.StatusInternalServerError, "创建资源失败", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
response.Success(ctx, "资源创建成功", resource)
|
|
|
|
}
|
|
|
|
|
|
|
|
// UpdateResource 更新资源
|
|
|
|
// @Summary 更新资源
|
|
|
|
// @Description 更新指定ID的资源信息
|
|
|
|
// @Tags 资源管理
|
|
|
|
// @Accept json
|
|
|
|
// @Produce json
|
|
|
|
// @Param id path int true "资源ID"
|
|
|
|
// @Param resource body model.Resource true "资源信息"
|
|
|
|
// @Success 200 {object} response.Response{data=model.Resource}
|
|
|
|
// @Failure 400 {object} response.Response
|
|
|
|
// @Failure 500 {object} response.Response
|
|
|
|
// @Router /api/auth/resources/{id} [put]
|
|
|
|
func (c *ResourceController) UpdateResource(ctx *gin.Context) {
|
|
|
|
idStr := ctx.Param("id")
|
|
|
|
id, err := strconv.ParseUint(idStr, 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "无效的资源ID")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var resource model.Resource
|
|
|
|
if err := ctx.ShouldBindJSON(&resource); err != nil {
|
|
|
|
response.Error(ctx, http.StatusBadRequest, "请求参数错误", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
resource.ID = uint(id)
|
|
|
|
|
|
|
|
if err := c.resourceService.UpdateResource(ctx.Request.Context(), &resource); err != nil {
|
|
|
|
response.Error(ctx, http.StatusInternalServerError, "更新资源失败", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
response.Success(ctx, "资源更新成功", resource)
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteResource 删除资源
|
|
|
|
// @Summary 删除资源
|
|
|
|
// @Description 删除指定ID的资源记录
|
|
|
|
// @Tags 资源管理
|
|
|
|
// @Accept json
|
|
|
|
// @Produce json
|
|
|
|
// @Param id path int true "资源ID"
|
|
|
|
// @Success 200 {object} response.Response
|
|
|
|
// @Failure 400 {object} response.Response
|
|
|
|
// @Failure 500 {object} response.Response
|
|
|
|
// @Router /api/auth/resources/{id} [delete]
|
|
|
|
func (c *ResourceController) DeleteResource(ctx *gin.Context) {
|
|
|
|
idStr := ctx.Param("id")
|
|
|
|
id, err := strconv.ParseUint(idStr, 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "无效的资源ID")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := c.resourceService.DeleteResource(ctx.Request.Context(), uint(id)); err != nil {
|
|
|
|
response.Error(ctx, http.StatusInternalServerError, "删除资源失败", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
response.Success(ctx, "资源删除成功", nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetResource 获取资源详情
|
|
|
|
// @Summary 获取资源详情
|
|
|
|
// @Description 根据ID获取资源的详细信息
|
|
|
|
// @Tags 资源管理
|
|
|
|
// @Accept json
|
|
|
|
// @Produce json
|
|
|
|
// @Param id path int true "资源ID"
|
|
|
|
// @Success 200 {object} response.Response{data=model.Resource}
|
|
|
|
// @Failure 400 {object} response.Response
|
|
|
|
// @Failure 404 {object} response.Response
|
|
|
|
// @Router /api/auth/resources/{id} [get]
|
|
|
|
func (c *ResourceController) GetResource(ctx *gin.Context) {
|
|
|
|
idStr := ctx.Param("id")
|
|
|
|
id, err := strconv.ParseUint(idStr, 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "无效的资源ID")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
resource, err := c.resourceService.GetResource(ctx.Request.Context(), uint(id))
|
|
|
|
if err != nil {
|
|
|
|
response.Error(ctx, http.StatusNotFound, "资源不存在", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
response.Success(ctx, "获取资源成功", resource)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ListResources 获取资源列表
|
|
|
|
// @Summary 获取资源列表
|
|
|
|
// @Description 分页获取资源列表信息
|
|
|
|
// @Tags 资源管理
|
|
|
|
// @Accept json
|
|
|
|
// @Produce json
|
|
|
|
// @Param page query int false "页码" default(1)
|
|
|
|
// @Param pageSize query int false "每页数量" default(10)
|
|
|
|
// @Success 200 {object} response.Response{data=object}
|
|
|
|
// @Failure 500 {object} response.Response
|
|
|
|
// @Router /api/auth/resources [get]
|
|
|
|
func (c *ResourceController) ListResources(ctx *gin.Context) {
|
|
|
|
pageStr := ctx.DefaultQuery("page", "1")
|
|
|
|
pageSizeStr := ctx.DefaultQuery("pageSize", "10")
|
|
|
|
|
|
|
|
page, err := strconv.Atoi(pageStr)
|
|
|
|
if err != nil || page < 1 {
|
|
|
|
page = 1
|
|
|
|
}
|
|
|
|
|
|
|
|
pageSize, err := strconv.Atoi(pageSizeStr)
|
|
|
|
if err != nil || pageSize < 1 || pageSize > 100 {
|
|
|
|
pageSize = 10
|
|
|
|
}
|
|
|
|
|
|
|
|
resources, total, err := c.resourceService.ListResources(ctx.Request.Context(), page, pageSize)
|
|
|
|
if err != nil {
|
|
|
|
response.Error(ctx, http.StatusInternalServerError, "获取资源列表失败", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
response.Success(ctx, "获取资源列表成功", gin.H{
|
|
|
|
"data": resources,
|
|
|
|
"page": page,
|
|
|
|
"size": pageSize,
|
|
|
|
"total": total,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetResourceTree 获取资源树
|
|
|
|
// @Summary 获取资源树
|
|
|
|
// @Description 获取层级结构的资源树
|
|
|
|
// @Tags 资源管理
|
|
|
|
// @Accept json
|
|
|
|
// @Produce json
|
|
|
|
// @Success 200 {object} response.Response{data=[]model.Resource}
|
|
|
|
// @Failure 500 {object} response.Response
|
|
|
|
// @Router /api/auth/resources/tree [get]
|
|
|
|
func (c *ResourceController) GetResourceTree(ctx *gin.Context) {
|
|
|
|
resources, err := c.resourceService.GetResourceTree(ctx.Request.Context())
|
|
|
|
if err != nil {
|
|
|
|
response.Error(ctx, http.StatusInternalServerError, "获取资源树失败", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
response.Success(ctx, "获取资源树成功", resources)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SyncResources 同步资源
|
|
|
|
// @Summary 同步资源
|
|
|
|
// @Description 从路由映射同步资源信息
|
|
|
|
// @Tags 资源管理
|
|
|
|
// @Accept json
|
|
|
|
// @Produce json
|
|
|
|
// @Success 200 {object} response.Response
|
|
|
|
// @Failure 500 {object} response.Response
|
|
|
|
// @Router /api/auth/resources/sync [post]
|
|
|
|
func (c *ResourceController) SyncResources(ctx *gin.Context) {
|
|
|
|
if err := c.resourceService.SyncResourcesFromRoutes(ctx.Request.Context()); err != nil {
|
|
|
|
response.Error(ctx, http.StatusInternalServerError, "同步资源失败", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
response.Success(ctx, "资源同步成功", nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ListResourcesByModule 根据模块获取资源列表
|
|
|
|
// @Summary 根据模块获取资源列表
|
|
|
|
// @Description 根据模块名称获取相关资源列表
|
|
|
|
// @Tags 资源管理
|
|
|
|
// @Accept json
|
|
|
|
// @Produce json
|
|
|
|
// @Param module path string true "模块名称"
|
|
|
|
// @Success 200 {object} response.Response{data=[]model.Resource}
|
|
|
|
// @Failure 400 {object} response.Response
|
|
|
|
// @Failure 500 {object} response.Response
|
|
|
|
// @Router /api/auth/resources/module/{module} [get]
|
|
|
|
func (c *ResourceController) ListResourcesByModule(ctx *gin.Context) {
|
|
|
|
module := ctx.Param("module")
|
|
|
|
if module == "" {
|
|
|
|
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "模块名称不能为空")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
resources, err := c.resourceService.ListResourcesByModule(ctx.Request.Context(), module)
|
|
|
|
if err != nil {
|
|
|
|
response.Error(ctx, http.StatusInternalServerError, "获取模块资源失败", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
response.Success(ctx, "获取模块资源成功", resources)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ListResourcesByType 根据类型获取资源列表
|
|
|
|
// @Summary 根据类型获取资源列表
|
|
|
|
// @Description 根据资源类型获取相关资源列表
|
|
|
|
// @Tags 资源管理
|
|
|
|
// @Accept json
|
|
|
|
// @Produce json
|
|
|
|
// @Param type path string true "资源类型"
|
|
|
|
// @Success 200 {object} response.Response{data=[]model.Resource}
|
|
|
|
// @Failure 400 {object} response.Response
|
|
|
|
// @Failure 500 {object} response.Response
|
|
|
|
// @Router /api/auth/resources/type/{type} [get]
|
|
|
|
func (c *ResourceController) ListResourcesByType(ctx *gin.Context) {
|
|
|
|
resourceType := ctx.Param("type")
|
|
|
|
if resourceType == "" {
|
|
|
|
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "资源类型不能为空")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
resources, err := c.resourceService.ListResourcesByType(ctx.Request.Context(), resourceType)
|
|
|
|
if err != nil {
|
|
|
|
response.Error(ctx, http.StatusInternalServerError, "获取类型资源失败", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
response.Success(ctx, "获取类型资源成功", resources)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetAuthGroupStats 获取权限分组统计
|
|
|
|
// @Summary 获取权限分组统计
|
|
|
|
// @Description 获取路由映射的权限分组统计信息
|
|
|
|
// @Tags 资源管理
|
|
|
|
// @Accept json
|
|
|
|
// @Produce json
|
|
|
|
// @Success 200 {object} response.Response{data=map[string]int}
|
|
|
|
// @Failure 400 {object} response.Response
|
|
|
|
// @Router /api/resources/auth-group-stats [get]
|
|
|
|
func (c *ResourceController) GetAuthGroupStats(ctx *gin.Context) {
|
|
|
|
stats, err := c.routeMappingRepo.GetAuthGroupStats()
|
|
|
|
if err != nil {
|
|
|
|
response.Error(ctx, http.StatusInternalServerError, "获取权限分组统计失败", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
response.Success(ctx, "获取权限分组统计成功", stats)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ListRoutesByAuthGroup 根据权限分组获取路由列表
|
|
|
|
// @Summary 根据权限分组获取路由列表
|
|
|
|
// @Description 根据权限分组获取路由映射列表
|
|
|
|
// @Tags 资源管理
|
|
|
|
// @Accept json
|
|
|
|
// @Produce json
|
|
|
|
// @Param authGroup path string true "权限分组" Enums(Read, Edit)
|
|
|
|
// @Success 200 {object} response.Response{data=[]model.RouteMapping}
|
|
|
|
// @Failure 400 {object} response.Response
|
|
|
|
// @Router /api/resources/auth-group/{authGroup}/routes [get]
|
|
|
|
func (c *ResourceController) ListRoutesByAuthGroup(ctx *gin.Context) {
|
|
|
|
authGroup := ctx.Param("authGroup")
|
|
|
|
if authGroup == "" {
|
|
|
|
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "权限分组不能为空")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// 验证权限分组值
|
|
|
|
if authGroup != "Read" && authGroup != "Edit" {
|
|
|
|
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "权限分组只能是Read或Edit")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
routes, err := c.routeMappingRepo.FindByAuthGroup(authGroup)
|
|
|
|
if err != nil {
|
|
|
|
response.Error(ctx, http.StatusInternalServerError, "获取权限分组路由失败", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
response.Success(ctx, "获取权限分组路由成功", routes)
|
|
|
|
}
|