feat: Phase 3 FBA UI 预构建产物 + Phase 4 按钮级权限(fba_jwt + perms)(Epic #159)

This commit is contained in:
2026-08-06 10:18:15 +08:00
parent 067ba0abe1
commit 4ea81cea91
7 changed files with 342 additions and 4 deletions
+77
View File
@@ -0,0 +1,77 @@
# -*- coding: utf-8 -*-
"""FBA JWT 校验模块单元测试(Epic #159 · Phase 4)。
运行:python -m unittest core.auth.tests.test_fba_jwt -v
"""
from __future__ import annotations
import os
import unittest
from core.auth.fba_jwt import FbaAuth, FbaAuthError, make_test_token
SECRET = "unit-test-secret-key"
class FbaJwtTest(unittest.TestCase):
def setUp(self):
self.auth = FbaAuth(SECRET)
def test_verify_ok(self):
token = make_test_token(SECRET, user_id=42, session_uuid="s-1")
claims = self.auth.verify(f"Bearer {token}")
self.assertEqual(claims["sub"], "42")
self.assertEqual(claims["session_uuid"], "s-1")
def test_verify_expired(self):
token = make_test_token(SECRET, exp_offset=-10)
with self.assertRaises(FbaAuthError) as ctx:
self.auth.verify(f"Bearer {token}")
self.assertEqual(ctx.exception.status, 401)
self.assertIn("过期", ctx.exception.message)
def test_verify_bad_signature(self):
token = make_test_token("other-secret")
with self.assertRaises(FbaAuthError) as ctx:
self.auth.verify(f"Bearer {token}")
self.assertEqual(ctx.exception.status, 401)
def test_verify_missing_bearer(self):
for bad in ("", "token-abc", "Basic abc"):
with self.assertRaises(FbaAuthError) as ctx:
self.auth.verify(bad)
self.assertEqual(ctx.exception.status, 401)
def test_verify_malformed(self):
with self.assertRaises(FbaAuthError):
self.auth.verify("Bearer not-a-jwt")
def test_missing_fields(self):
# 无 session_uuid 的 token(签名正确但字段缺失)
import base64, hashlib, hmac, json, time
enc = lambda b: base64.urlsafe_b64encode(b).rstrip(b"=").decode()
header = enc(json.dumps({"alg": "HS256", "typ": "JWT"}).encode())
payload = enc(json.dumps({"sub": "1", "exp": time.time() + 60}).encode())
sig = enc(hmac.new(SECRET.encode(), f"{header}.{payload}".encode(),
hashlib.sha256).digest())
with self.assertRaises(FbaAuthError) as ctx:
self.auth.verify(f"Bearer {header}.{payload}.{sig}")
self.assertIn("字段", ctx.exception.message)
def test_from_env_absent(self):
os.environ.pop("FBA_TOKEN_SECRET_KEY", None)
self.assertIsNone(FbaAuth.from_env())
def test_from_env_present(self):
os.environ["FBA_TOKEN_SECRET_KEY"] = SECRET
try:
auth = FbaAuth.from_env()
self.assertIsNotNone(auth)
token = make_test_token(SECRET)
self.assertEqual(auth.verify(f"Bearer {token}")["sub"], "1")
finally:
os.environ.pop("FBA_TOKEN_SECRET_KEY", None)
if __name__ == "__main__":
unittest.main()