Agrega API Keys scoped (token + IP obligatoria + alcance) para /api/v2
Alternativa al ADMIN_API_KEY único de entorno, que sigue funcionando como llave maestra para no romper integraciones existentes. - Modelo ApiKey: token hasheado, IP/CIDR obligatoria (fail-closed sin IP), scopes habilitados, último uso (fecha + IP). - AdminApiAuth() acepta ahora tanto la llave maestra como una ApiKey; nuevo middleware RequireScope(scope) para gatear grupos de rutas. - Fase 1: scopes aplicados a lo más sensible — oss (archivos), query_runner (SQL arbitrario), usuarios (usuarios/roles/módulos), pasarelas (credenciales de pago). El resto de /api/v2 sigue con la llave maestra hasta una fase 2. - Panel /app/api-keys: crear/editar/revocar, token visible solo al crear, scopes por checkbox, IP obligatoria.
This commit is contained in:
+59
-42
@@ -12,30 +12,31 @@ func AdminApiRoutes(api fiber.Router) {
|
||||
// ─── Spec (documentación completa de la API) ─────────────────────────────
|
||||
h.Get("/spec", controllers.AdminApiSpec)
|
||||
|
||||
// ─── Usuarios ────────────────────────────────────────────────────────────
|
||||
h.Get("/users", controllers.GetUsers)
|
||||
h.Get("/users/:id", controllers.GetUser)
|
||||
h.Post("/users", controllers.CreateUser)
|
||||
h.Put("/users/:id", controllers.UpdateUser)
|
||||
h.Delete("/users/:id", controllers.DeleteUser)
|
||||
// ─── Usuarios / Roles / Módulos / Submódulos ─────────────────────────────
|
||||
// Todo el sistema de permisos queda bajo un único scope "usuarios": una
|
||||
// ApiKey con este scope puede crear/editar cuentas y roles, así que es
|
||||
// tan sensible como tener acceso administrativo completo al panel.
|
||||
admin := h.Group("", middlewares.RequireScope("usuarios"))
|
||||
admin.Get("/users", controllers.GetUsers)
|
||||
admin.Get("/users/:id", controllers.GetUser)
|
||||
admin.Post("/users", controllers.CreateUser)
|
||||
admin.Put("/users/:id", controllers.UpdateUser)
|
||||
admin.Delete("/users/:id", controllers.DeleteUser)
|
||||
|
||||
// ─── Roles ───────────────────────────────────────────────────────────────
|
||||
h.Get("/roles", controllers.GetRoles)
|
||||
h.Post("/roles", controllers.CreateRole)
|
||||
h.Put("/roles/:id", controllers.UpdateRole)
|
||||
h.Delete("/roles/:id", controllers.DeleteRole)
|
||||
admin.Get("/roles", controllers.GetRoles)
|
||||
admin.Post("/roles", controllers.CreateRole)
|
||||
admin.Put("/roles/:id", controllers.UpdateRole)
|
||||
admin.Delete("/roles/:id", controllers.DeleteRole)
|
||||
|
||||
// ─── Módulos ─────────────────────────────────────────────────────────────
|
||||
h.Get("/modules", controllers.GetModules)
|
||||
h.Post("/modules", controllers.CreateModule)
|
||||
h.Put("/modules/:id", controllers.UpdateModule)
|
||||
h.Delete("/modules/:id", controllers.DeleteModule)
|
||||
admin.Get("/modules", controllers.GetModules)
|
||||
admin.Post("/modules", controllers.CreateModule)
|
||||
admin.Put("/modules/:id", controllers.UpdateModule)
|
||||
admin.Delete("/modules/:id", controllers.DeleteModule)
|
||||
|
||||
// ─── Submódulos ──────────────────────────────────────────────────────────
|
||||
h.Get("/submodules", controllers.GetSubmodules)
|
||||
h.Post("/submodules", controllers.CreateSubmodule)
|
||||
h.Put("/submodules/:id", controllers.UpdateSubmodule)
|
||||
h.Delete("/submodules/:id", controllers.DeleteSubmodule)
|
||||
admin.Get("/submodules", controllers.GetSubmodules)
|
||||
admin.Post("/submodules", controllers.CreateSubmodule)
|
||||
admin.Put("/submodules/:id", controllers.UpdateSubmodule)
|
||||
admin.Delete("/submodules/:id", controllers.DeleteSubmodule)
|
||||
|
||||
// ─── Servidores ──────────────────────────────────────────────────────────
|
||||
h.Get("/servidores", controllers.GetServidor)
|
||||
@@ -270,6 +271,13 @@ func AdminApiRoutes(api fiber.Router) {
|
||||
h.Post("/pagos-externos/servicios/:id/regenerar-token", controllers.RegenerarTokenServicioPagoHandler)
|
||||
h.Get("/pagos-externos/solicitudes", controllers.GetSolicitudesPagoExternoHandler)
|
||||
|
||||
// ─── API Keys de /api/v2 ────────────────────────────────────────────────
|
||||
h.Get("/api-keys", controllers.GetApiKeys)
|
||||
h.Post("/api-keys", controllers.CreateApiKeyHandler)
|
||||
h.Put("/api-keys/:id", controllers.UpdateApiKeyHandler)
|
||||
h.Delete("/api-keys/:id", controllers.DeleteApiKeyHandler)
|
||||
h.Post("/api-keys/:id/regenerar-token", controllers.RegenerarApiKeyHandler)
|
||||
|
||||
// ─── uMind: chat con IA embebible por tenant ───────────────────────────────
|
||||
h.Get("/umind/tenants", controllers.GetUmindTenants)
|
||||
h.Post("/umind/tenants", controllers.CreateUmindTenantHandler)
|
||||
@@ -282,15 +290,18 @@ func AdminApiRoutes(api fiber.Router) {
|
||||
h.Get("/umind/historial", controllers.GetUmindHistorialHandler)
|
||||
|
||||
// ─── OSS API (almacenamiento) ────────────────────────────────────────────
|
||||
// La gestión de credenciales de storage (CRUD de config) queda solo para
|
||||
// la llave maestra; el scope "oss" de una ApiKey solo permite operar
|
||||
// archivos (subir/listar/borrar), no ver ni cambiar las credenciales.
|
||||
h.Get("/oss-api", controllers.GetOssApiConfigs)
|
||||
h.Get("/oss-api/active", controllers.GetActiveOssApiList)
|
||||
h.Post("/oss-api", controllers.CreateOssApiConfig)
|
||||
h.Put("/oss-api/:id", controllers.UpdateOssApiConfig)
|
||||
h.Delete("/oss-api/:id", controllers.DeleteOssApiConfig)
|
||||
h.Get("/oss-api/browser", controllers.OssBrowserList)
|
||||
h.Get("/oss-api/browser/url", controllers.OssBrowserSignedURL)
|
||||
h.Delete("/oss-api/browser/object", controllers.OssBrowserDelete)
|
||||
h.Post("/oss-api/browser/upload", controllers.OssBrowserUpload)
|
||||
h.Get("/oss-api/browser", middlewares.RequireScope("oss"), controllers.OssBrowserList)
|
||||
h.Get("/oss-api/browser/url", middlewares.RequireScope("oss"), controllers.OssBrowserSignedURL)
|
||||
h.Delete("/oss-api/browser/object", middlewares.RequireScope("oss"), controllers.OssBrowserDelete)
|
||||
h.Post("/oss-api/browser/upload", middlewares.RequireScope("oss"), controllers.OssBrowserUpload)
|
||||
|
||||
// ─── Telegram ────────────────────────────────────────────────────────────
|
||||
h.Get("/telegram", controllers.GetTelegramConfigs)
|
||||
@@ -340,25 +351,31 @@ func AdminApiRoutes(api fiber.Router) {
|
||||
h.Get("/websms/logs", controllers.GetWebSmsLogs)
|
||||
|
||||
// ─── Pasarelas de pago ───────────────────────────────────────────────────
|
||||
h.Get("/pasarelas/bold/config", controllers.GetBoldConfigAPI)
|
||||
h.Post("/pasarelas/bold/save", controllers.SaveBoldConfig)
|
||||
h.Get("/pasarelas/bold/logs", controllers.BoldWebhookLogs)
|
||||
h.Get("/pasarelas/dlocal/config", controllers.GetDlocalConfigAPI)
|
||||
h.Post("/pasarelas/dlocal/save", controllers.SaveDlocalConfigWeb)
|
||||
h.Get("/pasarelas/dlocal/logs", controllers.DlocalPaymentLogsPaginated)
|
||||
h.Get("/pasarelas/paypal/config", controllers.GetPaypalConfigAPI)
|
||||
h.Post("/pasarelas/paypal/save", controllers.SavePaypalConfigWeb)
|
||||
// Credenciales de Bold/dLocal/PayPal: scope "pasarelas" propio.
|
||||
pasarelas := h.Group("/pasarelas", middlewares.RequireScope("pasarelas"))
|
||||
pasarelas.Get("/bold/config", controllers.GetBoldConfigAPI)
|
||||
pasarelas.Post("/bold/save", controllers.SaveBoldConfig)
|
||||
pasarelas.Get("/bold/logs", controllers.BoldWebhookLogs)
|
||||
pasarelas.Get("/dlocal/config", controllers.GetDlocalConfigAPI)
|
||||
pasarelas.Post("/dlocal/save", controllers.SaveDlocalConfigWeb)
|
||||
pasarelas.Get("/dlocal/logs", controllers.DlocalPaymentLogsPaginated)
|
||||
pasarelas.Get("/paypal/config", controllers.GetPaypalConfigAPI)
|
||||
pasarelas.Post("/paypal/save", controllers.SavePaypalConfigWeb)
|
||||
|
||||
// ─── Query Runner ────────────────────────────────────────────────────────
|
||||
h.Get("/query-runner/connections", controllers.GetConxDbList)
|
||||
h.Get("/query-runner/databases", controllers.GetDatabases)
|
||||
h.Get("/query-runner/tables", controllers.GetTables)
|
||||
h.Get("/query-runner/relations", controllers.GetRelations)
|
||||
h.Get("/query-runner/test", controllers.TestConnection)
|
||||
h.Post("/query-runner/run", controllers.RunQuery)
|
||||
h.Post("/query-runner/run-batch", controllers.RunBatchQuery)
|
||||
h.Get("/query-runner/history", controllers.GetHistory)
|
||||
h.Get("/query-runner/columns", controllers.GetTableColumnsHandler)
|
||||
// SQL arbitrario contra cualquier conexión configurada: es de lo más
|
||||
// sensible que expone /api/v2, así que una ApiKey scoped necesita el
|
||||
// scope "query_runner" explícito para todo este grupo.
|
||||
qr := h.Group("/query-runner", middlewares.RequireScope("query_runner"))
|
||||
qr.Get("/connections", controllers.GetConxDbList)
|
||||
qr.Get("/databases", controllers.GetDatabases)
|
||||
qr.Get("/tables", controllers.GetTables)
|
||||
qr.Get("/relations", controllers.GetRelations)
|
||||
qr.Get("/test", controllers.TestConnection)
|
||||
qr.Post("/run", controllers.RunQuery)
|
||||
qr.Post("/run-batch", controllers.RunBatchQuery)
|
||||
qr.Get("/history", controllers.GetHistory)
|
||||
qr.Get("/columns", controllers.GetTableColumnsHandler)
|
||||
|
||||
// ─── Hostinger ───────────────────────────────────────────────────────────
|
||||
h.Get("/hostinger/vps", controllers.GetHostingerVPS)
|
||||
|
||||
@@ -341,6 +341,16 @@ func UserRoutes(app fiber.Router) {
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user