"""Phase 3 认证测试:注册、登录、登出、鉴权、IDOR 防护。""" from fastapi.testclient import TestClient from app.main import app def _client() -> TestClient: return TestClient(app, raise_server_exceptions=False) # --- 注册 --- def test_register_success() -> None: with _client() as client: resp = client.post("/api/auth/register", json={ "username": "alice", "email": "alice@example.com", "password": "password123", }) assert resp.status_code == 201 body = resp.json() assert body["username"] == "alice" assert body["email"] == "alice@example.com" assert body["storage_quota"] == 104_857_600 # Cookie 已签发 assert "session_id" in resp.cookies def test_register_duplicate_username() -> None: with _client() as client: client.post("/api/auth/register", json={ "username": "bob", "email": "bob@example.com", "password": "password123", }) resp = client.post("/api/auth/register", json={ "username": "bob", "email": "bob2@example.com", "password": "password123", }) assert resp.status_code == 409 assert resp.json()["code"] == "USERNAME_TAKEN" def test_register_duplicate_email() -> None: with _client() as client: client.post("/api/auth/register", json={ "username": "carol", "email": "carol@example.com", "password": "password123", }) resp = client.post("/api/auth/register", json={ "username": "carol2", "email": "carol@example.com", "password": "password123", }) assert resp.status_code == 409 assert resp.json()["code"] == "EMAIL_TAKEN" def test_register_short_password() -> None: with _client() as client: resp = client.post("/api/auth/register", json={ "username": "dave", "email": "dave@example.com", "password": "short", }) assert resp.status_code == 422 # --- 登录 --- def test_login_by_username() -> None: with _client() as client: client.post("/api/auth/register", json={ "username": "eve", "email": "eve@example.com", "password": "password123", }) resp = client.post("/api/auth/login", json={ "username_or_email": "eve", "password": "password123", }) assert resp.status_code == 200 assert resp.json()["username"] == "eve" assert "session_id" in resp.cookies def test_login_by_email() -> None: with _client() as client: client.post("/api/auth/register", json={ "username": "frank", "email": "frank@example.com", "password": "password123", }) resp = client.post("/api/auth/login", json={ "username_or_email": "frank@example.com", "password": "password123", }) assert resp.status_code == 200 assert resp.json()["username"] == "frank" def test_login_wrong_password() -> None: with _client() as client: client.post("/api/auth/register", json={ "username": "grace", "email": "grace@example.com", "password": "password123", }) resp = client.post("/api/auth/login", json={ "username_or_email": "grace", "password": "wrongpassword", }) assert resp.status_code == 401 assert resp.json()["code"] == "AUTH_INVALID_CREDENTIALS" def test_login_nonexistent_user() -> None: with _client() as client: resp = client.post("/api/auth/login", json={ "username_or_email": "nobody", "password": "password123", }) assert resp.status_code == 401 # --- 登出 --- def test_logout() -> None: with _client() as client: client.post("/api/auth/register", json={ "username": "heidi", "email": "heidi@example.com", "password": "password123", }) resp = client.post("/api/auth/logout") assert resp.status_code == 204 # --- /api/me --- def test_me_authenticated() -> None: with _client() as client: client.post("/api/auth/register", json={ "username": "ivan", "email": "ivan@example.com", "password": "password123", }) resp = client.get("/api/auth/me") assert resp.status_code == 200 body = resp.json() assert body["username"] == "ivan" assert body["storage_used"] == 0 def test_me_unauthenticated() -> None: with _client() as client: resp = client.get("/api/auth/me") assert resp.status_code == 401 assert resp.json()["code"] == "AUTH_REQUIRED" # --- IDOR 防护 --- def test_user_a_cannot_see_user_b() -> None: """用户A 登录后,session 只能访问自己的 /me。""" with _client() as client: client.post("/api/auth/register", json={ "username": "user_a", "email": "a@example.com", "password": "password123", }) # user_a 已登录(Cookie 自动携带) me_resp = client.get("/api/auth/me") assert me_resp.status_code == 200 assert me_resp.json()["username"] == "user_a" def test_storage_endpoint() -> None: with _client() as client: client.post("/api/auth/register", json={ "username": "storage_user", "email": "storage@example.com", "password": "password123", }) resp = client.get("/api/auth/storage") assert resp.status_code == 200 body = resp.json() assert body["storage_used"] == 0 assert body["storage_quota"] == 104_857_600 assert body["storage_quota_mb"] == 100.0 # --- free plan seed --- def test_free_plan_auto_created() -> None: """free plan 应在应用启动时自动创建。""" with _client() as client: client.post("/api/auth/register", json={ "username": "plan_user", "email": "plan@example.com", "password": "password123", }) resp = client.get("/api/auth/me") assert resp.status_code == 200 assert resp.json()["storage_quota"] == 104_857_600