package handlers import ( "fmt" "net/http" "strconv" "gitea.d3m0k1d.ru/d3m0k1d/HellreigN/backend/internal/grpcsrv/commander" "gitea.d3m0k1d.ru/d3m0k1d/HellreigN/backend/internal/models" "gitea.d3m0k1d.ru/d3m0k1d/HellreigN/backend/internal/repository" "gitea.d3m0k1d.ru/d3m0k1d/HellreigN/backend/internal/service" "github.com/gin-gonic/gin" ) type ScriptHandlers struct { svc *service.ScriptService tracker *commander.ConnTracker whereami string } func NewScriptHandlers(svc *service.ScriptService, tracker *commander.ConnTracker, whereami string) ScriptHandlers { return ScriptHandlers{svc: svc, tracker: tracker, whereami: whereami} } type RunScriptIn struct { AgentID string `json:"agent_id" binding:"required"` InterpreterID int64 `json:"interpreter_id" binding:"required"` ScriptText string `json:"script_text" binding:"required"` Stdin *string `json:"stdin"` } // RunScript submits a script as a job and returns a wait_url for the result. // @Summary Run a script on an agent // @Description Resolves interpreter argv[] and sends the full command to the agent // @Tags scripts // @Accept json // @Produce json // @Param body body RunScriptIn true "Script request" // @Success 201 {object} AddJobOut // @Security Bearer // @Router /scripts/run [post] func (h *ScriptHandlers) RunScript(c *gin.Context) { var in RunScriptIn if err := c.Bind(&in); err != nil { c.Error(err) return } agent, ok := h.tracker.GetAgent(in.AgentID) if !ok { c.Status(http.StatusNotFound) c.Error(fmt.Errorf("agent not found")) return } command, err := h.svc.ResolveCommand(c.Request.Context(), in.InterpreterID, in.ScriptText) if err != nil { c.Error(err) return } jid, err := agent.AddJob(models.JobForInsert{ Command: command, Stdin: in.Stdin, }) if err != nil { c.Error(err) return } waitURL := fmt.Sprintf("%s/api/v1/jobs/%d/wait", h.whereami, jid) c.JSON(http.StatusCreated, AddJobOut{ ID: jid, Command: command, WaitURL: waitURL, }) } // ListInterpreters returns all registered script interpreters. // @Summary List interpreters // @Description Returns all script interpreters available in the system // @Tags scripts // @Produce json // @Success 200 {array} repository.ScriptInterpreter // @Security Bearer // @Router /scripts/interpreters [get] func (h *ScriptHandlers) ListInterpreters(c *gin.Context) { interpreters, err := h.svc.List(c.Request.Context()) if err != nil { c.Error(err) return } c.JSON(http.StatusOK, interpreters) } // CreateInterpreter registers a new script interpreter. // @Summary Create interpreter // @Description Registers a new script interpreter with name, label, and argv // @Tags scripts // @Accept json // @Produce json // @Param body body repository.ScriptInterpreterCreate true "Interpreter definition" // @Success 201 {object} repository.ScriptInterpreter // @Security Bearer // @Router /scripts/interpreters [post] func (h *ScriptHandlers) CreateInterpreter(c *gin.Context) { var in repository.ScriptInterpreterCreate if err := c.BindJSON(&in); err != nil { c.Error(err) return } si, err := h.svc.Create(c.Request.Context(), in) if err != nil { c.Error(err) return } c.JSON(http.StatusCreated, si) } // GetInterpreter returns a single interpreter by ID. // @Summary Get interpreter // @Description Returns a script interpreter by ID // @Tags scripts // @Produce json // @Param id path int true "Interpreter ID" // @Success 200 {object} repository.ScriptInterpreter // @Security Bearer // @Router /scripts/interpreters/:id [get] func (h *ScriptHandlers) GetInterpreter(c *gin.Context) { id, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { c.Error(err) return } si, err := h.svc.GetByID(c.Request.Context(), id) if err != nil { c.Error(err) return } c.JSON(http.StatusOK, si) } // UpdateInterpreter updates an interpreter. // @Summary Update interpreter // @Description Updates fields of a script interpreter // @Tags scripts // @Accept json // @Produce json // @Param id path int true "Interpreter ID" // @Param body body repository.ScriptInterpreterUpdate true "Interpreter fields" // @Success 200 {object} repository.ScriptInterpreter // @Security Bearer // @Router /scripts/interpreters/:id [put] func (h *ScriptHandlers) UpdateInterpreter(c *gin.Context) { id, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { c.Error(err) return } var in repository.ScriptInterpreterUpdate if err := c.BindJSON(&in); err != nil { c.Error(err) return } si, err := h.svc.Update(c.Request.Context(), id, in) if err != nil { c.Error(err) return } c.JSON(http.StatusOK, si) } // DeleteInterpreter removes an interpreter. // @Summary Delete interpreter // @Description Removes a script interpreter by ID // @Tags scripts // @Param id path int true "Interpreter ID" // @Success 204 // @Security Bearer // @Router /scripts/interpreters/:id [delete] func (h *ScriptHandlers) DeleteInterpreter(c *gin.Context) { id, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { c.Error(err) return } if err := h.svc.Delete(c.Request.Context(), id); err != nil { c.Error(err) return } c.Status(http.StatusNoContent) }