package handlers import ( "net/http" "github.com/flatrender/render-svc/internal/db" "github.com/flatrender/render-svc/internal/models" "github.com/gin-gonic/gin" "github.com/google/uuid" ) type FontHandler struct { store *db.Store } func NewFontHandler(store *db.Store) *FontHandler { return &FontHandler{store: store} } // ── Admin ──────────────────────────────────────────────────────────────────── // GET /v1/node-fonts func (h *FontHandler) List(c *gin.Context) { items, err := h.store.ListFontRequestsWithStatus(c.Request.Context()) if err != nil { c.JSON(http.StatusInternalServerError, models.APIError{Code: "internal_error", Message: err.Error()}) return } if items == nil { items = []models.FontRequestWithStatus{} } c.JSON(http.StatusOK, gin.H{"items": items}) } // POST /v1/node-fonts func (h *FontHandler) Create(c *gin.Context) { var req models.CreateFontRequestBody if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, models.APIError{Code: "bad_request", Message: err.Error()}) return } fr, err := h.store.CreateFontRequest(c.Request.Context(), req.Name, req.SystemName, req.FileURL) if err != nil { c.JSON(http.StatusInternalServerError, models.APIError{Code: "internal_error", Message: err.Error()}) return } c.JSON(http.StatusCreated, fr) } // DELETE /v1/node-fonts/:id func (h *FontHandler) Delete(c *gin.Context) { id, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, models.APIError{Code: "bad_request", Message: "invalid id"}) return } if err := h.store.DeleteFontRequest(c.Request.Context(), id); err != nil { c.JSON(http.StatusInternalServerError, models.APIError{Code: "internal_error", Message: err.Error()}) return } c.Status(http.StatusNoContent) } // ── Internal (node agents, HMAC auth) ──────────────────────────────────────── // GET /v1/internal/nodes/:node_id/fonts/pending func (h *FontHandler) Pending(c *gin.Context) { nodeID, err := uuid.Parse(c.Param("node_id")) if err != nil { c.JSON(http.StatusBadRequest, models.APIError{Code: "bad_request", Message: "invalid node_id"}) return } fonts, err := h.store.PendingFontsForNode(c.Request.Context(), nodeID) if err != nil { c.JSON(http.StatusInternalServerError, models.APIError{Code: "internal_error", Message: err.Error()}) return } if fonts == nil { fonts = []models.PendingFont{} } c.JSON(http.StatusOK, gin.H{"fonts": fonts}) } // POST /v1/internal/nodes/:node_id/fonts/:request_id/status func (h *FontHandler) Report(c *gin.Context) { nodeID, err := uuid.Parse(c.Param("node_id")) if err != nil { c.JSON(http.StatusBadRequest, models.APIError{Code: "bad_request", Message: "invalid node_id"}) return } reqID, err := uuid.Parse(c.Param("request_id")) if err != nil { c.JSON(http.StatusBadRequest, models.APIError{Code: "bad_request", Message: "invalid request_id"}) return } var body models.FontStatusReport _ = c.ShouldBindJSON(&body) status := body.Status if status != "Installed" { status = "Failed" } if err := h.store.ReportFontStatus(c.Request.Context(), nodeID, reqID, status, body.Error); err != nil { c.JSON(http.StatusInternalServerError, models.APIError{Code: "internal_error", Message: err.Error()}) return } c.Status(http.StatusNoContent) }