AgentEvalTool/tests/integration/test_auth_api.py
sinohqb 739d586aec feat(backend): v0.4 triggered_by tracking, login gate, compare guard, dashboard stats
- EvalRun.triggered_by 全链路(manual/ai_assistant/cli)+ 迁移 b7d4e6f81c22
- 标准 agenteval-run SKILL.md 纳入版本管理,deploy 脚本同步 + API Key 注入
- 简单登录:AGENTEVAL_ADMIN_PASSWORD + HMAC 会话 token,require_auth 双凭据
- 对比报告限同场景(400)+ 空 results 误判修复
- /api/stats/dashboard 扩展聚合;/api/runs 返回场景/对象名
- 测试 218 → 232
2026-07-28 17:40:54 +08:00

90 lines
3.2 KiB
Python

"""Integration tests for the login gate: /api/auth/* and require_auth."""
import pytest
from fastapi.testclient import TestClient
from sqlmodel import Session, SQLModel, create_engine
from agenteval.config.settings import Settings
from agenteval.web.app import app
from agenteval.web.deps import get_db
@pytest.fixture()
def client_with_db(tmp_path):
from agenteval.storage.db import ( # noqa: F401
EvalResultDB, EvalRunDB, EvalTargetDB, ScenarioDB, TurnDB,
)
engine = create_engine(
f"sqlite:///{tmp_path / 'auth_api.db'}",
connect_args={"check_same_thread": False},
)
SQLModel.metadata.create_all(engine)
session = Session(engine)
def override_get_db():
try:
yield session
finally:
pass
app.dependency_overrides[get_db] = override_get_db
client = TestClient(app)
yield client
app.dependency_overrides.clear()
session.close()
def _patch_settings(monkeypatch, **kwargs):
settings = Settings(_env_file=None, **kwargs)
from agenteval.web import deps as deps_module
from agenteval.web.routers import auth as auth_module
monkeypatch.setattr(deps_module, "get_settings", lambda: settings)
monkeypatch.setattr(auth_module, "get_settings", lambda: settings)
return settings
def test_no_credentials_configured_is_open(client_with_db, monkeypatch):
_patch_settings(monkeypatch)
assert client_with_db.get("/api/targets").status_code == 200
status = client_with_db.get("/api/auth/status").json()
assert status == {"auth_required": False, "authenticated": True}
def test_login_disabled_returns_400(client_with_db, monkeypatch):
_patch_settings(monkeypatch)
resp = client_with_db.post("/api/auth/login", json={"password": "whatever"})
assert resp.status_code == 400
def test_admin_password_gates_api(client_with_db, monkeypatch):
_patch_settings(monkeypatch, admin_password="s3cret")
# No credentials → 401.
assert client_with_db.get("/api/targets").status_code == 401
# Wrong password → 401.
assert client_with_db.post("/api/auth/login", json={"password": "nope"}).status_code == 401
# Correct password → token that unlocks the API.
token = client_with_db.post("/api/auth/login", json={"password": "s3cret"}).json()["token"]
resp = client_with_db.get("/api/targets", headers={"X-Auth-Token": token})
assert resp.status_code == 200
status = client_with_db.get("/api/auth/status", headers={"X-Auth-Token": token}).json()
assert status == {"auth_required": True, "authenticated": True}
assert client_with_db.get("/api/auth/status").json()["authenticated"] is False
def test_api_key_still_works_alongside_login(client_with_db, monkeypatch):
_patch_settings(monkeypatch, admin_password="s3cret", api_key="machine-key")
assert client_with_db.get("/api/targets").status_code == 401
assert client_with_db.get("/api/targets", headers={"X-API-Key": "machine-key"}).status_code == 200
assert client_with_db.get("/api/targets", headers={"X-API-Key": "wrong"}).status_code == 401
def test_health_stays_open(client_with_db, monkeypatch):
_patch_settings(monkeypatch, admin_password="s3cret")
assert client_with_db.get("/api/health").status_code == 200