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) }