2026-06-20 18:50:55 +02:00
|
|
|
"""Tests für das Audit-Logging der Admin-Aktionen."""
|
|
|
|
|
|
|
|
|
|
import logging
|
|
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
from fastapi.testclient import TestClient
|
|
|
|
|
|
|
|
|
|
from app.main import app
|
|
|
|
|
from app.config import settings
|
|
|
|
|
from app.runtime_config import invalidate_cache
|
|
|
|
|
|
|
|
|
|
client = TestClient(app)
|
|
|
|
|
ADMIN = "test-admin-key"
|
|
|
|
|
ADM_HDR = {"X-Admin-Key": ADMIN}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
|
|
|
def _setup(monkeypatch):
|
|
|
|
|
monkeypatch.setattr(settings, "admin_api_key", ADMIN)
|
|
|
|
|
monkeypatch.setattr(settings, "auth_enabled", False)
|
|
|
|
|
invalidate_cache()
|
|
|
|
|
yield
|
|
|
|
|
invalidate_cache()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_config_set_is_audited(caplog):
|
|
|
|
|
with caplog.at_level(logging.INFO, logger="va.audit"):
|
|
|
|
|
r = client.put("/api/admin/config/local_llm_top_p",
|
|
|
|
|
json={"value": "0.7"}, headers=ADM_HDR)
|
|
|
|
|
assert r.status_code == 200
|
|
|
|
|
line = "\n".join(caplog.messages)
|
|
|
|
|
assert "action=config_set" in line
|
|
|
|
|
assert "local_llm_top_p" in line
|
|
|
|
|
assert "user=admin-key" in line
|
|
|
|
|
# aufräumen
|
|
|
|
|
client.delete("/api/admin/config/local_llm_top_p", headers=ADM_HDR)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_backend_switch_rejection_is_audited(caplog):
|
|
|
|
|
with caplog.at_level(logging.INFO, logger="va.audit"):
|
|
|
|
|
r = client.post("/api/admin/llm/backend",
|
|
|
|
|
json={"backend": "boese"}, headers=ADM_HDR)
|
|
|
|
|
assert r.status_code == 422
|
|
|
|
|
assert "action=llm_backend_switch_rejected" in "\n".join(caplog.messages)
|
2026-06-20 20:08:10 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_me_exposes_allow_cloud_stt():
|
|
|
|
|
# /api/me liefert das Datenschutz-Flag (Client-Gate für Geräte-STT).
|
|
|
|
|
d = client.get("/api/me").json()
|
|
|
|
|
assert "allow_cloud_stt" in d
|
|
|
|
|
assert isinstance(d["allow_cloud_stt"], bool)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_allow_cloud_stt_runtime_settable():
|
|
|
|
|
from app.runtime_config import RUNTIME_SETTABLE
|
|
|
|
|
assert "allow_cloud_stt" in RUNTIME_SETTABLE
|
|
|
|
|
r = client.put("/api/admin/config/allow_cloud_stt", json={"value": "true"}, headers=ADM_HDR)
|
|
|
|
|
assert r.status_code == 200
|
|
|
|
|
assert client.get("/api/me").json()["allow_cloud_stt"] is True
|
|
|
|
|
client.delete("/api/admin/config/allow_cloud_stt", headers=ADM_HDR)
|