feat(09-01): implement GET /api/admin/overview endpoint — ADMIN-11

- New backend/api/admin/overview.py: aggregate stats (user_count,
  total_storage_bytes, doc_status) + last 10 audit entries in one payload
- Sub-router carries NO prefix (parent __init__.py carries /api/admin)
- Reuses _build_filtered_query_with_handles + _audit_to_dict_with_handles
  from api.audit — no new serializer or query logic
- Registered overview_router on admin parent router in __init__.py
- All 8 ADMIN-11 tests pass; existing admin and audit suites stay green
This commit is contained in:
curo1305
2026-06-12 15:50:38 +02:00
parent 4caeed2d22
commit 41d81c089f
3 changed files with 54 additions and 8 deletions
-8
View File
@@ -90,7 +90,6 @@ async def admin_client(db_session: AsyncSession):
@pytest.mark.asyncio
@pytest.mark.xfail(strict=True, reason="ADMIN-11: overview endpoint not yet implemented")
async def test_overview_requires_admin(async_client: AsyncClient):
"""Unauthenticated GET /api/admin/overview returns 401 or 403."""
resp = await async_client.get("/api/admin/overview")
@@ -98,7 +97,6 @@ async def test_overview_requires_admin(async_client: AsyncClient):
@pytest.mark.asyncio
@pytest.mark.xfail(strict=True, reason="ADMIN-11: overview endpoint not yet implemented")
async def test_overview_non_admin_forbidden(db_session: AsyncSession):
"""Regular-user JWT returns 403 from GET /api/admin/overview."""
from main import app
@@ -116,7 +114,6 @@ async def test_overview_non_admin_forbidden(db_session: AsyncSession):
@pytest.mark.asyncio
@pytest.mark.xfail(strict=True, reason="ADMIN-11: overview endpoint not yet implemented")
async def test_overview_returns_expected_keys(admin_client):
"""Admin GET returns 200 with all four top-level keys present."""
c, admin, session = admin_client
@@ -128,7 +125,6 @@ async def test_overview_returns_expected_keys(admin_client):
@pytest.mark.asyncio
@pytest.mark.xfail(strict=True, reason="ADMIN-11: overview endpoint not yet implemented")
async def test_overview_user_count_excludes_admins(admin_client):
"""user_count reflects only role='user' accounts, not admins."""
c, admin, session = admin_client
@@ -146,7 +142,6 @@ async def test_overview_user_count_excludes_admins(admin_client):
@pytest.mark.asyncio
@pytest.mark.xfail(strict=True, reason="ADMIN-11: overview endpoint not yet implemented")
async def test_overview_total_storage_sums_quotas(admin_client):
"""total_storage_bytes sums used_bytes across all Quota rows."""
c, admin, session = admin_client
@@ -173,7 +168,6 @@ async def test_overview_total_storage_sums_quotas(admin_client):
@pytest.mark.asyncio
@pytest.mark.xfail(strict=True, reason="ADMIN-11: overview endpoint not yet implemented")
async def test_overview_doc_status_groups_by_status(admin_client):
"""doc_status maps each status to its count."""
c, admin, session = admin_client
@@ -204,7 +198,6 @@ async def test_overview_doc_status_groups_by_status(admin_client):
@pytest.mark.asyncio
@pytest.mark.xfail(strict=True, reason="ADMIN-11: overview endpoint not yet implemented")
async def test_overview_recent_audit_limit_10(admin_client):
"""recent_audit returns at most 10 entries ordered newest first."""
c, admin, session = admin_client
@@ -240,7 +233,6 @@ async def test_overview_recent_audit_limit_10(admin_client):
@pytest.mark.asyncio
@pytest.mark.xfail(strict=True, reason="ADMIN-11: overview endpoint not yet implemented")
async def test_overview_no_sensitive_fields(admin_client):
"""Response body must not contain any sensitive field name."""
c, admin, session = admin_client