diff --git a/backend/handlers/cert.go b/backend/handlers/cert.go index 587da73..c49ca6d 100644 --- a/backend/handlers/cert.go +++ b/backend/handlers/cert.go @@ -78,7 +78,40 @@ func (h *CertHandler) CreateCertificate(c *gin.Context) { // Check if domain already exists var existing config.Certificate if err := config.DB.Where("domain = ?", req.Domain).First(&existing).Error; err == nil { - c.JSON(http.StatusConflict, gin.H{"error": "domain already exists"}) + // Domain exists, check if it's a failed/expired certificate that can be retried + if existing.Status == "error" || existing.Status == "expired" || existing.Status == "pending" { + // Update existing record and retry issuance + existing.Email = req.Email + existing.Provider = req.Provider + existing.ChallengeType = req.ChallengeType + existing.DNSProvider = req.DNSProvider + existing.DNSConfig = req.DNSConfig + existing.Status = "pending" + existing.ErrorMessage = "" + if req.AutoRenew != nil { + existing.AutoRenew = *req.AutoRenew + } + if req.RenewDays != nil { + existing.RenewDays = *req.RenewDays + } + if err := config.DB.Save(&existing).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + // Start issuance in background + go func() { + if err := services.GetACMECertificate(&existing, h.Cfg); err != nil { + existing.Status = "error" + existing.ErrorMessage = err.Error() + } else { + existing.Status = "active" + } + config.DB.Save(&existing) + }() + c.JSON(http.StatusAccepted, gin.H{"message": "certificate re-issuance started", "certificate": existing}) + return + } + c.JSON(http.StatusConflict, gin.H{"error": "domain already exists with status: " + existing.Status}) return }