Files
QMDSearch/tests/test_auth.py
T
kplam 92b062c048 feat: 新增用户管理(用户增删改查、密码重置、角色权限、会话认证)与 API 指南
- 新增 app/api/deps.py、app/core/users.py、app/core/sessions.py:会话鉴权依赖、
  用户存储(PBKDF2-HMAC-SHA256 + 随机 salt,Redis/内存降级)、会话签发与校验(TTL 12h)
- auth.py 新增用户管理端点(列表/创建/重置密码/删除)与 admin/user 角色权限边界,
  user 访问用户管理返回 1006,禁删自己与最后一个 admin
- admin.html 新增用户管理面板(仅 admin 挂载)与 API 指南在线测试台
- Dockerfile 将 uv 放入 PATH;docker-compose 调整 qdrant 依赖为 service_started
  并移除依赖 curl 的 healthcheck(官方镜像不含 curl)
- 新增用户管理测试(users/sessions/auth_api/auth_integration),全量 461 项测试通过

Co-Authored-By: WorkBuddy <workbuddy@tencent.com>
2026-07-31 21:29:02 +08:00

79 lines
2.7 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.
"""旧 JWT 认证核心(app.core.auth)的单元测试
API 层(/api/v1/auth/*)已切换为会话制认证,端点契约测试见 tests/test_auth_api.py
本文件仅保留 app.core.auth 的函数级覆盖:
- require_admin:非 admin 抛 FORBIDDEN(直接测函数)
- create_access_token + decode_token 往返一致 / 非法 token 拒绝
- hash_password + verify_password 正确 / 错误 / 非法哈希
"""
from datetime import UTC, datetime
import pytest
from app.api.response import ApiError
from app.config import settings
from app.core.auth import (
ERR_FORBIDDEN,
ERR_TOKEN_INVALID,
create_access_token,
decode_token,
hash_password,
require_admin,
verify_password,
)
from app.models.auth import AuthUser
def _now() -> datetime:
return datetime.now(UTC)
class TestRequireAdmin:
"""require_adminadmin 通过、非 admin 抛 FORBIDDEN(直接测函数,不经 API)"""
async def test_admin_passes(self):
admin = AuthUser(username="alice", role="admin", created_at=_now())
result = await require_admin(user=admin)
assert result.role == "admin"
async def test_non_admin_raises_forbidden(self):
normal = AuthUser(username="bob", role="user", created_at=_now())
with pytest.raises(ApiError) as exc:
await require_admin(user=normal)
assert exc.value.code == ERR_FORBIDDEN
class TestAuthCoreFunctions:
"""核心函数:token 往返 / 密码哈希"""
def test_create_and_decode_token_roundtrip(self):
token, expires_in = create_access_token("alice", "admin")
assert expires_in == settings.jwt_expire_minutes * 60
payload = decode_token(token)
assert payload["sub"] == "alice"
assert payload["role"] == "admin"
assert "iat" in payload and "exp" in payload
def test_decode_invalid_token_raises(self):
with pytest.raises(ApiError) as exc:
decode_token("not-a-jwt")
assert exc.value.code == ERR_TOKEN_INVALID
def test_hash_password_not_plaintext(self):
hashed = hash_password("my-secret")
assert hashed != "my-secret"
assert hashed.startswith("$2") # bcrypt 哈希前缀
def test_verify_password_correct(self):
hashed = hash_password("my-secret")
assert verify_password("my-secret", hashed) is True
def test_verify_password_wrong(self):
hashed = hash_password("my-secret")
assert verify_password("wrong-password", hashed) is False
def test_verify_password_garbage_hash_returns_false(self):
# 非法 hash 会被 bcrypt 拒绝,verify_password 捕获异常返回 False
assert verify_password("any", "not-a-valid-hash") is False