Weisse Seite beheben: Swagger lokal ausliefern, Startseite ergänzen
Zwei Fehler, beide erst im Browser sichtbar: 1. /docs blieb weiss. FastAPI holt Swagger von cdn.jsdelivr.net, und die in Phase 3 eingeführte CSP (script-src 'self') blockiert das zu Recht. Die Dateien liegen jetzt unter app/static/swagger/ im Repository - das funktioniert auch ohne Internet und ruft keinen fremden Server auf, aus demselben Grund, aus dem die Kantone-App ihre Schriften lokal ausliefert. Das Favicon holte FastAPI ebenfalls von aussen; auch das ist jetzt lokal. 2. Die Wurzel / lieferte ein nacktes 404-JSON - im Browser sieht das aus wie eine kaputte Anwendung. Jetzt eine schlichte Platzhalter-Seite, bis die Galerie in Phase 4 steht. Ausserdem beim Testen aufgefallen: eine lokale .env-Datei reicht ADMIN_PASSWORD auch dann herein, wenn die Umgebungsvariable gelöscht wird - bei pydantic-settings haben Umgebungsvariablen Vorrang, ein leerer Wert überstimmt die Datei, ein Löschen nicht. Der Test setzt jetzt leer statt zu löschen; im Betrieb ist das dieselbe Falle. Der neue Test prüft, dass /docs keinen einzigen Verweis auf einen fremden Host enthält - genau das würde sonst unbemerkt wieder hereinrutschen. 61 Tests, alle grün. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GR4bNaj9GtRu57J4Niii8o
This commit is contained in:
+37
-2
@@ -40,8 +40,15 @@ def test_falsches_passwort(gast):
|
||||
|
||||
|
||||
def test_ohne_passwort_ist_der_bereich_gesperrt(gast, monkeypatch, kategorie_id):
|
||||
"""Ohne hinterlegtes Passwort bleibt gesperrt statt offen zu stehen."""
|
||||
monkeypatch.delenv("ADMIN_PASSWORD", raising=False)
|
||||
"""Ohne hinterlegtes Passwort bleibt gesperrt statt offen zu stehen.
|
||||
|
||||
Leerer Wert statt delenv: Umgebungsvariablen haben bei pydantic-settings
|
||||
Vorrang vor der .env-Datei. Ein blosses Löschen brächte hier gar nichts,
|
||||
weil eine lokale .env den Wert sonst wieder hereinreicht - dieselbe
|
||||
Falle, die auch im Betrieb zuschlagen kann.
|
||||
"""
|
||||
monkeypatch.setenv("ADMIN_PASSWORD", "")
|
||||
monkeypatch.setenv("ADMIN_PASSWORD_HASH", "")
|
||||
einstellungen.cache_clear()
|
||||
security.hash_zwischenspeicher_leeren()
|
||||
|
||||
@@ -168,3 +175,31 @@ def test_robots_txt_sperrt_suchmaschinen(gast):
|
||||
antwort = gast.get("/robots.txt")
|
||||
assert antwort.status_code == 200
|
||||
assert "Disallow: /" in antwort.text
|
||||
|
||||
|
||||
def test_startseite_antwortet(gast):
|
||||
"""Ohne eigene Route lieferte die Wurzel ein nacktes 404-JSON - im
|
||||
Browser sieht das aus wie eine kaputte Anwendung."""
|
||||
antwort = gast.get("/")
|
||||
assert antwort.status_code == 200
|
||||
assert "Kinderkleider-Börse" in antwort.text
|
||||
|
||||
|
||||
def test_swagger_laedt_nichts_von_fremden_servern(gast):
|
||||
"""Die mitgelieferte /docs-Seite holt Swagger von cdn.jsdelivr.net.
|
||||
Die CSP (script-src 'self') blockiert das zu Recht - die Seite bliebe
|
||||
weiss. Ausserdem ginge dabei die IP jedes Besuchers an einen Dritten.
|
||||
"""
|
||||
import re
|
||||
|
||||
antwort = gast.get("/docs")
|
||||
assert antwort.status_code == 200
|
||||
|
||||
# Kein einziger Verweis auf einen anderen Host
|
||||
fremde = re.findall(r'(?:src|href)="(https?:)?//[^"]+"', antwort.text)
|
||||
assert not fremde, f"lädt von aussen: {fremde}"
|
||||
assert "/static/swagger/swagger-ui-bundle.js" in antwort.text
|
||||
|
||||
# Und die Dateien sind auch wirklich da
|
||||
assert gast.get("/static/swagger/swagger-ui-bundle.js").status_code == 200
|
||||
assert gast.get("/static/swagger/swagger-ui.css").status_code == 200
|
||||
|
||||
Reference in New Issue
Block a user