from concurrent.futures import ThreadPoolExecutor import pytest from fastapi.testclient import TestClient from apps.server.auth import Auth, password_hash, password_matches from apps.server.db import Store, identifier, now from apps.server.main import create_app class UnusedWorker: async def close(self): pass def test_default_admin_is_hashed_and_can_log_in(tmp_path): app = create_app(tmp_path, UnusedWorker(), database_url="") with TestClient(app, base_url="http://127.0.0.1") as client: status = client.get("/api/auth/status").json() assert status["initialized"] and not status["authenticated"] client.headers["X-CSRF-Token"] = status["csrf_token"] login = client.post("/api/auth/login", json={"username": "admin", "password": "123456"}) assert login.status_code == 200 assert login.json()["user"]["username"] == "admin" stored = app.state.store.one("SELECT password_hash FROM operators WHERE username='admin'")["password_hash"] assert stored.startswith("scrypt$") and password_matches("123456", stored) @pytest.mark.parametrize("username", ["admin", "existing-maintainer"]) def test_restart_preserves_existing_account_and_password(tmp_path, username): store = Store(tmp_path) stored = password_hash("Existing-password-4831") account_id, created_at = identifier("operator"), now() store.execute("INSERT INTO operators VALUES(?,?,?,?)", (account_id, username, stored, created_at)) before = store.rows("SELECT * FROM operators") # Repeated normal starts cannot replace a changed admin hash or add an admin # alongside a different already initialized maintainer. first = create_app(tmp_path, UnusedWorker(), database_url="") second = create_app(tmp_path, UnusedWorker(), database_url="") assert first.state.store.rows("SELECT * FROM operators") == before assert second.state.store.rows("SELECT * FROM operators") == before assert not password_matches("123456", stored) def test_concurrent_bootstrap_creates_exactly_one_admin(tmp_path): store = Store(tmp_path) with ThreadPoolExecutor(max_workers=4) as pool: created = list(pool.map(lambda _: Auth(store).bootstrap_admin(), range(4))) assert created.count(True) == 1 and created.count(False) == 3 rows = store.rows("SELECT * FROM operators") assert len(rows) == 1 and rows[0]["username"] == "admin" assert password_matches("123456", rows[0]["password_hash"])