Plugin neuheiten: Bearer-Token-Pflicht der BGG-XML-API2 (Fix für HTTP 401)
BoardGameGeek verlangt für die XML API2 jetzt Bearer-Authentifizierung
(Thread 3602374); ohne Token antwortet die API mit 401.
- BggClient: neuer Parameter token, sendet Authorization: Bearer … auf
allen Requests; Token kommt aus SPIELE_BGG_TOKEN (vor jedem Sync gelesen)
- HTTP 401 → klarer BggAuthFehler ('BGG hat die Anfrage abgelehnt (401) —
bitte gültigen API-Token in SPIELE_BGG_TOKEN hinterlegen.') statt
generischer Meldung, kein Retry
- Ohne konfigurierten Token wird der Sync übersprungen ('Kein BGG-API-Token
konfiguriert (SPIELE_BGG_TOKEN) — Sync übersprungen.'), statt Requests zu
feuern; Meldung erscheint im Sync-Ergebnis, UI-Banner und Protokoll
- SyncService: BggAuthFehler bricht den Lauf ab (weitere Suchbegriffe
scheitern zwangsläufig gleich), Teilergebnisse bleiben erhalten
- Tests: Bearer-Header, 401-Fall (Client/Sync/UI), Skip ohne Token;
bestehende Sync-UI-Tests setzen Test-Token
- README: neue Env-Variable SPIELE_BGG_TOKEN + Hinweis auf Token-Pflicht
This commit is contained in:
@@ -8,8 +8,10 @@ from sqlalchemy.orm import sessionmaker
|
||||
from redaktionskern.db import Base
|
||||
|
||||
from tests._neuheiten import (
|
||||
BggAuthFehler,
|
||||
BggFehler,
|
||||
BggSpiel,
|
||||
MELDUNG_401,
|
||||
Neuheit,
|
||||
SuchTreffer,
|
||||
SyncService,
|
||||
@@ -217,6 +219,31 @@ def test_prototyp_heuristik():
|
||||
# ---------- Robustheit ----------
|
||||
|
||||
|
||||
def test_401_bricht_sync_ab_mit_klarer_meldung(session_factory):
|
||||
"""BGG-401: Lauf stoppt, Meldung landet im Ergebnis, Teilergebnisse bleiben."""
|
||||
|
||||
class AuthKaputterClient(FakeBggClient):
|
||||
def suche(self, suchbegriff: str, *, max_treffer: int | None = None):
|
||||
self.suche_aufrufe.append(suchbegriff)
|
||||
if suchbegriff == "abgelehnt":
|
||||
raise BggAuthFehler(MELDUNG_401)
|
||||
return list(self.suchergebnisse.get(suchbegriff, []))
|
||||
|
||||
client = AuthKaputterClient(
|
||||
suchergebnisse={"gut": [SuchTreffer(13, "Catan", 1995)]},
|
||||
details_pro_id={13: _spiel()},
|
||||
)
|
||||
service = SyncService(session_factory, client)
|
||||
|
||||
ergebnis = service.synchronisiere(["gut", "abgelehnt", "dritter"])
|
||||
|
||||
assert ergebnis.abbruch == MELDUNG_401
|
||||
assert ergebnis.als_text() == MELDUNG_401 # klare Meldung statt Fehlerzähler
|
||||
assert ergebnis.neu == 1 # Teilergebnis vor dem 401 bleibt erhalten
|
||||
assert client.suche_aufrufe == ["gut", "abgelehnt"] # kein weiterer Begriff
|
||||
assert len(_alle_eintraege(session_factory)) == 1 # Commit trotz Abbruch
|
||||
|
||||
|
||||
def test_fehler_bei_einem_suchbegriff_bricht_lauf_nicht_ab(session_factory):
|
||||
class HalbKaputterClient(FakeBggClient):
|
||||
def suche(self, suchbegriff: str, *, max_treffer: int | None = None):
|
||||
|
||||
Reference in New Issue
Block a user