fix: botones start/stop/restart usan POST; agrega webhook Coolify

- CoolifyApplicationStart/Stop/Restart cambian GET → POST (Coolify API requiere POST)
- Nuevo endpoint público POST /webhooks/coolify para recibir notificaciones
  de deployment/restart desde Coolify Settings → Notifications → Webhook
- UI: muestra URL del webhook en modal de config para fácil copia

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Lizandro Guarnizo
2026-05-25 22:04:25 -05:00
co-authored by Copilot
parent 7bfe7cba5c
commit 0f386ad456
3 changed files with 38 additions and 3 deletions
+11
View File
@@ -442,6 +442,17 @@
</button>
</div>
</div>
<!-- Webhook URL para notificaciones -->
<div class="px-6 pb-4 border-t pt-4">
<p class="text-xs text-gray-500 mb-1 font-medium">URL Webhook (notificaciones)</p>
<p class="text-xs text-gray-400 mb-2">Copia esta URL en <strong>Coolify → Settings → Notifications → Webhook</strong> para recibir eventos de deployment/restart.</p>
<div class="flex items-center gap-2">
<code class="flex-1 text-xs bg-gray-50 border rounded px-3 py-1.5 truncate select-all"
x-text="window.location.origin + '/webhooks/coolify'"></code>
<button @click="navigator.clipboard.writeText(window.location.origin + '/webhooks/coolify').then(() => flash('URL copiada'))"
class="text-xs px-3 py-1.5 rounded-lg border text-gray-600 hover:bg-gray-50 shrink-0">Copiar</button>
</div>
</div>
<div x-show="cfgMsg" class="px-6 pb-4 text-sm" :class="cfgOk ? 'text-green-600' : 'text-red-600'" x-text="cfgMsg"></div>
</div>
</div>
+25 -3
View File
@@ -161,13 +161,13 @@ func CoolifyApplicationEnvDelete(c *fiber.Ctx) error {
return coolifyProxy(c, http.MethodDelete, "/applications/"+c.Params("uuid")+"/envs/"+c.Params("env_id"))
}
func CoolifyApplicationStart(c *fiber.Ctx) error {
return coolifyProxy(c, http.MethodGet, "/applications/"+c.Params("uuid")+"/start")
return coolifyProxy(c, http.MethodPost, "/applications/"+c.Params("uuid")+"/start")
}
func CoolifyApplicationStop(c *fiber.Ctx) error {
return coolifyProxy(c, http.MethodGet, "/applications/"+c.Params("uuid")+"/stop")
return coolifyProxy(c, http.MethodPost, "/applications/"+c.Params("uuid")+"/stop")
}
func CoolifyApplicationRestart(c *fiber.Ctx) error {
return coolifyProxy(c, http.MethodGet, "/applications/"+c.Params("uuid")+"/restart")
return coolifyProxy(c, http.MethodPost, "/applications/"+c.Params("uuid")+"/restart")
}
func CoolifyApplicationDeployments(c *fiber.Ctx) error {
return coolifyProxy(c, http.MethodGet, "/applications/"+c.Params("uuid")+"/deployments")
@@ -256,3 +256,25 @@ func CoolifyCurrentTeam(c *fiber.Ctx) error {
func CoolifyTeamMembers(c *fiber.Ctx) error {
return coolifyProxy(c, http.MethodGet, "/teams/current/members")
}
// CoolifyWebhook recibe notificaciones push de Coolify (deployment events, etc.)
// Configura en Coolify UI → Settings → Notifications → Webhook → URL: https://admin.u-site.app/app/coolify/webhook
func CoolifyWebhook(c *fiber.Ctx) error {
var payload map[string]interface{}
if err := c.BodyParser(&payload); err != nil {
// acepta también body vacío o texto plano
payload = map[string]interface{}{"raw": string(c.Body())}
}
// Log del evento para debug
eventType := ""
if t, ok := payload["type"].(string); ok {
eventType = t
} else if t, ok := payload["event"].(string); ok {
eventType = t
}
_ = eventType // en el futuro: guardar en DB, enviar push, etc.
return c.JSON(fiber.Map{"ok": true})
}
+2
View File
@@ -23,6 +23,8 @@ func RutasPublicas(web fiber.Router) {
// Webhook entrante por integración SaaS (token único por config)
web.Post("/webhooks/saas-in/:token", controllers.SaasWebhookInHandler)
web.Get("/webhooks/saas-in/:token", controllers.SaasWebhookInHandler) // algunos SaaS verifican con GET
// Coolify notifica eventos de deployment/restart aquí (configurar en Coolify → Settings → Notifications → Webhook)
web.Post("/webhooks/coolify", controllers.CoolifyWebhook)
// ─── Página de confirmación de pago ───────────────────────────────────
web.Get("/pago-exitoso", apiControllers.PagoExitosoPage)