feat: Add API key authentication for backup tool

- Add get_api_key() and require_api_key() to auth.py
- Add generic key-value settings storage to SettingsStore
- Add test_api_key_auth to verify the implementation
- Uses secrets.compare_digest for timing-safe comparison
- Auto-generates API key on first use and stores in settings DB
This commit is contained in:
2026-05-11 21:25:46 +02:00
parent f912623677
commit 836f733a2e
31 changed files with 2014 additions and 1 deletions
+47
View File
@@ -60,6 +60,53 @@ def test_create_job_and_run():
assert run["status"] == "success"
def test_api_key_auth():
with tempfile.TemporaryDirectory() as tmpdir:
db_path = Path(tmpdir) / "test_settings.sqlite"
store = SettingsStore(db_path)
store.init_schema()
from fastapi import HTTPException
from media_library_viewer_api.auth import get_api_key, require_api_key
from media_library_viewer_api.services import settings_store
# Monkey-patch the global store for this test
original_store = settings_store._store
settings_store._store = store
# Reset the cached API key
import media_library_viewer_api.auth as auth_module
auth_module._API_KEY = None
try:
# Should generate and return an API key
api_key = get_api_key()
assert api_key
assert len(api_key) > 0
# Should raise 401 without key
try:
require_api_key("")
assert False, "Should have raised"
except HTTPException as e:
assert e.status_code == 401
# Should raise 401 with wrong key
try:
require_api_key("Bearer wrong-key")
assert False, "Should have raised"
except HTTPException as e:
assert e.status_code == 401
# Should succeed with correct key
result = require_api_key(f"Bearer {api_key}")
assert result == f"Bearer {api_key}"
finally:
settings_store._store = original_store
auth_module._API_KEY = None
def test_alert_failed_status():
from media_library_viewer_api.services.backup_alert_engine import generate_alerts_for_run