"""Test-Setup: frische SQLite-DB je Testlauf, kein EZB-Netzabruf.""" import os import secrets import tempfile # Umgebung setzen, BEVOR app importiert wird (config wird beim Import gelesen). os.environ.setdefault("APP_DATA_DIR", tempfile.mkdtemp(prefix="cf-test-")) os.environ.setdefault("APP_ECB_FETCH_ON_START", "false") os.environ.setdefault("APP_ADMIN_USERNAME", "admin") # Muss die Standard-Passwortrichtlinie erfüllen (Länge 10, Gross/Klein/Ziffer), # sonst verlangt der erste Login sofort einen Wechsel und alle Tests scheitern. os.environ.setdefault("APP_ADMIN_PASSWORD", "AdminPass1") os.environ.setdefault("APP_SESSION_SECRET", "test-secret") import pytest from fastapi.testclient import TestClient ADMIN_PASSWORD = "AdminPass1" @pytest.fixture() def client(): from app.main import app with TestClient(app) as c: yield c @pytest.fixture() def admin(client): r = client.post("/api/auth/login", data={"username": "admin", "password": ADMIN_PASSWORD}) assert r.status_code == 200 return client def new_password() -> str: """Zufälliges, richtlinienkonformes Testpasswort.""" return "Pw1_" + secrets.token_hex(4) def new_user(admin_client) -> tuple[str, str]: """Legt (als Admin) einen frischen Nutzer an und gibt (username, passwort) zurück.""" username = "u_" + secrets.token_hex(4) password = new_password() r = admin_client.post("/api/users", json={"username": username, "password": password, "role": "user"}) assert r.status_code == 201, r.text return username, password @pytest.fixture() def policy_admin(admin): """Admin-Client für Tests, die die Passwortrichtlinie verändern. Die Testdatenbank lebt über den ganzen Testlauf und die Richtlinie ist global – ohne Zurücksetzen würde eine Verschärfung alle folgenden Tests kippen. Zurückgesetzt wird bewusst direkt über die Dienstschicht, nicht über die API: wer ``mfa_required`` einschaltet, sperrt sich damit selbst aus ``PUT /policy`` aus, bis er einen zweiten Faktor eingerichtet hat. Über die API bliebe die Verschärfung also stehen.""" from app.database import SessionLocal from app.services import policy as policy_service vorher = admin.get("/api/policy").json() try: yield admin finally: db = SessionLocal() try: policy_service.save(db, policy_service.Policy(**vorher)) finally: db.close() def login_ready(username: str, password: str) -> tuple[TestClient, str]: """Meldet einen frisch angelegten Nutzer an und erledigt den Pflichtwechsel. Vom Admin angelegte Konten tragen ``must_change_password``; solange das offen ist, sperrt der Server alle fachlichen Endpunkte. Für Tests, die den Nutzer einfach benutzen wollen, wird der Wechsel hier gleich mit erledigt. Gibt den angemeldeten Client und das nun gültige Passwort zurück.""" from app.main import app c = TestClient(app) r = c.post("/api/auth/login", data={"username": username, "password": password}) assert r.status_code == 200, r.text neu = new_password() r = c.post( "/api/auth/change-password", json={"current_password": password, "new_password": neu}, ) assert r.status_code == 200, r.text return c, neu