Add DB viewer access logging, account deletion, and forced password change

Logs a distinct db_viewer_accessed event (not just the earlier
session_created "requested" event) when an admin's browser actually
completes the hand-off into Adminer. Adds a password-confirmed
account-deletion box to Settings, relying on the existing ON DELETE
CASCADE foreign keys to clean up everything the account owns. Adds an
admin-only "require password change" flag that get_current_user
enforces server-side (403 on everything except /auth/me,
/auth/change-password, /auth/logout) - meant for handing a demo
account to someone with a known sample password.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
2026-08-05 23:41:21 -04:00
co-authored by Claude Sonnet 5
parent 3d6fe56991
commit 4ee38b6241
23 changed files with 1056 additions and 7 deletions
+13 -1
View File
@@ -100,12 +100,24 @@ async def test_bootstrap_with_a_valid_token_sets_a_session_cookie_and_redirects(
"/api/v1/db-viewer/bootstrap", params={"token": token}, follow_redirects=False
)
assert resp.status_code == 302
assert resp.headers["location"] == "/"
assert resp.headers["location"] == "/?pgsql=postgres"
assert "db_viewer_session" in resp.headers["set-cookie"]
assert "HttpOnly" in resp.headers["set-cookie"]
assert "Secure" in resp.headers["set-cookie"]
async def test_bootstrap_success_is_logged_to_the_admins_account_activity(
client: TestClient, db_session: AsyncSession
):
headers = await _register_admin_and_login(client, db_session)
token = client.post("/api/v1/db-viewer/session", headers=headers).json()["token"]
client.get("/api/v1/db-viewer/bootstrap", params={"token": token}, follow_redirects=False)
events = client.get("/api/v1/auth/security-events", headers=headers).json()
assert any(e["event_type"] == "db_viewer_accessed" for e in events)
def test_bootstrap_rejects_a_garbage_token(client: TestClient):
resp = client.get(
"/api/v1/db-viewer/bootstrap", params={"token": "not-a-real-token"}, follow_redirects=False