aps-agent/aps/tests/test_auth.py

101 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""A5.7 / ADR-0012:账号与登录态。
要证明三件事:密码不落盘、能力调用必须带登录态、登录态对不上就是拒绝。
"""
from __future__ import annotations
import json
from pathlib import Path
from fastapi.testclient import TestClient
from aps.api.app import app
from aps.identity import verify_password
client = TestClient(app)
ACCOUNTS_FILE = Path(__file__).resolve().parents[1] / "data" / "demo_accounts.json"
DEMO_PASSWORD = "aps-demo-pass"
def login(account_id: str = "E1001", password: str = DEMO_PASSWORD) -> dict:
response = client.post("/api/auth/login", json={"accountId": account_id, "password": password})
return {"status": response.status_code, "body": response.json()}
def auth_header(token: str) -> dict[str, str]:
return {"authorization": f"Bearer {token}"}
def test_password_is_never_stored_in_plaintext() -> None:
"""凭据文件里只有 PBKDF2 哈希;明文密码绝不落盘。"""
raw = ACCOUNTS_FILE.read_text(encoding="utf-8")
assert DEMO_PASSWORD not in raw, "演示密码不该出现在账号文件里"
stored = json.loads(raw)["accounts"][0]["passwordHash"]
assert stored.startswith("pbkdf2_sha256$"), stored
assert verify_password(DEMO_PASSWORD, stored)
assert not verify_password("wrong-password", stored)
def test_login_returns_token_and_whoami_accepts_it() -> None:
result = login()
assert result["status"] == 200
body = result["body"]
assert body["accountId"] == "E1001"
assert body["token"].startswith("aps_")
assert body["expiresAt"] > 0
who = client.get("/api/auth/whoami", headers=auth_header(body["token"]))
assert who.status_code == 200
assert who.json()["displayName"] == body["displayName"]
def test_wrong_password_is_rejected() -> None:
result = login(password="not-the-password")
assert result["status"] == 401
assert "token" not in result["body"]
def test_whoami_rejects_unknown_token() -> None:
assert client.get("/api/auth/whoami", headers=auth_header("aps_not-a-real-token")).status_code == 401
def test_capability_call_requires_login_state() -> None:
"""登录态归 APS 判:没带 token 的能力调用一律 401(D9)。"""
response = client.post("/api/capabilities/aps.orders.query", json={"params": {}})
assert response.status_code == 401
assert "重新绑定" in response.json()["detail"]
def test_capability_call_succeeds_with_token() -> None:
token = login()["body"]["token"]
response = client.post(
"/api/capabilities/aps.orders.query",
json={"params": {"limit": 2}},
headers=auth_header(token),
)
assert response.status_code == 200
assert response.json()["status"] == "succeeded"
def test_account_mismatch_is_forbidden() -> None:
"""平台传来的账号与登录态不是同一个人:拒绝,别拿别人的登录态干活。"""
token = login()["body"]["token"]
response = client.post(
"/api/capabilities/aps.orders.query",
json={"params": {}, "identity": {"accountId": "E1002"}},
headers=auth_header(token),
)
assert response.status_code == 403
def test_logout_invalidates_token() -> None:
token = login()["body"]["token"]
assert client.post("/api/auth/logout", headers=auth_header(token)).json()["loggedOut"] is True
assert client.get("/api/auth/whoami", headers=auth_header(token)).status_code == 401