package handler import ( "errors" "net/http" "github.com/1024XEngineer/xinfra/server/internal/auth" "github.com/1024XEngineer/xinfra/server/internal/model" "github.com/1024XEngineer/xinfra/server/internal/service" "github.com/gin-gonic/gin" "gorm.io/gorm" ) type ContainerServiceHandler struct { db *gorm.DB wayne *service.WayneRoleBindingService } func NewContainerServiceHandler(db *gorm.DB, wayne *service.WayneRoleBindingService) *ContainerServiceHandler { return &ContainerServiceHandler{db: db, wayne: wayne} } func (h *ContainerServiceHandler) Summary(c *gin.Context) { data, ok := h.loadData(c) if !ok { return } c.JSON(http.StatusOK, data.Summary) } func (h *ContainerServiceHandler) Workloads(c *gin.Context) { data, ok := h.loadData(c) if !ok { return } c.JSON(http.StatusOK, gin.H{"items": data.Workloads, "summary": data.Summary}) } func (h *ContainerServiceHandler) loadData(c *gin.Context) (*service.ContainerServiceData, bool) { claims, ok := CurrentClaims(c) if !ok { c.JSON(http.StatusUnauthorized, gin.H{"error": "missing current user"}) return nil, false } businessLineID, ok := parseBusinessLineID(c) if !ok { return nil, false } businessLine, ok := h.getBusinessLine(c, businessLineID) if !ok { return nil, false } if !h.canReadBusinessLine(c, claims, businessLineID) { return nil, false } namespaces, ok := h.listBusinessLineNamespaces(c, businessLineID) if !ok { return nil, false } data, err := h.wayne.ContainerServiceData(c.Request.Context(), service.ContainerBusinessLineQuery{ BusinessLineID: businessLineID, BusinessLineName: businessLine.Name, Namespaces: namespaces, }) if err != nil { writeWayneRoleBindingError(c, nil, err) return nil, false } return data, true } func (h *ContainerServiceHandler) getBusinessLine(c *gin.Context, id uint64) (model.BusinessLine, bool) { var businessLine model.BusinessLine if err := h.db.First(&businessLine, "id = ?", id).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { c.JSON(http.StatusNotFound, gin.H{"error": "business line not found"}) return businessLine, false } c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return businessLine, false } return businessLine, true } func (h *ContainerServiceHandler) canReadBusinessLine(c *gin.Context, claims *auth.Claims, businessLineID uint64) bool { if claims.IsAdmin { return true } var binding model.BusinessLineUser if err := h.db.Where("business_line_id = ? AND user_id = ?", businessLineID, claims.UserID).First(&binding).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { c.JSON(http.StatusForbidden, gin.H{"error": "current user is not bound to current business line"}) return false } c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return false } return true } func (h *ContainerServiceHandler) listBusinessLineNamespaces(c *gin.Context, businessLineID uint64) ([]model.BusinessLineWayneNamespace, bool) { var rows []model.BusinessLineWayneNamespace if err := h.db.Where("business_line_id = ?", businessLineID).Order("wayne_namespace_id ASC").Find(&rows).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return nil, false } return rows, true }