93 lines
3.5 KiB
Python
93 lines
3.5 KiB
Python
# tests/api/test_auth.py
|
|
import pytest
|
|
|
|
def test_create_and_verify_token():
|
|
from sanguo_api.auth import create_token, verify_token, set_jwt_config
|
|
set_jwt_config(secret="test_secret", expire_minutes=60)
|
|
token = create_token("admin")
|
|
assert isinstance(token, str)
|
|
assert verify_token(token) == "admin"
|
|
|
|
def test_verify_token_invalid_raises_401():
|
|
from fastapi import HTTPException
|
|
from sanguo_api.auth import verify_token, set_jwt_config
|
|
set_jwt_config(secret="test_secret", expire_minutes=60)
|
|
with pytest.raises(HTTPException) as exc:
|
|
verify_token("invalid.token.here")
|
|
assert exc.value.status_code == 401
|
|
|
|
def test_hash_and_verify_password():
|
|
from sanguo_api.auth import hash_password, verify_password
|
|
h = hash_password("mypass")
|
|
assert h != "mypass"
|
|
assert verify_password("mypass", h) is True
|
|
assert verify_password("wrong", h) is False
|
|
|
|
|
|
# ---- P1.4 token 静默刷新 ----
|
|
|
|
def test_token_expiry_helpers():
|
|
"""get_token_exp 返回 unix 秒(供前端/拦截器判断剩余时间)。"""
|
|
import time
|
|
from sanguo_api.auth import create_token, get_token_exp, set_jwt_config
|
|
set_jwt_config(secret="test_secret", expire_minutes=60)
|
|
token = create_token("admin")
|
|
exp = get_token_exp(token)
|
|
assert exp is not None
|
|
assert abs(exp - (time.time() + 3600)) < 30 # ≈ now + 60min
|
|
|
|
|
|
def test_refresh_endpoint_returns_new_valid_token():
|
|
"""POST /auth/refresh:有效旧 token → 新 token(可过 verify),返回 expires_in。"""
|
|
from fastapi.testclient import TestClient
|
|
|
|
from sanguo_api.app import create_app
|
|
from sanguo_api.auth import hash_password, set_jwt_config, verify_token
|
|
set_jwt_config(secret="test_secret", expire_minutes=60)
|
|
app = create_app(db_path=":memory:", auth_config={
|
|
"username": "admin",
|
|
"password_hash": hash_password("pass123"),
|
|
"jwt_secret": "test_secret",
|
|
"expire_minutes": 60,
|
|
})
|
|
client = TestClient(app)
|
|
old = client.post("/api/v1/auth/login",
|
|
json={"username": "admin", "password": "pass123"}).json()["token"]
|
|
r = client.post("/api/v1/auth/refresh",
|
|
headers={"Authorization": f"Bearer {old}"})
|
|
assert r.status_code == 200
|
|
data = r.json()
|
|
# 同秒签发的 JWT 可能逐字相同,以 exp 语义断言续期
|
|
from sanguo_api.auth import get_token_exp
|
|
assert get_token_exp(data["token"]) >= get_token_exp(old)
|
|
assert verify_token(data["token"]) == "admin"
|
|
assert data["expires_in"] == 3600
|
|
|
|
|
|
def test_refresh_endpoint_rejects_expired_or_missing_token():
|
|
"""过期/缺 token → 401(不放过期 token 无限续命)。"""
|
|
import time
|
|
|
|
import jwt as pyjwt
|
|
from fastapi.testclient import TestClient
|
|
|
|
from sanguo_api.app import create_app
|
|
from sanguo_api.auth import hash_password, set_jwt_config
|
|
set_jwt_config(secret="test_secret", expire_minutes=60)
|
|
app = create_app(db_path=":memory:", auth_config={
|
|
"username": "admin",
|
|
"password_hash": hash_password("pass123"),
|
|
"jwt_secret": "test_secret",
|
|
"expire_minutes": 60,
|
|
})
|
|
client = TestClient(app)
|
|
# 无 header
|
|
assert client.post("/api/v1/auth/refresh").status_code == 401
|
|
# 过期 token(手工签一个已过期的)
|
|
expired = pyjwt.encode(
|
|
{"sub": "admin", "exp": int(time.time()) - 3600},
|
|
"test_secret", algorithm="HS256")
|
|
r = client.post("/api/v1/auth/refresh",
|
|
headers={"Authorization": f"Bearer {expired}"})
|
|
assert r.status_code == 401
|