"""T2.10 Admin 管理后台 + 审计日志测试。 测试 Admin API 的系统概览、租户管理、用户管理和审计日志查询。 """ import uuid as uuid_mod import pytest from fastapi.testclient import TestClient from sqlalchemy.ext.asyncio import AsyncSession from app.core.audit import log_audit from app.models.tenant import Tenant from app.models.user import User from tests.conftest import test_session_factory @pytest.fixture def admin_headers(client: TestClient): """注册并登录 admin 用户,返回认证头。""" client.post( "/api/v1/auth/register", json={ "email": "admin_test@example.com", "password": "password123", "name": "管理员", "tenant_name": "管理机构", "role": "admin", }, ) resp = client.post( "/api/v1/auth/login", json={"email": "admin_test@example.com", "password": "password123"}, ) token = resp.json()["data"]["access_token"] return {"Authorization": f"Bearer {token}"} @pytest.fixture def investor_headers(client: TestClient): """注册并登录 investor 用户,返回认证头。""" client.post( "/api/v1/auth/register", json={ "email": "investor_admin_test@example.com", "password": "password123", "name": "投资人", "tenant_name": "投资人机构", "role": "investor", }, ) resp = client.post( "/api/v1/auth/login", json={"email": "investor_admin_test@example.com", "password": "password123"}, ) token = resp.json()["data"]["access_token"] return {"Authorization": f"Bearer {token}"} @pytest.fixture async def db_session(): """创建数据库会话。""" async with test_session_factory() as session: yield session await session.rollback() class TestAdminOverview: """系统概览测试。""" def test_overview_as_admin(self, client: TestClient, admin_headers: dict): """admin 可以访问概览。""" resp = client.get("/api/v1/admin/overview", headers=admin_headers) assert resp.status_code == 200 data = resp.json()["data"] assert "tenant_count" in data assert "user_count" in data def test_overview_as_investor_forbidden(self, client: TestClient, investor_headers: dict): """investor 无权访问 admin 概览。""" resp = client.get("/api/v1/admin/overview", headers=investor_headers) assert resp.status_code == 403 def test_overview_no_auth(self, client: TestClient): """无认证返回 401。""" resp = client.get("/api/v1/admin/overview") assert resp.status_code == 401 class TestAdminTenants: """租户管理测试。""" def test_list_tenants(self, client: TestClient, admin_headers: dict): """admin 可以查看租户列表。""" resp = client.get("/api/v1/admin/tenants", headers=admin_headers) assert resp.status_code == 200 assert isinstance(resp.json()["data"], list) class TestAdminUsers: """用户管理测试。""" def test_list_users(self, client: TestClient, admin_headers: dict): """admin 可以查看用户列表。""" resp = client.get("/api/v1/admin/users", headers=admin_headers) assert resp.status_code == 200 assert isinstance(resp.json()["data"], list) class TestAdminAuditLogs: """审计日志测试。""" def test_list_audit_logs(self, client: TestClient, admin_headers: dict): """admin 可以查看审计日志。""" resp = client.get("/api/v1/admin/audit-logs", headers=admin_headers) assert resp.status_code == 200 assert isinstance(resp.json()["data"], list) async def test_log_audit(self, db_session: AsyncSession): """审计日志写入测试。""" unique = uuid_mod.uuid4().hex[:8] tenant = Tenant(name=f"audit机构_{unique}") db_session.add(tenant) await db_session.flush() user = User( email=f"audit_{unique}@example.com", name="审计测试用户", role="admin", tenant_id=tenant.id, password_hash="fake_hash", is_active=True, ) db_session.add(user) await db_session.flush() await log_audit(db_session, str(user.id), "CREATE", "company", "comp-123", {"name": "测试公司"}, tenant_id=str(tenant.id)) await db_session.commit() from sqlalchemy import select from app.models.audit import AuditLog result = await db_session.execute(select(AuditLog).where(AuditLog.resource_id == "comp-123")) log = result.scalar_one_or_none() assert log is not None assert log.action == "CREATE" assert log.resource_type == "company"