Merge branch 'main' into feat/mysql-service-delivery
This commit is contained in:
@@ -144,9 +144,53 @@ func (h *BusinessLineHandler) Create(c *gin.Context) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
req.Name = strings.TrimSpace(req.Name)
|
||||
if req.Name == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "business line name is required"})
|
||||
return
|
||||
}
|
||||
|
||||
var existing model.BusinessLine
|
||||
if err := h.db.Where("name = ?", req.Name).First(&existing).Error; err == nil {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "business line already exists"})
|
||||
return
|
||||
} else if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if h.wayne == nil {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "wayne native api is not configured"})
|
||||
return
|
||||
}
|
||||
namespace, err := h.wayne.EnsureNamespace(c.Request.Context(), req.Name)
|
||||
if err != nil {
|
||||
writeWayneRoleBindingError(c, nil, err)
|
||||
return
|
||||
}
|
||||
if namespace == nil || namespace.ID == 0 {
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": "wayne namespace response is invalid"})
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(namespace.Name) == "" {
|
||||
namespace.Name = req.Name
|
||||
}
|
||||
if strings.TrimSpace(namespace.KubeNamespace) == "" {
|
||||
namespace.KubeNamespace = req.Name
|
||||
}
|
||||
|
||||
item := model.BusinessLine{Name: req.Name}
|
||||
if err := h.db.Create(&item).Error; err != nil {
|
||||
if err := h.db.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Create(&item).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Create(&model.BusinessLineWayneNamespace{
|
||||
BusinessLineID: item.ID,
|
||||
WayneNamespaceID: namespace.ID,
|
||||
WayneNamespaceName: namespace.Name,
|
||||
KubeNamespace: namespace.KubeNamespace,
|
||||
}).Error
|
||||
}); err != nil {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user