package httpapi import ( "net/http" "strconv" "github.com/gin-gonic/gin" "github.com/google/uuid" "git.apinb.com/ops/license/internal/subject" ) type subjectHandler struct { service *subject.Service } type subjectRequest struct { PlatformName string `json:"platform_name"` Workspace string `json:"workspace"` } type subjectView struct { ID uuid.UUID `json:"id"` PlatformName string `json:"platform_name"` Workspace string `json:"workspace"` CreatedAt string `json:"created_at"` UpdatedAt string `json:"updated_at"` LicenceCount int64 `json:"licence_count"` } func (h subjectHandler) list(c *gin.Context) { page, pageSize, ok := parsePagination(c) if !ok { writeBadRequest(c) return } items, total, err := h.service.List(c.Request.Context(), c.Query("q"), page, pageSize) if err != nil { writeError(c, err) return } views := make([]subjectView, len(items)) for index := range items { views[index] = newSubjectView(items[index]) } writePage(c, views, page, pageSize, total) } func (h subjectHandler) create(c *gin.Context) { request, ok := readSubjectRequest(c) if !ok { return } item, err := h.service.Create(c.Request.Context(), subject.UpsertInput{ PlatformName: request.PlatformName, Workspace: request.Workspace, }) if err != nil { writeError(c, err) return } writeData(c, http.StatusCreated, newSubjectView(item)) } func (h subjectHandler) get(c *gin.Context) { id, ok := parseID(c) if !ok { return } item, err := h.service.Get(c.Request.Context(), id) if err != nil { writeError(c, err) return } writeData(c, http.StatusOK, newSubjectView(item)) } func (h subjectHandler) update(c *gin.Context) { id, ok := parseID(c) if !ok { return } request, ok := readSubjectRequest(c) if !ok { return } item, err := h.service.Update(c.Request.Context(), id, subject.UpsertInput{ PlatformName: request.PlatformName, Workspace: request.Workspace, }) if err != nil { writeError(c, err) return } writeData(c, http.StatusOK, newSubjectView(item)) } func (h subjectHandler) delete(c *gin.Context) { id, ok := parseID(c) if !ok { return } if err := h.service.Delete(c.Request.Context(), id); err != nil { writeError(c, err) return } writeData(c, http.StatusOK, nil) } func readSubjectRequest(c *gin.Context) (subjectRequest, bool) { var request subjectRequest if err := decodeJSON(c, &request); err != nil { writeBadRequest(c) return subjectRequest{}, false } return request, true } func parsePagination(c *gin.Context) (int, int, bool) { page, pageSize := 1, 20 if raw, exists := c.GetQuery("page"); exists { value, err := strconv.Atoi(raw) if err != nil || value < 1 { return 0, 0, false } page = value } if raw, exists := c.GetQuery("page_size"); exists { value, err := strconv.Atoi(raw) if err != nil || value < 1 || value > 100 { return 0, 0, false } pageSize = value } return page, pageSize, true } func parseID(c *gin.Context) (uuid.UUID, bool) { id, err := uuid.Parse(c.Param("id")) if err != nil || id == uuid.Nil { writeBadRequest(c) return uuid.Nil, false } return id, true } func newSubjectView(item subject.Subject) subjectView { return subjectView{ ID: item.ID, PlatformName: item.PlatformName, Workspace: item.Workspace, CreatedAt: item.CreatedAt.UTC().Format(timeLayout), UpdatedAt: item.UpdatedAt.UTC().Format(timeLayout), LicenceCount: item.LicenceCount, } }