Files
soft_usite/rest/routes/user.go
T
Lizandro GuarnizoandClaude Sonnet 5 08265510ea feat(umind): mide el consumo de IA, OCR y transcripción por tenant
Es la base del cobro por uso: hasta ahora no había ninguna medición de
consumo en todo el repo.

- UmindUso registra cada evento facturable con el costo YA calculado al
  precio vigente del plan. Congelarlo evita que subir un precio revalúe
  consumo pasado, que haría indefendible una factura ante un reclamo.
- callAI devuelve los tokens que reportó el proveedor (campo usage, igual
  en todos los OpenAI-compatibles; input+output en Anthropic). Se mide
  cada ronda de tool-calling, no solo la última: todas gastan tokens.
- ExtraerTextoOCR y TranscribirAudioSelfHosted reciben agenteID; 0 = no
  medir, que es lo que pasan los botones "Probar" del panel de staff.
- Aviso al superar el tope del plan, una vez por mes y sin cortar el
  servicio. El flag de "ya avisé" es en memoria a propósito.
- GET /app/umind/uso con filtros de fecha: resumen por tipo + detalle.
- Test del cálculo de costo por tipo, incluida fracción de 1k tokens y
  tenant sin plan.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 11:41:23 -05:00

648 lines
44 KiB
Go
Executable File

package routes
import (
"net/http"
"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 UserRoutes(app fiber.Router) {
protected := app.Group("/app").
Use(
middlewares.AuthWeb(), // Middleware de autenticación
middlewares.LoadUserMiddleware, // Middleware para cargar el usuario
)
// Perfil del usuario autenticado
protected.Get("/profile", middlewares.MenuMiddleware, controllers.Profile)
protected.Get("/profile/telegram-status", controllers.TelegramStaffStatus)
protected.Post("/profile/telegram-init", controllers.TelegramStaffInit)
protected.Post("/profile/telegram-validar", controllers.TelegramStaffValidar)
// Rutas de la aplicación
// web me redireccione a /
protected.Get("/web", func(c *fiber.Ctx) error { return c.Redirect("/", http.StatusSeeOther) })
app.Get("/web", func(c *fiber.Ctx) error { return c.Redirect("/", http.StatusSeeOther) })
protected.Get("/", controllers.App)
protected.Get("/dashboard", middlewares.MenuMiddleware, controllers.Dashboard)
protected.Get("/modules", middlewares.MenuMiddleware, controllers.Modules) // Renderizar la vista
protected.Get("/loadmodules", controllers.GetModules) // Obtener todos los módulos
protected.Post("/modules", middlewares.SoloAdmin, controllers.CreateModule) // Crear un nuevo módulo
protected.Put("/modules/:id", middlewares.SoloAdmin, controllers.UpdateModule) // Actualizar un módulo existente
protected.Delete("/modules/:id", middlewares.SoloAdmin, controllers.DeleteModule) // Eliminar un módulo
// Rutas de roles
protected.Get("/roles", middlewares.MenuMiddleware, controllers.Roles) // Renderizar la vista
protected.Get("/loadroles", controllers.GetRoles) // Obtener todos
protected.Post("/roles", middlewares.SoloAdmin, controllers.CreateRole) // Crear
protected.Put("/roles/:id", middlewares.SoloAdmin, controllers.UpdateRole) // Actualizar
protected.Delete("/roles/:id", middlewares.SoloAdmin, controllers.DeleteRole) // Eliminar
// Rutas de módulos
protected.Get("/submodules", middlewares.MenuMiddleware, controllers.Submodules) // Renderizar la vista
protected.Get("/loadsubmodules", controllers.GetSubmodules) // Obtener todos los módulos
protected.Post("/submodules", middlewares.SoloAdmin, controllers.CreateSubmodule) // Crear un nuevo módulo
protected.Put("/submodules/:id", middlewares.SoloAdmin, controllers.UpdateSubmodule) // Actualizar un módulo existente
protected.Delete("/submodules/:id", middlewares.SoloAdmin, controllers.DeleteSubmodule) // Eliminar un módulo
// Rutas de usuarios
protected.Get("/users", middlewares.MenuMiddleware, controllers.Users) // Renderizar la vista
protected.Get("/loadusers", controllers.GetUsers) // Obtener
protected.Post("/users", middlewares.SoloAdmin, controllers.CreateUser) // Crear
protected.Put("/users/:id", middlewares.SoloAdmin, controllers.UpdateUser) // Actualizar
protected.Put("/password/:id", middlewares.SoloAdmin, controllers.UpdatePassword) // Actualizar
protected.Delete("/users/:id", middlewares.SoloAdmin, controllers.DeleteUser) // Eliminar
protected.Get("/user/:id", controllers.GetUser) // Buscar un usuario
protected.Post("/users/:id/credenciales", controllers.EnviarCredencialesUsuario) // Enviar credenciales
// Rutas de conexiones ssh
protected.Get("/conexion_ssh", middlewares.MenuMiddleware, controllers.ConxSsh) // Renderizar la vista
protected.Get("/loadconexionssh", controllers.GetConxSsh) // Obtener
protected.Post("/conexionssh", controllers.CreateConxSsh) // Crear
protected.Put("/conexionssh/:id", controllers.UpdateConxSsh) // Actualizar
protected.Delete("/conexionssh/:id", controllers.DeleteConxSsh) // Eliminar
// Rutas de conexiones db
protected.Get("/conexion_db", middlewares.MenuMiddleware, controllers.ConxDb) // Renderizar la vista
protected.Get("/loadconexiondb", controllers.GetConxDb) // Obtener
protected.Get("/api/conxdb/select", controllers.GetConxDbSelect) // Select (filtrado por ?servidor_id=)
protected.Post("/conexiondb", controllers.CreateConxDb) // Crear
protected.Put("/conexiondb/:id", controllers.UpdateConxDb) // Actualizar
protected.Delete("/conexiondb/:id", controllers.DeleteConxDb) // Eliminar
// Rutas de servidor
protected.Get("/servidor", middlewares.MenuMiddleware, controllers.Servidor)
protected.Get("/servidor-dashboard", middlewares.MenuMiddleware, controllers.ServidorDashboard)
protected.Get("/loadservidorselect", controllers.GetServidor)
protected.Get("/loadservidor", controllers.GetServidor)
protected.Post("/servidor", controllers.CreateServidor)
protected.Put("/servidor/:id", controllers.UpdateServidor)
protected.Delete("/servidor/:id", controllers.DeleteServidor)
protected.Get("/servidor-dashboard/:id", controllers.GetServidorDashboard)
protected.Get("/conx-ping/:id", controllers.PingConexion)
protected.Post("/servidor/:id/agent-token", controllers.GenerateAgentToken)
protected.Get("/servidor/:id/metricas-history", controllers.GetMetricasHistory)
protected.Post("/servidor/:id/sync-hostinger", controllers.SyncServidorFromHostinger)
// Tareas (kanban)
protected.Get("/tareas", middlewares.MenuMiddleware, controllers.TareasIndex)
protected.Get("/tareas/data", controllers.GetTareas)
protected.Get("/tareas/usuarios", controllers.GetUsuariosSistema)
protected.Post("/tarea", controllers.CreateTarea)
protected.Get("/tarea/:id", controllers.GetTareaDetalle)
protected.Put("/tarea/:id", controllers.UpdateTarea)
protected.Put("/tarea/:id/estado", controllers.CambiarEstadoTarea)
protected.Delete("/tarea/:id", controllers.DeleteTareaHandler)
protected.Post("/tarea/:id/comentario", controllers.AddComentario)
// Monitor de URLs
protected.Get("/url-monitor", middlewares.MenuMiddleware, controllers.UrlMonitorIndex)
protected.Get("/url-monitors", controllers.GetUrlMonitors)
protected.Post("/url-monitor", controllers.CreateUrlMonitor)
protected.Put("/url-monitor/:id", controllers.UpdateUrlMonitor)
protected.Delete("/url-monitor/:id", controllers.DeleteUrlMonitorHandler)
protected.Post("/url-monitor/:id/check", controllers.CheckUrlMonitorNow)
protected.Get("/url-monitor/:id/logs", controllers.GetUrlMonitorLogsHandler)
// Rutas de proveedores de servidor
protected.Get("/prov_servidor", middlewares.MenuMiddleware, controllers.ProvServidor)
protected.Get("/loadprovservidor", controllers.GetProvServidor)
protected.Post("/provservidor", controllers.CreateProvServidor)
protected.Put("/provservidor/:id", controllers.UpdateProvServidor)
protected.Put("/provservidor/:id/integraciones", controllers.SetProvServidorIntegraciones)
protected.Delete("/provservidor/:id", controllers.DeleteProvServidor)
// Rutas de tipos de servidor
protected.Get("/tipo_servidor", middlewares.MenuMiddleware, controllers.TipoServidor)
protected.Get("/loadtiposervidor", controllers.GetTipoServidor)
protected.Post("/tiposervidor", controllers.CreateTipoServidor)
protected.Put("/tiposervidor/:id", controllers.UpdateTipoServidor)
protected.Delete("/tiposervidor/:id", controllers.DeleteTipoServidor)
// Rutas de tipo db
protected.Get("/tipo_db", middlewares.MenuMiddleware, controllers.TipoDb)
protected.Get("/loadtipodb", controllers.GetTipoDb)
protected.Post("/tipodb", controllers.CreateTipoDb)
protected.Put("/tipodb/:id", controllers.UpdateTipoDb)
protected.Delete("/tipodb/:id", controllers.DeleteTipoDb)
// ─── Módulo de Renovaciones / Contratos ──────────────────────────
RenovacionesRoutes(protected)
// ─── Seed manual (admin) ────────────────────────────────────────────
protected.Get("/run-seed", middlewares.SoloAdmin, controllers.RunSeed)
// ─── Query Runner (editor SQL) ────────────────────────────────────────────
protected.Get("/query-runner", middlewares.MenuMiddleware, controllers.QueryRunnerPage)
protected.Get("/query-runner/connections", controllers.GetConxDbList)
protected.Get("/query-runner/databases", controllers.GetDatabases)
protected.Get("/query-runner/tables", controllers.GetTables)
protected.Get("/query-runner/relations", controllers.GetRelations)
protected.Get("/query-runner/test", controllers.TestConnection)
// Sin SoloAdmin a propósito: RunQuery/RunBatchQuery ya limitan el alcance
// internamente (un no-admin solo ve/consulta las conexiones que su rol
// tiene asignadas vía Role.ConxDBs). El acceso real se controla asignando o
// no el submódulo "Query Runner" a su rol, no aquí.
protected.Post("/query-runner/run", controllers.RunQuery)
protected.Post("/query-runner/run-batch", controllers.RunBatchQuery)
protected.Get("/query-runner/history", controllers.GetHistory)
protected.Delete("/query-runner/history", controllers.ClearHistory)
protected.Post("/query-runner/export/csv", controllers.ExportCSV)
protected.Post("/query-runner/export/json", controllers.ExportJSON)
protected.Get("/query-runner/columns", controllers.GetTableColumnsHandler)
protected.Post("/query-runner/update-cell", controllers.UpdateCellHandler)
protected.Post("/query-runner/suggest", controllers.CorrectQueryHandler)
protected.Post("/query-runner/nl2sql", controllers.NL2SQLHandler)
// ─── Hostinger API ────────────────────────────────────────────────
protected.Get("/hostinger", middlewares.MenuMiddleware, controllers.HostingerConfigPage)
protected.Post("/hostinger/config", controllers.SaveHostingerConfig)
protected.Get("/hostinger/vps", controllers.GetHostingerVPS)
protected.Get("/hostinger/domains", controllers.GetHostingerDomains)
protected.Get("/hostinger/dns/:domain", controllers.GetHostingerDNS)
protected.Put("/hostinger/dns/:domain", controllers.UpdateHostingerDNS)
protected.Post("/hostinger/dns/:domain/reset", controllers.ResetHostingerDNS)
protected.Get("/hostinger/orders", controllers.GetHostingerOrders)
protected.Get("/hostinger/hosting", controllers.GetHostingerHosting)
// Domains: escritura
protected.Put("/hostinger/domains/:domain/nameservers", controllers.UpdateHostingerNameservers)
protected.Put("/hostinger/domains/:domain/domain-lock", controllers.EnableHostingerDomainLock)
protected.Delete("/hostinger/domains/:domain/domain-lock", controllers.DisableHostingerDomainLock)
protected.Put("/hostinger/domains/:domain/privacy", controllers.EnableHostingerPrivacy)
protected.Delete("/hostinger/domains/:domain/privacy", controllers.DisableHostingerPrivacy)
// VPS: acciones
protected.Post("/hostinger/vps/:id/start", controllers.StartHostingerVPS)
protected.Post("/hostinger/vps/:id/stop", controllers.StopHostingerVPS)
protected.Post("/hostinger/vps/:id/restart", controllers.RestartHostingerVPS)
protected.Put("/hostinger/vps/:id/root-password", controllers.SetHostingerVPSRootPassword)
protected.Put("/hostinger/vps/:id/hostname", controllers.SetHostingerVPSHostname)
protected.Get("/hostinger/vps/:id/metrics", controllers.GetHostingerVPSMetrics)
protected.Get("/hostinger/vps/:id/backups", controllers.GetHostingerVPSBackups)
// Billing: autorenovación
protected.Patch("/hostinger/billing/:id/auto-renewal/enable", controllers.EnableHostingerAutoRenewal)
protected.Delete("/hostinger/billing/:id/auto-renewal/disable", controllers.DisableHostingerAutoRenewal)
// ─── Cloudflare API ───────────────────────────────────────────────
protected.Get("/cloudflare", middlewares.MenuMiddleware, controllers.CloudflareConfigPage)
protected.Post("/cloudflare/config", controllers.SaveCloudflareConfig)
protected.Get("/cloudflare/verify", controllers.VerifyCloudflareToken)
protected.Post("/cloudflare/clean-token", controllers.CleanCloudflareToken)
protected.Get("/cloudflare/user", controllers.GetCloudflareUser)
protected.Get("/cloudflare/zones", controllers.GetCloudflareZones)
protected.Get("/cloudflare/zones/:zone_id/dns", controllers.GetCloudflareDNS)
protected.Post("/cloudflare/zones/:zone_id/dns", controllers.CreateCloudflareDNS)
protected.Put("/cloudflare/zones/:zone_id/dns/:record_id", controllers.UpdateCloudflareDNS)
protected.Patch("/cloudflare/zones/:zone_id/dns/:record_id", controllers.PatchCloudflareDNS)
protected.Delete("/cloudflare/zones/:zone_id/dns/:record_id", controllers.DeleteCloudflareDNS)
protected.Get("/cloudflare/zones/:zone_id/ssl", controllers.GetCloudflareSSL)
protected.Get("/cloudflare/zones/:zone_id/firewall", controllers.GetCloudflareFirewall)
// ─── Coolify API ──────────────────────────────────────────────────
protected.Get("/coolify", middlewares.MenuMiddleware, controllers.CoolifyIndex)
// Gestión de instancias Coolify (multi-instancia)
protected.Get("/coolify/configs", controllers.CoolifyListConfigs)
protected.Post("/coolify/configs", controllers.CoolifyCreateConfig)
protected.Get("/coolify/configs/:id", controllers.CoolifyGetConfigByID)
protected.Put("/coolify/configs/:id", controllers.CoolifyUpdateConfig)
protected.Delete("/coolify/configs/:id", controllers.CoolifyDeleteConfig)
protected.Get("/coolify/configs/:id/test", controllers.CoolifyTestConfig)
// Compat legado (upsert sobre primer registro)
protected.Get("/coolify/config", controllers.CoolifyGetConfig)
protected.Post("/coolify/config", controllers.CoolifySaveConfig)
protected.Get("/coolify/health", controllers.CoolifyTestConnection)
// Applications
protected.Get("/coolify/apps", controllers.CoolifyListApplications)
protected.Get("/coolify/apps/:uuid", controllers.CoolifyGetApplication)
protected.Get("/coolify/apps/:uuid/logs", controllers.CoolifyApplicationLogs)
protected.Get("/coolify/apps/:uuid/envs", controllers.CoolifyApplicationEnvs)
protected.Post("/coolify/apps/:uuid/envs", controllers.CoolifyApplicationEnvCreate)
protected.Patch("/coolify/apps/:uuid/envs", controllers.CoolifyApplicationEnvUpdateBulk)
protected.Delete("/coolify/apps/:uuid/envs/:env_id", controllers.CoolifyApplicationEnvDelete)
protected.Get("/coolify/apps/:uuid/start", controllers.CoolifyApplicationStart)
protected.Get("/coolify/apps/:uuid/stop", controllers.CoolifyApplicationStop)
protected.Get("/coolify/apps/:uuid/restart", controllers.CoolifyApplicationRestart)
protected.Get("/coolify/apps/:uuid/deployments", controllers.CoolifyApplicationDeployments)
protected.Post("/coolify/apps/:uuid/deploy", controllers.CoolifyApplicationDeploy)
// Servers
protected.Get("/coolify/servers", controllers.CoolifyListServers)
protected.Get("/coolify/servers/:uuid", controllers.CoolifyGetServer)
protected.Get("/coolify/servers/:uuid/resources", controllers.CoolifyServerResources)
protected.Get("/coolify/servers/:uuid/domains", controllers.CoolifyServerDomains)
protected.Get("/coolify/servers/:uuid/validate", controllers.CoolifyServerValidate)
// Services
protected.Get("/coolify/services", controllers.CoolifyListServices)
protected.Get("/coolify/services/:uuid", controllers.CoolifyGetService)
protected.Get("/coolify/services/:uuid/start", controllers.CoolifyServiceStart)
protected.Get("/coolify/services/:uuid/stop", controllers.CoolifyServiceStop)
protected.Get("/coolify/services/:uuid/restart", controllers.CoolifyServiceRestart)
protected.Get("/coolify/services/:uuid/envs", controllers.CoolifyServiceEnvs)
protected.Patch("/coolify/services/:uuid/envs", controllers.CoolifyServiceEnvUpdateBulk)
// Databases
protected.Get("/coolify/databases", controllers.CoolifyListDatabases)
protected.Get("/coolify/databases/:uuid", controllers.CoolifyGetDatabase)
protected.Get("/coolify/databases/:uuid/start", controllers.CoolifyDatabaseStart)
protected.Get("/coolify/databases/:uuid/stop", controllers.CoolifyDatabaseStop)
protected.Get("/coolify/databases/:uuid/restart", controllers.CoolifyDatabaseRestart)
// Projects
protected.Get("/coolify/projects", controllers.CoolifyListProjects)
protected.Get("/coolify/projects/:uuid", controllers.CoolifyGetProject)
protected.Get("/coolify/projects/:uuid/environments", controllers.CoolifyProjectEnvironments)
// Deployments
protected.Get("/coolify/deployments", controllers.CoolifyListDeployments)
protected.Get("/coolify/deployments/:uuid", controllers.CoolifyGetDeployment)
// Team
protected.Get("/coolify/team", controllers.CoolifyCurrentTeam)
protected.Get("/coolify/team/members", controllers.CoolifyTeamMembers)
protected.Get("/coolify/teams", controllers.CoolifyListTeams)
// ─── Pasarelas de Pago ────────────────────────────────────────────
protected.Get("/pasarelas-pago", middlewares.MenuMiddleware, controllers.PasarelasPage)
// Bold
protected.Get("/pasarelas/bold/config", controllers.GetBoldConfigAPI)
protected.Post("/pasarelas/bold/save", controllers.SaveBoldConfig)
protected.Get("/pasarelas/bold/logs", controllers.BoldWebhookLogs)
protected.Post("/pasarelas/bold/logs/:id/validar", controllers.ValidarBoldLog)
protected.Get("/pasarelas/bold/callbacks", controllers.BoldCallbackLogs)
protected.Post("/pasarelas/bold/callbacks/:id/validar", controllers.ValidarBoldCallback)
// dLocal
protected.Get("/pasarelas/dlocal/config", controllers.GetDlocalConfigAPI)
protected.Post("/pasarelas/dlocal/save", controllers.SaveDlocalConfigWeb)
protected.Get("/pasarelas/dlocal/logs", controllers.DlocalPaymentLogsPaginated)
protected.Post("/pasarelas/dlocal/logs/:id/validar", controllers.ValidarDlocalLog)
protected.Post("/pasarelas/dlocal/registro-pago", apiControllers.DlocalRegistrarPago)
// PayPal
protected.Get("/pasarelas/paypal/config", controllers.GetPaypalConfigAPI)
protected.Post("/pasarelas/paypal/save", controllers.SavePaypalConfigWeb)
// Bold API (crear link, consultar estado)
protected.Post("/pasarelas/bold/crear-link", apiControllers.BoldCreatePaymentLink)
protected.Get("/pasarelas/bold/link/:linkID", apiControllers.BoldGetLinkStatus)
// ─── Landing Generator (admin) ────────────────────────────────────────────
protected.Get("/landing-pages", middlewares.MenuMiddleware, apiControllers.LandingAdminList)
// ─── Productos SaaS ──────────────────────────────────────────────────────
protected.Get("/saas", middlewares.MenuMiddleware, controllers.SaasIndex)
protected.Get("/loadsaas", controllers.GetSaasProductos)
protected.Post("/saas", controllers.CreateSaasProducto)
protected.Put("/saas/:id", controllers.UpdateSaasProducto)
protected.Delete("/saas/:id", controllers.DeleteSaasProducto)
protected.Get("/saas/:id/health", controllers.HealthCheckSaas)
// ─── Documentación: categorías globales ──────────────────────────────────
protected.Get("/doc/categorias", middlewares.MenuMiddleware, controllers.DocCategoriasIndex)
protected.Get("/doc/loadcategorias", controllers.GetDocCategorias)
protected.Post("/doc/categorias", controllers.CreateDocCategoria)
protected.Put("/doc/categorias/:id", controllers.UpdateDocCategoria)
protected.Delete("/doc/categorias/:id", controllers.DeleteDocCategoria)
// ─── Documentación: páginas ───────────────────────────────────────────────
protected.Get("/doc/paginas", middlewares.MenuMiddleware, controllers.DocPaginasIndex)
protected.Get("/doc/loadpaginas", controllers.GetDocPaginas)
protected.Get("/doc/paginas/:id", controllers.GetDocPaginaDetalle)
protected.Post("/doc/paginas", controllers.CreateDocPagina)
protected.Put("/doc/paginas/:id", controllers.UpdateDocPagina)
protected.Delete("/doc/paginas/:id", controllers.DeleteDocPagina)
// ─── Documentación: lectura privada (usuario logueado) ───────────────────
protected.Get("/docs/:saas", middlewares.MenuMiddleware, controllers.DocsPrivadoIndex)
protected.Get("/docs/:saas/:slug", middlewares.MenuMiddleware, controllers.DocsPrivadaPagina)
// ─── Integraciones SaaS (dispatcher de pagos) ─────────────────────────────
protected.Get("/saas-api", middlewares.MenuMiddleware, controllers.SaasApiIndex)
protected.Get("/loadsaasapi", controllers.GetSaasApiConfigs)
protected.Post("/saas-api", controllers.CreateSaasApiConfig)
protected.Put("/saas-api/:id", controllers.UpdateSaasApiConfig)
protected.Delete("/saas-api/:id", controllers.DeleteSaasApiConfig)
protected.Post("/saas-api/:id/probar", controllers.ProbaSaasApiConfig)
// Logs de despacho
protected.Get("/saas-api/logs", middlewares.MenuMiddleware, controllers.SaasDispatchLogIndex)
protected.Get("/loadsaasdispatchlogs", controllers.GetSaasDispatchLogs)
// ─── Configuraciones de IA (Qwen, OpenAI, etc.) ─────────────────────────
protected.Get("/ai-config", middlewares.MenuMiddleware, controllers.AiConfigIndex)
protected.Get("/ai-config/list", controllers.GetAiConfigs)
protected.Get("/api/ai-config/select", controllers.GetAiConfigSelect)
protected.Post("/ai-config", controllers.CreateAiConfigHandler)
protected.Put("/ai-config/:id", controllers.UpdateAiConfigHandler)
protected.Delete("/ai-config/:id", controllers.DeleteAiConfigHandler)
protected.Get("/ai-config/:id/test", controllers.TestAiConfigHandler)
// ─── Pagos externos (API para que apps de terceros pidan cobros) ───────────
// Sensible: emitir/regenerar un token da acceso a crear cobros reales por
// Bold/dLocal/PayPal, así que solo un administrador puede administrarlo.
protected.Get("/pagos-externos", middlewares.MenuMiddleware, controllers.PagosExternosIndex)
protected.Get("/pagos-externos/servicios", controllers.GetServiciosPagoExterno)
protected.Post("/pagos-externos/servicios", middlewares.SoloAdmin, controllers.CreateServicioPagoExternoHandler)
protected.Put("/pagos-externos/servicios/:id", middlewares.SoloAdmin, controllers.UpdateServicioPagoExternoHandler)
protected.Delete("/pagos-externos/servicios/:id", middlewares.SoloAdmin, controllers.DeleteServicioPagoExternoHandler)
protected.Post("/pagos-externos/servicios/:id/regenerar-token", middlewares.SoloAdmin, controllers.RegenerarTokenServicioPagoHandler)
protected.Get("/pagos-externos/solicitudes", controllers.GetSolicitudesPagoExternoHandler)
// ─── API Keys de /api/v2 (token + IP obligatoria + scopes) ────────────────
// Muy sensible: un scope "usuarios" o "query_runner" filtrado equivale a
// dar acceso administrativo — solo un administrador puede administrarlas.
protected.Get("/api-keys", middlewares.MenuMiddleware, controllers.ApiKeysIndex)
protected.Get("/api-keys/list", controllers.GetApiKeys)
protected.Post("/api-keys", middlewares.SoloAdmin, controllers.CreateApiKeyHandler)
protected.Put("/api-keys/:id", middlewares.SoloAdmin, controllers.UpdateApiKeyHandler)
protected.Delete("/api-keys/:id", middlewares.SoloAdmin, controllers.DeleteApiKeyHandler)
protected.Post("/api-keys/:id/regenerar-token", middlewares.SoloAdmin, controllers.RegenerarApiKeyHandler)
// ─── uMind: chat con IA embebible por tenant ───────────────────────────────
// Sensible: un tenant queda ligado a una config de IA (API key) y controla
// desde qué dominios se puede llamar al widget, así que crear/editar es
// solo para administradores.
protected.Get("/umind", middlewares.MenuMiddleware, controllers.UmindIndex)
protected.Get("/umind/tenants", controllers.GetUmindTenants)
protected.Post("/umind/tenants", middlewares.SoloAdmin, controllers.CreateUmindTenantHandler)
protected.Put("/umind/tenants/:id", middlewares.SoloAdmin, controllers.UpdateUmindTenantHandler)
protected.Delete("/umind/tenants/:id", middlewares.SoloAdmin, controllers.DeleteUmindTenantHandler)
protected.Get("/umind/agentes", controllers.GetUmindAgentesHandler)
protected.Post("/umind/agentes", middlewares.SoloAdmin, controllers.CreateUmindAgenteHandler)
protected.Put("/umind/agentes/:id", middlewares.SoloAdmin, controllers.UpdateUmindAgenteHandler)
protected.Delete("/umind/agentes/:id", middlewares.SoloAdmin, controllers.DeleteUmindAgenteHandler)
protected.Get("/umind/documentos", controllers.GetUmindDocumentosHandler)
protected.Post("/umind/documentos", middlewares.SoloAdmin, controllers.CreateUmindDocumentoHandler)
protected.Delete("/umind/documentos/:id", middlewares.SoloAdmin, controllers.DeleteUmindDocumentoHandler)
protected.Get("/umind/sesiones", controllers.GetUmindSesionesHandler)
protected.Get("/umind/historial", controllers.GetUmindHistorialHandler)
protected.Get("/umind/tools", controllers.GetUmindHerramientasHandler)
protected.Post("/umind/tools", middlewares.SoloAdmin, controllers.CreateUmindHerramientaHandler)
protected.Put("/umind/tools/:id", middlewares.SoloAdmin, controllers.UpdateUmindHerramientaHandler)
protected.Delete("/umind/tools/:id", middlewares.SoloAdmin, controllers.DeleteUmindHerramientaHandler)
protected.Get("/umind/canales", controllers.GetUmindCanalesHandler)
protected.Post("/umind/canales", middlewares.SoloAdmin, controllers.CreateUmindCanalHandler)
protected.Put("/umind/canales/:id", middlewares.SoloAdmin, controllers.UpdateUmindCanalHandler)
protected.Delete("/umind/canales/:id", middlewares.SoloAdmin, controllers.DeleteUmindCanalHandler)
protected.Post("/umind/chat", controllers.UmindChatPruebaHandler)
protected.Get("/umind/conexiones", controllers.GetUmindConexionesHandler)
protected.Get("/umind/conexiones/conectar", middlewares.SoloAdmin, controllers.UmindConectarHandler)
protected.Get("/umind/conexiones/callback/:proveedor", controllers.UmindOAuthCallbackHandler)
protected.Delete("/umind/conexiones/:id", middlewares.SoloAdmin, controllers.DeleteUmindConexionHandler)
protected.Get("/umind/eventos", controllers.GetUmindEventosHandler)
protected.Get("/umind/uso", controllers.GetUmindUsoHandler)
// Planes: definen el límite de agentes y los precios por consumo. Solo staff.
protected.Get("/umind-planes", middlewares.MenuMiddleware, controllers.UmindPlanesPage)
protected.Get("/umind-planes/list", controllers.GetUmindPlanesHandler)
protected.Post("/umind-planes", middlewares.SoloAdmin, controllers.CreateUmindPlanHandler)
protected.Put("/umind-planes/:id", middlewares.SoloAdmin, controllers.UpdateUmindPlanHandler)
protected.Delete("/umind-planes/:id", middlewares.SoloAdmin, controllers.DeleteUmindPlanHandler)
// ─── uMind Orquestador (SPA Vue) ────────────────────────────────────────────
// Estáticos reales (JS/CSS del build) ya los sirve el Static("/") general
// registrado en config.LoadStatic — esto es solo el fallback para las rutas
// del lado del cliente (vue-router en modo history), protegido con sesión.
orchestratorFallback := func(c *fiber.Ctx) error {
return c.SendFile("./public/orchestrator/index.html")
}
app.Get("/orchestrator", middlewares.AuthWeb(), orchestratorFallback)
app.Get("/orchestrator/*", middlewares.AuthWeb(), orchestratorFallback)
// ─── OSS API (Alibaba Cloud + S3/MinIO) ────────────────────────────────────
protected.Get("/oss-api", middlewares.MenuMiddleware, controllers.OssApiIndex)
protected.Get("/loadossapi", controllers.GetOssApiConfigs)
protected.Get("/oss-api/active", controllers.GetActiveOssApiList)
protected.Post("/oss-api", controllers.CreateOssApiConfig)
protected.Put("/oss-api/:id", controllers.UpdateOssApiConfig)
protected.Delete("/oss-api/:id", controllers.DeleteOssApiConfig)
// Explorador de archivos OSS
protected.Get("/oss-api/browser", controllers.OssBrowserList)
protected.Get("/oss-api/browser/url", controllers.OssBrowserSignedURL)
protected.Delete("/oss-api/browser/object", controllers.OssBrowserDelete)
protected.Post("/oss-api/browser/upload", controllers.OssBrowserUpload)
// ─── VCard API (integración Admin Laravel) ────────────────────────────────
protected.Get("/vcard-api", middlewares.MenuMiddleware, controllers.VcardApiIndex)
protected.Post("/vcard-api/login", controllers.VcardApiLogin)
protected.Get("/vcard-api/config", controllers.VcardApiGetConfig)
protected.Post("/vcard-api/config", controllers.VcardApiSaveConfig)
// Usuarios (GET)
protected.Get("/vcard-api/usuarios", controllers.VcardApiUsuarios)
protected.Get("/vcard-api/usuarios/:id/membresia", controllers.VcardApiMembresia)
protected.Get("/vcard-api/usuarios/:userId/vcards", controllers.VcardApiVcardsByUsuario)
protected.Get("/vcard-api/usuarios/:userId/pagos", controllers.VcardApiPagosByUsuario)
protected.Get("/vcard-api/usuarios/:userId/transacciones", controllers.VcardApiTransaccionesByUsuario)
protected.Get("/vcard-api/usuarios/:userId/logs", controllers.VcardApiLogsByUsuario)
protected.Get("/vcard-api/usuarios/:userId/miniwebs", controllers.VcardApiMiniwebsByUsuario)
protected.Get("/vcard-api/usuarios/:id", controllers.VcardApiUsuario)
// Usuarios (mutaciones)
protected.Put("/vcard-api/usuarios/:id", controllers.VcardApiUsuarioUpdate)
protected.Post("/vcard-api/usuarios/:id/activar", controllers.VcardApiUsuarioActivar)
protected.Post("/vcard-api/usuarios/:id/desactivar", controllers.VcardApiUsuarioDesactivar)
protected.Post("/vcard-api/usuarios/:id/activar-membresia", controllers.VcardApiActivarMembresia)
protected.Post("/vcard-api/usuarios/:id/desactivar-membresia", controllers.VcardApiDesactivarMembresia)
protected.Post("/vcard-api/usuarios/:id/cambiar-plan", controllers.VcardApiCambiarPlan)
// VCards
protected.Get("/vcard-api/vcards", controllers.VcardApiVcards)
protected.Get("/vcard-api/vcards/:id", controllers.VcardApiVcard)
protected.Put("/vcard-api/vcards/:id", controllers.VcardApiVcardUpdate)
// Resto (solo GET)
protected.Get("/vcard-api/planes", controllers.VcardApiPlanes)
protected.Get("/vcard-api/planes/:id", controllers.VcardApiPlan)
protected.Put("/vcard-api/planes/:id", controllers.VcardApiPlanUpdate)
protected.Get("/vcard-api/pagos", controllers.VcardApiPagos)
protected.Get("/vcard-api/transacciones", controllers.VcardApiTransacciones)
protected.Get("/vcard-api/logs", controllers.VcardApiLogs)
protected.Get("/vcard-api/miniwebs", controllers.VcardApiMiniwebs)
protected.Get("/vcard-api/miniwebs/:id", controllers.VcardApiMiniweb)
// ─── Telegram ─────────────────────────────────────────────────────────────
protected.Get("/telegram", middlewares.MenuMiddleware, controllers.TelegramIndex)
protected.Get("/loadtelegram", controllers.GetTelegramConfigs)
protected.Post("/telegram", controllers.CreateTelegramConfig)
protected.Put("/telegram/:id", controllers.UpdateTelegramConfig)
protected.Delete("/telegram/:id", controllers.DeleteTelegramConfig)
protected.Post("/telegram/:id/test", controllers.TestTelegramConfig)
protected.Post("/telegram/send", controllers.SendTelegramNotification)
protected.Get("/telegram/logs", controllers.GetTelegramLogs)
protected.Post("/telegram/:id/set-portal-webhook", controllers.SetPortalWebhook)
protected.Get("/telegram/:id/webhook-info", controllers.GetPortalWebhookInfo)
// ─── Portal de Clientes ────────────────────────────────────────────────────
protected.Get("/proyectos", middlewares.MenuMiddleware, controllers.ProyectosIndex)
protected.Get("/loadproyectos", controllers.LoadProyectos)
protected.Post("/proyectos", controllers.CreateProyecto)
protected.Put("/proyectos/:id", controllers.UpdateProyecto)
protected.Delete("/proyectos/:id", controllers.DeleteProyecto)
protected.Get("/proyectos/:id/detalle", middlewares.MenuMiddleware, controllers.ProyectoDetalleIndex)
protected.Get("/proyectos/:id/fases", controllers.GetFases)
protected.Post("/proyectos/:id/fases", controllers.CreateFase)
protected.Put("/proyectos/:id/fases/:faseID", controllers.UpdateFase)
protected.Delete("/proyectos/:id/fases/:faseID", controllers.DeleteFase)
protected.Post("/proyectos/:id/fases/template", controllers.ApplyTemplate)
protected.Get("/proyectos/:id/avances", controllers.GetAvances)
protected.Post("/proyectos/:id/avances", controllers.CreateAvance)
protected.Put("/proyectos/:id/avances/:avID", controllers.UpdateAvance)
protected.Delete("/proyectos/:id/avances/:avID", controllers.DeleteAvance)
protected.Get("/proyectos/:id/entregables", controllers.GetEntregables)
protected.Post("/proyectos/:id/entregables", controllers.UploadEntregable)
protected.Delete("/proyectos/:id/entregables/:entID", controllers.DeleteEntregable)
protected.Get("/proyectos/:id/entregables/:entID/download", controllers.DownloadEntregable)
protected.Put("/proyectos/:id/entregables/:entID/visibilidad", controllers.UpdateEntregableVisibilidad)
protected.Get("/proyectos/:id/tickets", controllers.GetTickets)
protected.Put("/proyectos/:id/tickets/:ticketID/estado", controllers.UpdateTicketEstadoAdmin)
protected.Post("/proyectos/:id/tickets/:ticketID/mensaje", controllers.AdminResponderTicket)
protected.Get("/proyectos/:id/documentos", controllers.GetDocumentos)
protected.Post("/proyectos/:id/documentos", controllers.UploadDocumento)
protected.Delete("/proyectos/:id/documentos/:docID", controllers.DeleteDocumento)
protected.Get("/proyectos/:id/documentos/:docID/download", controllers.DownloadDocumento)
protected.Get("/portal-usuarios", middlewares.MenuMiddleware, controllers.PortalUsuariosIndex)
protected.Get("/loadportalusuarios", controllers.LoadPortalUsuarios)
protected.Get("/loadportalusuarios/:id", controllers.GetPortalUsuarioDetail)
protected.Post("/portal-usuarios", controllers.CreatePortalUsuario)
protected.Put("/portal-usuarios/:id", controllers.UpdatePortalUsuario)
protected.Delete("/portal-usuarios/:id", controllers.DeletePortalUsuario)
protected.Get("/portal-usuarios/:id/rut-file", controllers.PortalUsuarioRutFile)
protected.Post("/portal-usuarios/:id/acceso", controllers.AddPortalAcceso)
protected.Delete("/portal-usuarios/:id/acceso/:clienteID", controllers.RemovePortalAcceso)
protected.Post("/portal-usuarios/:id/send-credentials", controllers.SendPortalCredentials)
protected.Get("/facturas", middlewares.MenuMiddleware, controllers.FacturasIndex)
protected.Get("/loadfacturas", controllers.LoadFacturas)
protected.Post("/facturas", controllers.CreateFactura)
protected.Put("/facturas/:id", controllers.UpdateFactura)
protected.Delete("/facturas/:id", controllers.DeleteFactura)
protected.Post("/facturas/:id/upload-pdf", controllers.UploadFacturaPDF)
protected.Get("/facturas/:id/download", controllers.DownloadFacturaPDF)
// ─── USITE Shield ─────────────────────────────────────────────────────────
protected.Get("/shield", middlewares.MenuMiddleware, controllers.ShieldIndex)
protected.Get("/loadshield", controllers.LoadShieldConfig)
protected.Post("/saveshield", controllers.SaveShieldConfig)
protected.Get("/shield/health", controllers.ShieldHealth)
protected.Get("/shield/extension-version", controllers.ShieldExtensionVersion)
protected.Get("/shield/logs", controllers.ShieldLogs)
protected.Get("/shield/logs/stats", controllers.ShieldLogStats)
protected.Get("/shield/review-requests", controllers.ShieldReviewRequests)
protected.Put("/shield/review-requests/:id/approve", controllers.ShieldApproveRequest)
protected.Put("/shield/review-requests/:id/reject", controllers.ShieldRejectRequest)
protected.Get("/shield/whitelist", controllers.ShieldWhitelist)
protected.Post("/shield/whitelist", controllers.ShieldAddWhitelist)
protected.Delete("/shield/whitelist/:domain", controllers.ShieldDeleteWhitelist)
protected.Get("/shield/blacklist", controllers.ShieldBlacklist)
protected.Post("/shield/blacklist", controllers.ShieldAddBlacklist)
protected.Delete("/shield/blacklist/:domain", controllers.ShieldDeleteBlacklist)
protected.Get("/shield/reputation/:domain", controllers.ShieldReputation)
protected.Put("/shield/reputation/:domain/score", controllers.ShieldAdjustScore)
// Tickets global (todos los proyectos)
protected.Get("/tickets", middlewares.MenuMiddleware, controllers.TicketsAdminIndex)
protected.Get("/tickets/data", controllers.GetAllTicketsAdmin)
protected.Put("/tickets/:ticketID/estado", controllers.UpdateTicketEstadoAdmin)
protected.Post("/tickets/:ticketID/mensaje", controllers.AdminResponderTicket)
protected.Put("/tickets/:ticketID/asignar", controllers.AsignarTicket)
protected.Get("/tickets/admins", controllers.GetSoporteAdmins)
// Configuración webhook de soporte
protected.Get("/soporte/webhook", middlewares.MenuMiddleware, controllers.SoporteWebhookConfigPage)
protected.Get("/soporte/webhook/data", controllers.GetSoporteWebhookConfig)
protected.Post("/soporte/webhook", controllers.SaveSoporteWebhookConfig)
// Configuración de notificaciones
protected.Get("/notif-config", middlewares.MenuMiddleware, controllers.NotifConfigIndex)
protected.Get("/notif-config/data", controllers.GetNotifConfigs)
protected.Post("/notif-config", controllers.SaveNotifConfig)
// Umbrales de alerta de servidores
protected.Get("/servidor-alerta-config", controllers.GetServidorAlertaConfig)
protected.Post("/servidor-alerta-config", controllers.SaveServidorAlertaConfig)
// Partner Recursos (documentación y comunicados para partners)
protected.Get("/partner-recursos", middlewares.MenuMiddleware, controllers.PartnerRecursosIndex)
protected.Get("/partner-recursos/data", controllers.LoadPartnerRecursos)
protected.Post("/partner-recursos", controllers.CreatePartnerRecurso)
protected.Put("/partner-recursos/:id", controllers.UpdatePartnerRecurso)
protected.Delete("/partner-recursos/:id", controllers.DeletePartnerRecurso)
protected.Post("/partner-recursos/:id/upload", controllers.UploadPartnerRecursoArchivo)
protected.Get("/partner-recursos/:id/download", controllers.DownloadPartnerRecurso)
protected.Get("/partner-comunicados/data", controllers.LoadPartnerComunicados)
protected.Post("/partner-comunicados", controllers.CreatePartnerComunicado)
protected.Put("/partner-comunicados/:id", controllers.UpdatePartnerComunicado)
protected.Delete("/partner-comunicados/:id", controllers.DeletePartnerComunicado)
protected.Post("/partner-comunicados/:id/upload", controllers.UploadPartnerComunicadoArchivo)
protected.Get("/partner-comunicados/:id/download", controllers.DownloadPartnerComunicadoArchivo)
// Notificaciones in-app del admin (bell)
protected.Get("/mis-notifs", controllers.GetMisNotifs)
protected.Put("/mis-notifs/:id/leida", controllers.MarcarNotifLeida)
protected.Post("/mis-notifs/marcar-todas", controllers.MarcarTodasLeidas)
// ─── Contabilidad ─────────────────────────────────────────────────────────
protected.Get("/contabilidad", middlewares.MenuMiddleware, controllers.ContabilidadIndex)
protected.Get("/contabilidad/dashboard", controllers.ContabilidadDashboard)
protected.Get("/contabilidad/consolidado", controllers.ContabilidadConsolidado)
protected.Get("/contabilidad/consolidados", controllers.ContabilidadListConsolidados)
// Transacciones
protected.Get("/contabilidad/transacciones", middlewares.MenuMiddleware, controllers.ContabilidadTransaccionesView)
protected.Get("/contabilidad/transacciones/list", controllers.GetTransacciones)
protected.Post("/contabilidad/transacciones", controllers.CreateTransaccion)
protected.Put("/contabilidad/transacciones/:id", controllers.UpdateTransaccion)
protected.Delete("/contabilidad/transacciones/:id", controllers.DeleteTransaccion)
// Cuentas (categorías contables)
protected.Get("/contabilidad/cuentas", middlewares.MenuMiddleware, controllers.ContabilidadCuentasView)
protected.Get("/contabilidad/cuentas/list", controllers.GetCuentas)
protected.Get("/contabilidad/cuentas/select", controllers.GetCuentasSelect)
protected.Post("/contabilidad/cuentas", controllers.CreateCuenta)
protected.Put("/contabilidad/cuentas/:id", controllers.UpdateCuenta)
protected.Delete("/contabilidad/cuentas/:id", controllers.DeleteCuenta)
// Entidades
protected.Get("/contabilidad/entidades", middlewares.MenuMiddleware, controllers.ContabilidadEntidadesView)
protected.Get("/contabilidad/entidades/list", controllers.GetEntidades)
protected.Get("/contabilidad/entidades/select", controllers.GetEntidadesSelect)
protected.Post("/contabilidad/entidades", controllers.CreateEntidad)
protected.Put("/contabilidad/entidades/:id", controllers.UpdateEntidad)
protected.Delete("/contabilidad/entidades/:id", controllers.DeleteEntidad)
// Cuentas por cobrar
protected.Get("/contabilidad/cuentas-cobro", middlewares.MenuMiddleware, controllers.ContabilidadCobroView)
protected.Get("/contabilidad/cuentas-cobro/list", controllers.GetCuentasCobro)
protected.Post("/contabilidad/cuentas-cobro", controllers.CreateCuentaCobro)
protected.Put("/contabilidad/cuentas-cobro/:id", controllers.UpdateCuentaCobro)
protected.Delete("/contabilidad/cuentas-cobro/:id", controllers.DeleteCuentaCobro)
protected.Post("/contabilidad/cuentas-cobro/:id/pagar", controllers.MarcarCuentaCobroPagada)
protected.Post("/contabilidad/cuentas-cobro/:id/generar-documento", controllers.GenerarDocumentoCuentaCobro)
// Cuentas por pagar
protected.Get("/contabilidad/cuentas-pagar", middlewares.MenuMiddleware, controllers.ContabilidadPagarView)
protected.Get("/contabilidad/cuentas-pagar/list", controllers.GetCuentasPagar)
protected.Post("/contabilidad/cuentas-pagar", controllers.CreateCuentaPagar)
protected.Put("/contabilidad/cuentas-pagar/:id", controllers.UpdateCuentaPagar)
protected.Post("/contabilidad/cuentas-pagar/:id/pagar", controllers.MarcarCuentaPagarPagada)
protected.Delete("/contabilidad/cuentas-pagar/:id", controllers.DeleteCuentaPagar)
protected.Get("/contabilidad/cuentas-pagar/:id/archivo", controllers.DownloadCuentaPagarArchivo)
// ─── WebSMS (LabsMobile) ───────────────────────────────────────────────────
protected.Get("/websms", middlewares.MenuMiddleware, controllers.WebSmsConfigPage)
protected.Get("/websms/config", controllers.GetWebSmsConfig)
protected.Post("/websms/save", controllers.SaveWebSmsConfig)
protected.Post("/websms/test", controllers.TestWebSms)
protected.Get("/websms/logs", controllers.GetWebSmsLogs)
protected.Get("/websms/webhook-logs", controllers.GetWebSmsWebhookLogs)
// ─── OCR (servicio propio) ─────────────────────────────────────────────────
protected.Get("/ocr", middlewares.MenuMiddleware, controllers.OcrConfigPage)
protected.Get("/ocr/config", controllers.GetOcrConfigHandler)
protected.Post("/ocr/save", controllers.SaveOcrConfigHandler)
protected.Post("/ocr/test", controllers.TestOcrConfigHandler)
// ─── Whisper ASR (transcripción, servicio propio) ─────────────────────────
protected.Get("/whisper-asr", middlewares.MenuMiddleware, controllers.WhisperAsrConfigPage)
protected.Get("/whisper-asr/config", controllers.GetWhisperAsrConfigHandler)
protected.Post("/whisper-asr/save", controllers.SaveWhisperAsrConfigHandler)
protected.Post("/whisper-asr/test", controllers.TestWhisperAsrConfigHandler)
// ─── Planes dLocal (gestión desde panel protegido) ────────────────────────
protected.Get("/dlocal/planes", apiControllers.SeePlanes)
protected.Post("/dlocal/planes", apiControllers.CreatePlan)
protected.Get("/dlocal/planes/:planID", apiControllers.SeePlan)
protected.Patch("/dlocal/planes/:planID", apiControllers.UpdatedPlan)
protected.Patch("/dlocal/planes/:planID/subscription/:subscriptionId/deactivate", apiControllers.DeactivatePlan)
}