fix: multiple error
ci-api / test (push) Successful in 23m32s
ci-web / test (push) Successful in 13m52s

This commit is contained in:
Nuxgrid
2026-08-01 17:24:34 +02:00
parent a06205a608
commit 5d2a132c3c
9 changed files with 144 additions and 54 deletions
+30 -16
View File
@@ -24,11 +24,14 @@ type createRequest struct {
}
type DetailDemoUserRequest struct {
Username string `json:"username" binding:"required,min=3,max=64,alphanum"`
// Namespace identifie la démo de façon unique. Le username ne suffit
// pas : un même client peut avoir plusieurs démos (historique, relances),
// et interroger par username renvoyait toujours la même (la plus
// ancienne), jamais celle réellement sélectionnée dans l'UI.
Namespace string `json:"namespace" binding:"required,min=3,max=63"`
}
type DemoDetailsResponse struct {
Username string `json:"username"`
Namespace string `json:"namespace"`
State ResourceState `json:"state"`
}
@@ -42,11 +45,14 @@ func (h *Handler) Create(c *gin.Context) {
}
d, err := h.svc.Create(req.LeadID, req.Username)
if err != nil {
if errors.Is(err, ErrCapacityReached) {
switch {
case errors.Is(err, ErrCapacityReached):
c.JSON(http.StatusConflict, gin.H{"error": "capacité maximale de démos atteinte"})
return
case errors.Is(err, ErrUserHasActiveDemo):
c.JSON(http.StatusConflict, gin.H{"error": "ce client a déjà une démo active"})
default:
c.JSON(http.StatusInternalServerError, gin.H{"error": "erreur serveur"})
}
c.JSON(http.StatusInternalServerError, gin.H{"error": "erreur serveur"})
return
}
c.JSON(http.StatusAccepted, d)
@@ -62,6 +68,21 @@ func (h *Handler) List(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"items": items})
}
// ListMine : GET /demos/mine — démo(s) rattachée(s) au client authentifié.
func (h *Handler) ListMine(c *gin.Context) {
p := auth.PrincipalFrom(c)
if p == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "non authentifié"})
return
}
items, err := h.svc.ListForUser(p.Username)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "erreur serveur"})
return
}
c.JSON(http.StatusOK, gin.H{"items": items})
}
func (h *Handler) ListDetails(c *gin.Context) {
p := auth.PrincipalFrom(c)
if p == nil {
@@ -74,26 +95,19 @@ func (h *Handler) ListDetails(c *gin.Context) {
}
var req DetailDemoUserRequest
if err := c.ShouldBindJSON(&req); err != nil || req.Username == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "username requis"})
if err := c.ShouldBindJSON(&req); err != nil || req.Namespace == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "namespace requis"})
return
}
demo, err := h.svc.store.GetDemoByUsername(req.Username)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "démo introuvable"})
return
}
state, err := h.helm.GetResourceState(c.Request.Context(), demo.Namespace)
state, err := h.helm.GetResourceState(c.Request.Context(), req.Namespace)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "impossible de récupérer l'état des ressources"})
return
}
c.JSON(http.StatusOK, DemoDetailsResponse{
Username: req.Username,
Namespace: demo.Namespace,
Namespace: req.Namespace,
State: state,
})
}
+20 -5
View File
@@ -11,9 +11,10 @@ import (
)
var (
ErrCapacityReached = errors.New("capacité maximale de démos atteinte")
ErrNotFound = errors.New("démo introuvable")
ErrNotExtendable = errors.New("démo non prolongeable dans son état actuel")
ErrCapacityReached = errors.New("capacité maximale de démos atteinte")
ErrNotFound = errors.New("démo introuvable")
ErrNotExtendable = errors.New("démo non prolongeable dans son état actuel")
ErrUserHasActiveDemo = errors.New("ce client a déjà une démo active")
)
// Config du service (injectable pour les tests).
@@ -50,8 +51,22 @@ func NewService(store Store, pool Pool, prov Provisioner, cfg Config) *Service {
}
// Create réserve la capacité + le pool, persiste la démo et déclenche le worker.
// username (optionnel) rattache la démo à un client existant.
// username (optionnel) rattache la démo à un client existant. Un client n'a
// droit qu'à une seule démo active à la fois.
func (s *Service) Create(leadID, username string) (Demo, error) {
normalizedUsername := auth.NormalizeUsername(username)
if normalizedUsername != "" {
existing, err := s.store.ListByUsername(normalizedUsername)
if err != nil {
return Demo{}, err
}
for _, d := range existing {
if d.Status.Active() {
return Demo{}, ErrUserHasActiveDemo
}
}
}
active, err := s.store.CountActive()
if err != nil {
return Demo{}, err
@@ -63,7 +78,7 @@ func (s *Service) Create(leadID, username string) (Demo, error) {
id := uuid.NewString()
demo := Demo{
ID: id,
Username: auth.NormalizeUsername(username),
Username: normalizedUsername,
LeadID: leadID,
Status: StatusPending,
Namespace: "demo-" + shortID(id),