Multi-tenant dentro de soft_usite, reutilizando la infraestructura ya existente (AiConfig, motor de function-calling del agente de Telegram) en vez de un servicio nuevo aparte: - UmindTenant: sitio/cliente con dominios permitidos, config de IA para el chat y personalidad/tono. - Ingesta: crawler simple (mismo dominio, N páginas) + chunking + embeddings (config global con módulo "umind_embeddings", pensada para OpenAI ya que Claude no ofrece embeddings) guardados como JSON, con búsqueda por similitud coseno en memoria (sin pgvector todavía). - Agente acotado: única herramienta buscar_conocimiento, sin acceso a nada interno — si no encuentra la respuesta, lo dice en vez de inventar. - Widget público (/widget/umind.js + /widget/:site_key/*), autenticado por site_key + validación de dominio (Origin/Referer), no por secreto, ya que la key viaja en el HTML público del sitio instalado. - Panel /app/umind: tenants, estado de ingesta, historial de conversaciones por sesión.
110 lines
6.5 KiB
Go
Executable File
110 lines
6.5 KiB
Go
Executable File
package routes
|
|
|
|
import (
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/sujit-baniya/fiber-boilerplate/rest/controllers"
|
|
apiControllers "github.com/sujit-baniya/fiber-boilerplate/rest/controllers/api"
|
|
"github.com/sujit-baniya/fiber-boilerplate/rest/middlewares"
|
|
)
|
|
|
|
func RutasPublicas(web fiber.Router) {
|
|
web.Get("/", controllers.Landing)
|
|
web.Get("/index", controllers.Index)
|
|
//web.Get("/login", controllers.Login)
|
|
web.Get("/ping", Pong)
|
|
web.Get("/all-routes", AllRoutes)
|
|
web.Get("/do/verify-email", middlewares.ValidateConfirmToken, controllers.VerifyRegisteredEmail)
|
|
|
|
// ─── Webhooks públicos (sin autenticación) ────────────────────────────
|
|
// Bold requiere respuesta HTTP 200 rápida, sin middleware de sesión.
|
|
web.Post("/webhooks/bold", apiControllers.BoldWebhook)
|
|
// dLocal requiere respuesta HTTP 200 inmediata.
|
|
web.Post("/webhooks/dlocal", apiControllers.DlocalWebhook)
|
|
// PayPal: configurar en el panel de PayPal → Webhooks, con los eventos
|
|
// CHECKOUT.ORDER.APPROVED y PAYMENT.CAPTURE.COMPLETED.
|
|
web.Post("/webhooks/paypal", apiControllers.PaypalWebhook)
|
|
// 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)
|
|
// Ruta genérica
|
|
web.Post("/webhooks/coolify", controllers.CoolifyWebhook)
|
|
// Ruta por instancia: incluye el config_id para identificar de qué Coolify viene
|
|
web.Post("/webhooks/coolify/:config_id", controllers.CoolifyWebhook)
|
|
|
|
// ─── Página de confirmación de pago ───────────────────────────────────
|
|
web.Get("/pago-exitoso", apiControllers.PagoExitosoPage)
|
|
// Ruta fuera del prefijo /api para evitar que AuthApi() la intercepte
|
|
web.Get("/pago/estado", apiControllers.PagoEstadoAPI)
|
|
// ─── Documentación pública ────────────────────────────────────────────────
|
|
web.Get("/docs/:saas", controllers.DocsPublicoIndex)
|
|
web.Get("/docs/:saas/:slug", controllers.DocsPublicaPagina)
|
|
// ─── Webhook de Telegram para vinculación del portal ──────────────────────
|
|
// Configurar en el bot: POST https://api.telegram.org/bot{TOKEN}/setWebhook?url={HOST}/webhooks/telegram-portal
|
|
web.Post("/webhooks/telegram-portal", controllers.TelegramPortalWebhook)
|
|
|
|
// ─── Webhook del agente administrador (bot con IA) ──────────────────────
|
|
// Configurar en el bot: POST https://api.telegram.org/bot{TOKEN}/setWebhook?url={HOST}/webhooks/telegram-agent/{BOT_TOKEN}
|
|
web.Post("/webhooks/telegram-agent/:bot_token", controllers.TelegramAgentWebhook)
|
|
|
|
// ─── WebSMS (LabsMobile) — API de envío + webhooks ──────────────────
|
|
web.Post("/api/sms/send", controllers.ApiSendSms)
|
|
web.Post("/webhooks/websms/delivery", controllers.WebSmsDeliveryWebhook)
|
|
web.Post("/webhooks/websms/click", controllers.WebSmsClickWebhook)
|
|
web.Post("/webhooks/websms/incoming", controllers.WebSmsIncomingWebhook)
|
|
|
|
// ─── Agente de monitoreo de servidores ────────────────────────────────────
|
|
// El agente instalado en cada servidor reporta métricas aquí (sin sesión, auth por token).
|
|
web.Post("/agent/heartbeat", controllers.AgentHeartbeat)
|
|
// Servir el script de instalación del agente
|
|
web.Get("/agent/install.sh", func(c *fiber.Ctx) error {
|
|
c.Set("Content-Type", "text/plain; charset=utf-8")
|
|
return c.SendFile("./agent/install.sh")
|
|
})
|
|
// Descargar binario pre-compilado del agente
|
|
// Ejemplo: GET /agent/download/usite-agent-linux-amd64
|
|
web.Get("/agent/download/:filename", func(c *fiber.Ctx) error {
|
|
filename := c.Params("filename")
|
|
// Validar que sea un nombre de binario válido (sin path traversal)
|
|
for _, ch := range filename {
|
|
if ch == '/' || ch == '.' || ch == '\\' {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "nombre inválido"})
|
|
}
|
|
}
|
|
path := "./agent/dist/" + filename
|
|
c.Set("Content-Disposition", "attachment; filename=\""+filename+"\"")
|
|
c.Set("Content-Type", "application/octet-stream")
|
|
return c.SendFile(path)
|
|
})
|
|
// ─── Página de estado del sistema (Atlassian Statuspage) ────────────────
|
|
web.Get("/status", controllers.StatusPage)
|
|
|
|
// ─── Webhook de soporte (correo entrante) ────────────────────────────────
|
|
// Configurar en SendGrid/Mailgun: POST {HOST}/webhooks/soporte/{provider}
|
|
web.Post("/webhooks/soporte/:provider", controllers.SoporteWebhook)
|
|
|
|
// ─── Landing Generator (acceso con X-Landing-Secret) ─────────────────────
|
|
// Rutas públicas (sin secret) para lectura de preview y polling
|
|
web.Get("/landing/preview/:token", apiControllers.LandingGetSession)
|
|
web.Get("/landing/poll/:token", apiControllers.LandingPollPayment)
|
|
// Rutas internas (requieren X-Landing-Secret del Next.js)
|
|
web.Post("/landing/session", apiControllers.LandingCreateSession)
|
|
web.Post("/landing/chat", apiControllers.LandingChat)
|
|
web.Post("/landing/generate", apiControllers.LandingGenerate)
|
|
web.Post("/landing/payment", apiControllers.LandingCreatePayment)
|
|
web.Get("/landing/answers/:token", apiControllers.LandingGetAnswers)
|
|
web.Get("/landing/download/:token", apiControllers.LandingDownload)
|
|
// Config de IA activa (para Landing Generator)
|
|
web.Get("/landing/ai-config", apiControllers.LandingGetAiConfig)
|
|
|
|
// ─── uMind: widget de chat embebible por tenant ───────────────────────────
|
|
// Público por diseño (lo llama el navegador del visitante de un sitio de
|
|
// terceros) — la protección es site_key + validación de dominio, no
|
|
// sesión. Excluido de AuthApi() por vivir fuera del grupo /api.
|
|
web.Get("/widget/umind.js", apiControllers.UmindWidgetScript)
|
|
widget := web.Group("/widget/:site_key")
|
|
widget.Options("*", middlewares.UmindWidgetCORS)
|
|
widget.Get("/init", middlewares.AuthUmindWidget, apiControllers.UmindWidgetInit)
|
|
widget.Post("/mensaje", middlewares.AuthUmindWidget, apiControllers.UmindWidgetMensaje)
|
|
}
|