Files
soft_usite/rest/routes/user.go
T
Lizandro GuarnizoandClaude Opus 5 8c3ab79e88 feat(soporte): leer el buzón por IMAP, no solo esperar el webhook
Los clientes escriben a soporte@ desde su correo de siempre. Hasta ahora eso
solo llegaba si un proveedor (SendGrid/Mailgun) nos hacía POST; si nadie lo
configuraba, los correos quedaban sin leer en el buzón.

Ahora el cron entra al buzón cada 2 minutos, baja los no leídos, abre ticket
(o los engancha al hilo si son respuesta) y los marca como leídos. La lógica
de ingesta se movió a services para que webhook e IMAP se comporten igual.

La contraseña del buzón se guarda cifrada (AES-GCM con APP_KEY) y no vuelve
al navegador.

De paso, dos bugs que impedían guardar la configuración: el formulario mandaba
id=0 (gorm.Model serializa "ID"), así que cada guardado creaba una fila nueva
en vez de editar la que se usa; y Updates con struct ignoraba los booleanos en
false, así que desactivar algo no tenía efecto.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 18:36:08 -05:00

645 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", middlewares.RequiereModulo("/app/modules"), 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", middlewares.RequiereModulo("/app/roles"), 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", middlewares.RequiereModulo("/app/submodules"), 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", middlewares.RequiereModulo("/app/users"), 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", middlewares.RequiereModulo("/app/users"), 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", middlewares.RequiereModulo("/app/doc/categorias"), controllers.GetDocCategorias)
protected.Post("/doc/categorias", middlewares.RequiereModulo("/app/doc/categorias"), controllers.CreateDocCategoria)
protected.Put("/doc/categorias/:id", middlewares.RequiereModulo("/app/doc/categorias"), controllers.UpdateDocCategoria)
protected.Delete("/doc/categorias/:id", middlewares.RequiereModulo("/app/doc/categorias"), controllers.DeleteDocCategoria)
// ─── Documentación: páginas ───────────────────────────────────────────────
protected.Get("/doc/paginas", middlewares.MenuMiddleware, controllers.DocPaginasIndex)
protected.Get("/doc/loadpaginas", middlewares.RequiereModulo("/app/doc/paginas"), controllers.GetDocPaginas)
protected.Get("/doc/paginas/:id", middlewares.RequiereModulo("/app/doc/paginas"), controllers.GetDocPaginaDetalle)
protected.Post("/doc/paginas", middlewares.RequiereModulo("/app/doc/paginas"), controllers.CreateDocPagina)
protected.Put("/doc/paginas/:id", middlewares.RequiereModulo("/app/doc/paginas"), controllers.UpdateDocPagina)
protected.Delete("/doc/paginas/:id", middlewares.RequiereModulo("/app/doc/paginas"), 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)
// Las escrituras siguen siendo SoloAdmin del lado del staff; el alcance
// (qué tenants ve cada quien) lo decide el middleware de scope, que es el
// mismo contrato para /app/umind y /portal/umind.
RegistrarRutasUmind(protected, middlewares.UmindScopeStaff, middlewares.SoloAdmin)
protected.Post("/umind/tenants", middlewares.SoloAdmin, middlewares.UmindScopeStaff, controllers.CreateUmindTenantHandler)
protected.Put("/umind/tenants/:id", middlewares.SoloAdmin, middlewares.UmindScopeStaff, controllers.UpdateUmindTenantHandler)
protected.Delete("/umind/tenants/:id", middlewares.SoloAdmin, middlewares.UmindScopeStaff, controllers.DeleteUmindTenantHandler)
protected.Get("/umind/conexiones/callback/:proveedor", middlewares.UmindScopeStaff, controllers.UmindOAuthCallbackHandler)
// 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 Studio (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.
studioFallback := func(c *fiber.Ctx) error {
return c.SendFile("./public/orchestrator/index.html")
}
app.Get("/studio", middlewares.AuthWeb(), studioFallback)
app.Get("/studio/*", middlewares.AuthWeb(), studioFallback)
// /orchestrator era la URL vieja: redirige para no romper los enlaces que
// alguien haya guardado. Los assets del build siguen viviendo bajo
// /orchestrator/assets (es el base del bundle), así que solo se redirige
// la navegación, no los estáticos.
redirigirAStudio := func(c *fiber.Ctx) error {
return c.Redirect(destinoStudio(c.Path()), fiber.StatusMovedPermanently)
}
app.Get("/orchestrator", middlewares.AuthWeb(), redirigirAStudio)
app.Get("/orchestrator/*", middlewares.AuthWeb(), func(c *fiber.Ctx) error {
if esAssetDelBundle(c.Path()) {
return c.Next()
}
return redirigirAStudio(c)
})
// ─── 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)
protected.Post("/soporte/webhook/probar-imap", controllers.ProbarImapSoporte)
protected.Post("/soporte/webhook/revisar-buzon", controllers.RevisarBuzonAhora)
// 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)
}