fix(auth): unify site-wide 401/403 semantics (cma-auth-401-403-unify-20260915)
require_auth now uses HTTPBearer(auto_error=False) and raises 401 explicitly when the Authorization header is missing or non-Bearer, matching require_auth_401. Unauthenticated requests are 401 for every user endpoint; authenticated-but-forbidden (cross-entity / role) stays 403. - app/auth_middleware.py: single optional bearer, 401 on missing token (require_auth_401 kept as a compatibility alias) - tests: update 4 pre-existing cases that asserted 403 without a token (test_auth, test_reports, test_kpi_causality, test_expenses, test_api_auth_surface_20260914) - intentional behavior change - add tests/test_auth_401_unification_20260915.py: sample + full sweep (all AUTHED GET routes -> 401), invalid token -> 401, cross-entity and role-denied still 403, bot channel (X-BOT-KEY) and public paths unchanged
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
1. B 类(原缺鉴权用户端点)无 token → **401**(46 个端点逐条断言)
|
||||
2. C 类(显式公开端点)无 token 仍按原语义可用
|
||||
3. A 类(X-BOT-KEY Bot 通道)行为不变:带 key 200 / 无 key 401
|
||||
4. 既有 require_auth 端点(kpis/maps)无 token → 403(对照,不回归)
|
||||
4. 既有 require_auth 端点(kpis/maps/org-tree)无 token → **401**(2026-09-15 语义统一:原 403)
|
||||
5. 持 token 正常 200;跨实体(token entity=1 + entity_id=2)仍 403
|
||||
6. 结构性不变量:全量路由巡检无 B 类缺口(新增用户端点漏挂鉴权 → 本用例 FAIL)
|
||||
"""
|
||||
@@ -221,11 +221,12 @@ class TestPublicAndExistingBaseline:
|
||||
"username": "testadmin", "password": "wrong", "entity_id": 1})
|
||||
assert r.status_code == 401
|
||||
|
||||
def test_existing_403_endpoints_unchanged(self, client: TestClient, seeded):
|
||||
"""对照:原 403 端点(kpis/maps/org-tree)不回归"""
|
||||
def test_existing_403_endpoints_now_401(self, client: TestClient, seeded):
|
||||
"""语义统一(cma-auth-401-403-unify-20260915):原 403 端点(kpis/maps/org-tree)
|
||||
无 token 现返回 401(未认证语义);持 token 仍 200"""
|
||||
token = _login(client, 1)
|
||||
for path in ["/api/cma/kpis", "/api/cma/maps", "/api/cma/org/tree"]:
|
||||
assert client.get(path).status_code == 403, f"{path} 无 token 期望仍 403"
|
||||
assert client.get(path).status_code == 401, f"{path} 无 token 期望 401"
|
||||
assert client.get(path, headers=auth_header(token)).status_code == 200
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user