初始化提交

This commit is contained in:
chenxin committed 2026-08-21 16:00:13 +08:00
commit 887c1f449e
963 files changed
+166869

No files matched your search

+110
View File
@@ -0,0 +1,110 @@
"""管理端点鉴权(require_admin)测试。
覆盖四种情形:ADMIN_TOKEN 未配置 → 503(fail-closed,避免裸奔);已配置但缺凭证 /
凭证错误 → 401;正确凭证放行。探针端点用 ``/api/v1/admin/traces``(不依赖沙箱运行时,
测试环境可正常返回,便于判定鉴权层是否放行)。
"""
from collections.abc import AsyncGenerator
import pytest
from httpx import ASGITransport, AsyncClient
from app.main import app
_PROBE = "/api/v1/admin/traces"
@pytest.fixture
async def client() -> AsyncGenerator[AsyncClient, None]:
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://test") as http_client:
yield http_client
@pytest.mark.asyncio
async def test_admin_unconfigured_returns_503(
client: AsyncClient, monkeypatch: pytest.MonkeyPatch
) -> None:
"""ADMIN_TOKEN 与 JWT_SECRET 均未配置时管理端点 fail-closed(503)。"""
monkeypatch.setattr("app.api.v1.deps.settings.admin_token", "")
monkeypatch.setattr("app.api.v1.deps.settings.jwt_secret", "")
resp = await client.get(_PROBE)
assert resp.status_code == 503
@pytest.mark.asyncio
async def test_admin_missing_credential_returns_401(
client: AsyncClient, monkeypatch: pytest.MonkeyPatch
) -> None:
"""已配置 ADMIN_TOKEN 但请求未带 Authorization 头 → 401。"""
monkeypatch.setattr("app.api.v1.deps.settings.admin_token", "secret-token")
monkeypatch.setattr("app.api.v1.deps.settings.jwt_secret", "")
resp = await client.get(_PROBE)
assert resp.status_code == 401
@pytest.mark.asyncio
async def test_admin_wrong_credential_returns_401(
client: AsyncClient, monkeypatch: pytest.MonkeyPatch
) -> None:
"""Authorization 凭证错误 → 401。"""
monkeypatch.setattr("app.api.v1.deps.settings.admin_token", "secret-token")
monkeypatch.setattr("app.api.v1.deps.settings.jwt_secret", "")
resp = await client.get(_PROBE, headers={"Authorization": "Bearer wrong"})
assert resp.status_code == 401
@pytest.mark.asyncio
async def test_admin_correct_credential_passes(
client: AsyncClient, monkeypatch: pytest.MonkeyPatch
) -> None:
"""正确凭证放行:鉴权层不再拦截。"""
monkeypatch.setattr("app.api.v1.deps.settings.admin_token", "secret-token")
monkeypatch.setattr("app.api.v1.deps.settings.jwt_secret", "")
resp = await client.get(_PROBE, headers={"Authorization": "Bearer secret-token"})
assert resp.status_code != 401
# ═══════════════════════════════════════════════════════════════
# JWT 模式测试
# ═══════════════════════════════════════════════════════════════
@pytest.mark.asyncio
async def test_admin_jwt_admin_user_passes(
client: AsyncClient, monkeypatch: pytest.MonkeyPatch
) -> None:
"""拥有 is_admin 标记的用户 JWT 放行 /admin/*。"""
monkeypatch.setattr("app.api.v1.deps.settings.jwt_secret", "test-jwt-secret")
from app.db.session import AsyncSessionLocal
from app.services.auth import create_access_token, create_user
async with AsyncSessionLocal() as session:
user = await create_user(
session, username="adminuser", email="admin@test.com", password="pass", is_admin=True
)
await session.commit()
token = create_access_token(subject=user.id, extra={"owner_scope": user.id})
resp = await client.get(_PROBE, headers={"Authorization": f"Bearer {token}"})
assert resp.status_code != 401
assert resp.status_code != 403
@pytest.mark.asyncio
async def test_admin_jwt_non_admin_returns_403(
client: AsyncClient, monkeypatch: pytest.MonkeyPatch
) -> None:
"""普通用户 JWT 访问 /admin/* → 403。"""
monkeypatch.setattr("app.api.v1.deps.settings.jwt_secret", "test-jwt-secret")
from app.db.session import AsyncSessionLocal
from app.services.auth import create_access_token, create_user
async with AsyncSessionLocal() as session:
user = await create_user(
session, username="regular", email="regular@test.com", password="pass", is_admin=False
)
await session.commit()
token = create_access_token(subject=user.id, extra={"owner_scope": user.id})
resp = await client.get(_PROBE, headers={"Authorization": f"Bearer {token}"})
assert resp.status_code == 403