Initial commit: TaskPool React panel
- React frontend with route-level code splitting - Backend rebranded from Baihu to TaskPool - DB brand migration script and local compatibility
This commit is contained in:
@@ -0,0 +1,389 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/engigu/taskpool/internal/constant"
|
||||
"github.com/engigu/taskpool/internal/database"
|
||||
"github.com/engigu/taskpool/internal/models"
|
||||
"github.com/engigu/taskpool/internal/models/vo"
|
||||
"github.com/engigu/taskpool/internal/services"
|
||||
"github.com/engigu/taskpool/internal/services/relation"
|
||||
"github.com/engigu/taskpool/internal/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type EnvController struct {
|
||||
envService *services.EnvService
|
||||
}
|
||||
|
||||
func NewEnvController(envService *services.EnvService) *EnvController {
|
||||
return &EnvController{envService: envService}
|
||||
}
|
||||
|
||||
// GetSecretStatus 获取加密秘钥状态
|
||||
// @Summary 获取加密秘钥状态
|
||||
// @Description 返回系统是否已配置加密秘钥
|
||||
// @Tags Env
|
||||
// @Produce json
|
||||
// @Success 200 {object} utils.Response{data=bool} "成功"
|
||||
// @Router /env/secret-status [get]
|
||||
// @Security BearerAuth
|
||||
func (ec *EnvController) GetSecretStatus(c *gin.Context) {
|
||||
utils.Success(c, utils.IsSecretKeySet())
|
||||
}
|
||||
|
||||
// CreateEnvVar 创建环境变量
|
||||
// @Summary 创建环境变量
|
||||
// @Description 创建一个新的环境变量
|
||||
// @Tags 环境变量
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param body body object true "环境变量信息"
|
||||
// @Success 200 {object} utils.Response{data=vo.EnvVO}
|
||||
// @Router /env [post]
|
||||
func (ec *EnvController) CreateEnvVar(c *gin.Context) {
|
||||
userID := c.GetString("userID")
|
||||
|
||||
var req struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Value string `json:"value" binding:"required"`
|
||||
Remark string `json:"remark"`
|
||||
Type string `json:"type"`
|
||||
Hidden *bool `json:"hidden"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
Tags string `json:"tags"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if req.Type == "" {
|
||||
req.Type = constant.EnvTypeNormal
|
||||
}
|
||||
|
||||
hidden := true
|
||||
if req.Hidden != nil {
|
||||
hidden = *req.Hidden
|
||||
}
|
||||
|
||||
enabled := true
|
||||
if req.Enabled != nil {
|
||||
enabled = *req.Enabled
|
||||
}
|
||||
|
||||
envVar := ec.envService.CreateEnvVar(req.Name, req.Value, req.Remark, req.Type, hidden, enabled, userID)
|
||||
if envVar != nil {
|
||||
relation.DataRelation.SaveTags(envVar.ID, constant.RelationTypeEnvTag, req.Tags)
|
||||
envVar.Tags = req.Tags
|
||||
}
|
||||
|
||||
// Broadcast tasks to all agents because global envs changed
|
||||
services.GetAgentWSManager().BroadcastTasksToAll()
|
||||
|
||||
utils.Success(c, vo.ToEnvVO(envVar))
|
||||
}
|
||||
|
||||
// GetEnvVars 获取环境变量列表
|
||||
// @Summary 获取环境变量列表
|
||||
// @Description 分页获取环境变量列表,支持按名称筛选
|
||||
// @Tags 环境变量
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param name query string false "按名称模糊查询"
|
||||
// @Param page query int false "页码"
|
||||
// @Param page_size query int false "每页数量"
|
||||
// @Param type query string false "按类型筛选"
|
||||
// @Param tags query string false "按标签筛选"
|
||||
// @Success 200 {object} utils.Response{data=utils.PaginationData{data=[]vo.EnvVO}}
|
||||
// @Router /env [get]
|
||||
func (ec *EnvController) GetEnvVars(c *gin.Context) {
|
||||
userID := c.GetString("userID")
|
||||
p := utils.ParsePagination(c)
|
||||
name := c.DefaultQuery("name", "")
|
||||
envType := c.DefaultQuery("type", "")
|
||||
tags := c.DefaultQuery("tags", "")
|
||||
envVars, total := ec.envService.GetEnvVarsWithPagination(userID, name, envType, tags, p.Page, p.PageSize)
|
||||
utils.PaginatedResponse(c, vo.ToEnvVOListFromModels(envVars), total, p)
|
||||
}
|
||||
|
||||
// GetAllEnvVars 获取所有环境变量
|
||||
// @Summary 获取所有环境变量
|
||||
// @Description 获取当前用户的所有环境变量(不分页)
|
||||
// @Tags 环境变量
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Success 200 {object} utils.Response{data=[]vo.EnvVO}
|
||||
// @Router /env/all [get]
|
||||
func (ec *EnvController) GetAllEnvVars(c *gin.Context) {
|
||||
userID := c.GetString("userID")
|
||||
envVars := ec.envService.GetEnvVarsByUserID(userID)
|
||||
utils.Success(c, vo.ToEnvVOListFromModels(envVars))
|
||||
}
|
||||
|
||||
// GetEnvVar 获取环境变量详情
|
||||
// @Summary 获取环境变量详情
|
||||
// @Description 根据 ID 获取环境变量详情
|
||||
// @Tags 环境变量
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "环境变量ID"
|
||||
// @Success 200 {object} utils.Response{data=vo.EnvVO}
|
||||
// @Failure 404 {object} utils.Response
|
||||
// @Router /env/{id} [get]
|
||||
func (ec *EnvController) GetEnvVar(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
utils.BadRequest(c, "无效的环境变量ID")
|
||||
return
|
||||
}
|
||||
|
||||
envVar := ec.envService.GetEnvVarByID(id)
|
||||
if envVar == nil {
|
||||
utils.NotFound(c, "环境变量不存在")
|
||||
return
|
||||
}
|
||||
|
||||
utils.Success(c, vo.ToEnvVO(envVar))
|
||||
}
|
||||
|
||||
// UpdateEnvVar 更新环境变量
|
||||
// @Summary 更新环境变量
|
||||
// @Description 根据 ID 更新环境变量信息
|
||||
// @Tags 环境变量
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "环境变量ID"
|
||||
// @Param body body object true "环境变量更新信息"
|
||||
// @Success 200 {object} utils.Response{data=vo.EnvVO}
|
||||
// @Failure 404 {object} utils.Response
|
||||
// @Router /env/{id} [put]
|
||||
func (ec *EnvController) UpdateEnvVar(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
utils.BadRequest(c, "无效的环境变量ID")
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
Remark string `json:"remark"`
|
||||
Type string `json:"type"`
|
||||
Hidden *bool `json:"hidden"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
Tags string `json:"tags"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if req.Type == "" {
|
||||
req.Type = constant.EnvTypeNormal
|
||||
}
|
||||
|
||||
// 对于更新,获取现有数据
|
||||
existing := ec.envService.GetEnvVarByID(id)
|
||||
if existing == nil {
|
||||
utils.NotFound(c, "环境变量不存在")
|
||||
return
|
||||
}
|
||||
|
||||
hidden := existing.Hidden
|
||||
if req.Hidden != nil {
|
||||
hidden = req.Hidden
|
||||
}
|
||||
|
||||
enabled := existing.Enabled
|
||||
if req.Enabled != nil {
|
||||
enabled = req.Enabled
|
||||
}
|
||||
|
||||
envVar := ec.envService.UpdateEnvVar(id, req.Name, req.Value, req.Remark, req.Type, utils.DerefBool(hidden, true), utils.DerefBool(enabled, true))
|
||||
if envVar == nil {
|
||||
utils.NotFound(c, "环境变量不存在")
|
||||
return
|
||||
}
|
||||
|
||||
relation.DataRelation.SaveTags(envVar.ID, constant.RelationTypeEnvTag, req.Tags)
|
||||
envVar.Tags = req.Tags
|
||||
|
||||
// Broadcast tasks to all agents because global envs changed
|
||||
services.GetAgentWSManager().BroadcastTasksToAll()
|
||||
|
||||
utils.Success(c, vo.ToEnvVO(envVar))
|
||||
}
|
||||
|
||||
// DeleteEnvVar 删除环境变量
|
||||
// @Summary 删除环境变量
|
||||
// @Description 根据 ID 删除环境变量
|
||||
// @Tags 环境变量
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "环境变量ID"
|
||||
// @Param force query boolean false "强制删除(忽略任务关联)"
|
||||
// @Success 200 {object} utils.Response
|
||||
// @Failure 404 {object} utils.Response
|
||||
// @Failure 409 {object} utils.Response{data=[]vo.TaskVO}
|
||||
// @Router /env/{id} [delete]
|
||||
func (ec *EnvController) DeleteEnvVar(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
utils.BadRequest(c, "无效的环境变量ID")
|
||||
return
|
||||
}
|
||||
|
||||
force := c.Query("force") == "true"
|
||||
success, associatedTasks := ec.envService.DeleteEnvVar(id, force)
|
||||
|
||||
if len(associatedTasks) > 0 {
|
||||
c.JSON(200, utils.Response{
|
||||
Code: 409,
|
||||
Msg: "该环境变量已被任务引用,请先在任务中删除引用或选择强制删除",
|
||||
Data: vo.ToTaskVOListFromModels(associatedTasks),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if !success {
|
||||
utils.NotFound(c, "环境变量不存在或删除失败")
|
||||
return
|
||||
}
|
||||
|
||||
// Broadcast tasks to all agents because global envs changed
|
||||
services.GetAgentWSManager().BroadcastTasksToAll()
|
||||
|
||||
utils.SuccessMsg(c, "删除成功")
|
||||
}
|
||||
|
||||
// GetAssociatedTasks 获取关联任务
|
||||
// @Summary 获取关联任务
|
||||
// @Description 获取引用了该环境变量的任务列表
|
||||
// @Tags 环境变量
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "环境变量ID"
|
||||
// @Success 200 {object} utils.Response{data=[]vo.TaskVO}
|
||||
// @Router /env/{id}/tasks [get]
|
||||
func (ec *EnvController) GetAssociatedTasks(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
utils.BadRequest(c, "无效的环境变量ID")
|
||||
return
|
||||
}
|
||||
tasks := ec.envService.GetAssociatedTasks(id)
|
||||
utils.Success(c, vo.ToTaskVOListFromModels(tasks))
|
||||
}
|
||||
|
||||
// GetTags 获取所有环境变量标签
|
||||
// @Summary 获取所有环境变量标签
|
||||
// @Description 获取所有环境变量中使用的标签列表
|
||||
// @Tags 环境变量
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Success 200 {object} utils.Response{data=[]string}
|
||||
// @Router /env/tags [get]
|
||||
func (ec *EnvController) GetTags(c *gin.Context) {
|
||||
tags, err := ec.envService.GetAllEnvTags()
|
||||
if err != nil {
|
||||
utils.ServerError(c, "获取标签失败")
|
||||
return
|
||||
}
|
||||
utils.Success(c, tags)
|
||||
}
|
||||
|
||||
// BulkSaveEnv 批量保存环境变量
|
||||
func (ec *EnvController) BulkSaveEnv(c *gin.Context) {
|
||||
var reqs []struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name" binding:"required"`
|
||||
Value string `json:"value" binding:"required"`
|
||||
Remark string `json:"remark"`
|
||||
Type string `json:"type"`
|
||||
Hidden *bool `json:"hidden"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&reqs); err != nil {
|
||||
utils.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
userID := c.GetString("userID")
|
||||
|
||||
for _, req := range reqs {
|
||||
if req.Type == constant.EnvTypeSecret {
|
||||
continue // 二次严苛拦截,机密变量不应下发/保存
|
||||
}
|
||||
|
||||
hidden := true
|
||||
if req.Hidden != nil {
|
||||
hidden = *req.Hidden
|
||||
}
|
||||
enabled := true
|
||||
if req.Enabled != nil {
|
||||
enabled = *req.Enabled
|
||||
}
|
||||
|
||||
var existingEnv *models.EnvironmentVariable
|
||||
// 优先按 ID 匹配
|
||||
if req.ID != "" {
|
||||
var e models.EnvironmentVariable
|
||||
if err := database.DB.Where("id = ?", req.ID).First(&e).Error; err == nil {
|
||||
existingEnv = &e
|
||||
}
|
||||
}
|
||||
// 如果 ID 没找到,按 Name 匹配
|
||||
if existingEnv == nil {
|
||||
var e models.EnvironmentVariable
|
||||
if err := database.DB.Where("name = ?", req.Name).First(&e).Error; err == nil {
|
||||
existingEnv = &e
|
||||
}
|
||||
}
|
||||
|
||||
if existingEnv != nil {
|
||||
existingEnv.Name = req.Name
|
||||
existingEnv.Value = models.BigText(req.Value)
|
||||
existingEnv.Remark = req.Remark
|
||||
existingEnv.Type = req.Type
|
||||
existingEnv.Hidden = &hidden
|
||||
existingEnv.Enabled = &enabled
|
||||
database.DB.Save(existingEnv)
|
||||
|
||||
if req.ID != "" && existingEnv.ID != req.ID {
|
||||
database.DB.Model(existingEnv).Update("id", req.ID)
|
||||
}
|
||||
} else {
|
||||
envVar := &models.EnvironmentVariable{
|
||||
ID: req.ID,
|
||||
Name: req.Name,
|
||||
Value: models.BigText(req.Value),
|
||||
Remark: req.Remark,
|
||||
Type: req.Type,
|
||||
Hidden: &hidden,
|
||||
Enabled: &enabled,
|
||||
UserID: userID,
|
||||
CreatedAt: models.Now(),
|
||||
UpdatedAt: models.Now(),
|
||||
}
|
||||
if envVar.ID == "" {
|
||||
envVar.ID = utils.GenerateID()
|
||||
}
|
||||
database.DB.Create(envVar)
|
||||
}
|
||||
}
|
||||
|
||||
services.GetAgentWSManager().BroadcastTasksToAll()
|
||||
utils.Success(c, nil)
|
||||
}
|
||||
Reference in New Issue
Block a user