Kanbante 0.47.0 — HUB-23 : métadonnées des jetons kbt_ pour le registre du Hub (GET /api/jetons/metadonnees, cookie draco relayé, métadonnées seulement)
CI / test (pull_request) Failing after 1s
CI / test (push) Failing after 2m34s

This commit is contained in:
Spark
2026-11-06 17:01:31 +00:00
parent bb0cc2c72b
commit 8993656948
5 changed files with 228 additions and 2 deletions
+54 -1
View File
@@ -439,7 +439,7 @@ class AuthMiddleware(BaseHTTPMiddleware):
# lieu à la première connexion par le pont /auth/draco.
# Les preflights OPTIONS ne portent jamais de cookies : ils
# sont répondus par RechercheCorsMiddleware avant d'arriver ici.
if path == "/api/search":
if path in ("/api/search", "/api/jetons/metadonnees"):
try:
from app import accounts as accounts_service
from app import draco
@@ -7160,6 +7160,59 @@ async def api_projects():
return {"active": active, "inactive": inactive, "archived": archived}
@app.get("/api/jetons/metadonnees")
async def api_jetons_metadonnees(request: Request):
"""Métadonnées des jetons `kbt_` pour le registre du Hub (HUB-23).
Le Hub interroge cette route côté serveur en relayant le cookie
`draco_session` de l'administrateur connecté (même patron que
/api/search : correspondance par utilisateur exigée, aucun JIT —
l'amorçage de l'unique compte admin reste possible, comme sur
/api/search). Un administrateur Kanbante reçoit les métadonnées
de tous les jetons ; tout autre compte, seulement les siennes.
Métadonnées seulement : nom, propriétaire, préfixe `kbt_`,
création, dernier usage, état (actif / révoqué). La valeur du
jeton n'existe plus après sa création et l'empreinte SHA-256 ne
quitte jamais la base : aucun des deux ne figure ici.
"""
from app import accounts as accounts_service
from app import draco
claims = draco.claims_for(request)
user = (
accounts_service.resolve_draco_user(claims)
if claims is not None
else None
)
if user is None:
return JSONResponse(
{"ok": False, "error": "Authentification draco requise"},
status_code=401,
)
if user["role"] == "admin":
lignes = models.list_all_api_tokens()
portee = "tous"
else:
lignes = [
{**t, "proprietaire": user["username"]}
for t in models.list_api_tokens(user["id"])
]
portee = "propres"
jetons = [
{
"nom": t["name"],
"proprietaire": t["proprietaire"],
"prefixe": models.API_TOKEN_PREFIX,
"cree_le": t["created_at"],
"dernier_usage": t["last_used_at"],
"etat": "revoque" if t["revoked_at"] else "actif",
}
for t in lignes
]
return {"jetons": jetons, "portee": portee}
@app.get("/api/health")
async def health():
"""Liveness probe: the process is up. Deliberately dependency-free."""