Files
xinfra/server/internal/handler/container_service.go
T

118 lines
3.4 KiB
Go

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) Clusters(c *gin.Context) {
data, ok := h.loadData(c)
if !ok {
return
}
c.JSON(http.StatusOK, gin.H{"items": data.Clusters, "nodes": data.Nodes, "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
}