package handlers import ( "net/http" "strconv" "github.com/gin-gonic/gin" "armature/store" "armature/triggers" ) // TriggerHandler provides admin CRUD for extension-declared triggers. type TriggerHandler struct { stores store.Stores engine *triggers.Engine } // NewTriggerHandler creates a TriggerHandler. func NewTriggerHandler(stores store.Stores, engine *triggers.Engine) *TriggerHandler { return &TriggerHandler{stores: stores, engine: engine} } // ListTriggers returns all triggers with optional filters. // GET /admin/triggers?package_id=&type=&enabled= func (h *TriggerHandler) ListTriggers(c *gin.Context) { opts := store.TriggerListOptions{ ListOptions: store.ListOptions{ Limit: parseIntParam(c, "limit", 50), Offset: parseIntParam(c, "offset", 0), }, PackageID: c.Query("package_id"), Type: c.Query("type"), } if e := c.Query("enabled"); e != "" { b := e == "true" opts.Enabled = &b } triggers, total, err := h.stores.Triggers.List(c.Request.Context(), opts) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"triggers": triggers, "total": total}) } // GetTrigger returns a single trigger by ID. // GET /admin/triggers/:id func (h *TriggerHandler) GetTrigger(c *gin.Context) { t, err := h.stores.Triggers.GetByID(c.Request.Context(), c.Param("id")) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } if t == nil { c.JSON(http.StatusNotFound, gin.H{"error": "trigger not found"}) return } c.JSON(http.StatusOK, t) } // EnableTrigger enables a trigger. // PUT /admin/triggers/:id/enable func (h *TriggerHandler) EnableTrigger(c *gin.Context) { id := c.Param("id") if err := h.stores.Triggers.SetEnabled(c.Request.Context(), id, true); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // Re-register with engine t, _ := h.stores.Triggers.GetByID(c.Request.Context(), id) if t != nil { h.engine.RegisterTrigger(t) } c.JSON(http.StatusOK, gin.H{"ok": true}) } // DisableTrigger disables a trigger. // PUT /admin/triggers/:id/disable func (h *TriggerHandler) DisableTrigger(c *gin.Context) { id := c.Param("id") if err := h.stores.Triggers.SetEnabled(c.Request.Context(), id, false); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } h.engine.UnregisterTrigger(id) c.JSON(http.StatusOK, gin.H{"ok": true}) } // DeleteTrigger deletes a trigger. // DELETE /admin/triggers/:id func (h *TriggerHandler) DeleteTrigger(c *gin.Context) { id := c.Param("id") h.engine.UnregisterTrigger(id) if err := h.stores.Triggers.Delete(c.Request.Context(), id); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"ok": true}) } // ListTriggerLogs returns execution logs for a trigger. // GET /admin/triggers/:id/logs?limit= func (h *TriggerHandler) ListTriggerLogs(c *gin.Context) { limit := parseIntParam(c, "limit", 50) logs, err := h.stores.Triggers.ListLogs(c.Request.Context(), c.Param("id"), limit) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"logs": logs}) } // ListPackageTriggers returns triggers for a specific package. // GET /admin/packages/:id/triggers func (h *TriggerHandler) ListPackageTriggers(c *gin.Context) { triggers, err := h.stores.Triggers.ListByPackage(c.Request.Context(), c.Param("id")) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"triggers": triggers}) } func parseIntParam(c *gin.Context, key string, defaultVal int) int { if v := c.Query(key); v != "" { if n, err := strconv.Atoi(v); err == nil && n > 0 { return n } } return defaultVal }