fix(api-keys): no se podía asignar el scope vcard
La pantalla lo ofrecía y las rutas de /api/v2/vcard lo exigen, pero la lista de scopes válidos del backend nunca lo incluyó: crear la llave devolvía "scope inválido: vcard" y la integración de vCard no tenía forma de autenticarse. La lista estaba escrita dos veces —una en Go y otra en el HTML— y se desincronizaron. Ahora la vista la pide al backend, así que no puede volver a ofrecer algo que el backend rechace, y un test fija que todo scope exigido por las rutas se pueda asignar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
4135850e5b
commit
dda5898c0d
@@ -105,7 +105,9 @@
|
||||
<div>
|
||||
<label class="block text-xs font-medium text-gray-600 mb-2">Scopes *</label>
|
||||
<div class="border border-gray-200 rounded-lg p-3 space-y-2 bg-gray-50">
|
||||
<template x-for="s in ['oss', 'query_runner', 'usuarios', 'pasarelas', 'vcard']" :key="s">
|
||||
<!-- La lista viene del backend: cuando estaba escrita acá, la
|
||||
pantalla ofrecía scopes que el backend rechazaba al guardar. -->
|
||||
<template x-for="s in scopesDisponibles" :key="s">
|
||||
<label class="flex items-center gap-2 cursor-pointer select-none">
|
||||
<input type="checkbox" :checked="form.scopes.includes(s)"
|
||||
@change="toggleScope(s)" class="rounded text-[#8eb02f] focus:ring-[#8eb02f]">
|
||||
@@ -191,8 +193,15 @@ function apiKeysApp() {
|
||||
showModal: false, editItem: null, deleteId: null, regenerarId: null, tokenResult: null,
|
||||
errorMsg: '', successMsg: '', formError: '',
|
||||
form: { nombre: '', ip_permitida: '', scopes: [], activa: true },
|
||||
scopesDisponibles: [],
|
||||
|
||||
async init() { await this.load() },
|
||||
async init() {
|
||||
try {
|
||||
const r = await fetch('/app/api-keys/scopes')
|
||||
this.scopesDisponibles = await r.json()
|
||||
} catch { this.scopesDisponibles = [] }
|
||||
await this.load()
|
||||
},
|
||||
|
||||
async load() {
|
||||
this.loading = true; this.errorMsg = ''
|
||||
|
||||
@@ -2,6 +2,7 @@ package controllers
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -17,6 +18,20 @@ var scopesValidos = map[string]bool{
|
||||
"query_runner": true,
|
||||
"usuarios": true,
|
||||
"pasarelas": true,
|
||||
"vcard": true,
|
||||
}
|
||||
|
||||
// ScopesDisponibles devuelve la lista para que la vista la muestre en vez de
|
||||
// tener su propia copia: la copia de la vista ya ofreció "vcard" cuando el
|
||||
// backend todavía lo rechazaba.
|
||||
// GET /app/api-keys/scopes
|
||||
func ScopesDisponibles(c *fiber.Ctx) error {
|
||||
lista := make([]string, 0, len(scopesValidos))
|
||||
for s := range scopesValidos {
|
||||
lista = append(lista, s)
|
||||
}
|
||||
sort.Strings(lista)
|
||||
return c.JSON(lista)
|
||||
}
|
||||
|
||||
// ApiKeysIndex renderiza el panel de administración de API keys.
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package controllers
|
||||
|
||||
import "testing"
|
||||
|
||||
// La pantalla ofrecía "vcard" mientras el backend lo rechazaba al guardar, y el
|
||||
// único síntoma era "scope inválido: vcard" al crear la llave. Los scopes que
|
||||
// las rutas de /api/v2 exigen con RequireScope tienen que poder asignarse.
|
||||
func TestScopesDeLasRutasSonAsignables(t *testing.T) {
|
||||
// Sacados de los RequireScope() de rest/routes.
|
||||
usadosEnRutas := []string{"oss", "query_runner", "usuarios", "pasarelas", "vcard"}
|
||||
for _, s := range usadosEnRutas {
|
||||
if !scopesValidos[s] {
|
||||
t.Errorf("las rutas exigen el scope %q pero no se puede asignar a una API key", s)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -346,6 +346,7 @@ func UserRoutes(app fiber.Router) {
|
||||
// dar acceso administrativo — solo un administrador puede administrarlas.
|
||||
protected.Get("/api-keys", middlewares.MenuMiddleware, controllers.ApiKeysIndex)
|
||||
protected.Get("/api-keys/list", controllers.GetApiKeys)
|
||||
protected.Get("/api-keys/scopes", controllers.ScopesDisponibles)
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user