Files
xiaoxia-saas/packages/application/auth/password_handler.py
T
xiaoxia 4244c558a5
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 47s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 47s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m13s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 2m26s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m48s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m5s
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 26h39m38s
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Failing after 26h39m44s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 26h39m53s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 26h39m13s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 26h39m6s
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Failing after 26h39m6s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Failing after 26h39m8s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 26h39m13s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 26h39m15s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 26h39m13s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 26h39m13s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 26h39m0s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 26h39m3s
CI/CD Pipeline / Check push changed paths (pull_request) Failing after 26h39m16s
fix(#1834): 批量修复 UP 系列静态分析警告
- UP007: Optional[X] -> X | None
- UP006: List/Dict/Tuple/Set/Type -> list/dict/tuple/set/type
- UP017: timezone.utc -> datetime.UTC
- UP035: 移除 typing 模块已弃用的导入

共修复 224 个文件,971 处问题
B006/B909/B904/B023 在 develop 上已全部通过
B008 已在 ruff 配置中忽略(FastAPI Depends 模式)

Closes #1834
2026-09-15 12:43:31 +08:00

127 lines
3.2 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.
"""
密码处理器委托层
此模块作为 Domain 层 (packages.domain.auth.password_hasher) 和 Application 层之间的委托层,
隔离 Domain 层对 bcrypt 库的直接依赖。
使用方式:
from packages.application.auth.password_handler import PasswordHandler, get_password_handler
password_handler = PasswordHandler()
hashed = password_handler.hash_password("my_secure_password")
is_valid = password_handler.verify_password("my_secure_password", hashed)
"""
from typing import Optional
from packages.application.auth.password_hasher import PasswordHasher, PasswordValidator
class PasswordHandler:
"""
密码处理器委托类
委托给 packages.domain.auth.password_hasher 进行实际的密码哈希操作,
此层仅负责配置和封装,不直接依赖 bcrypt 库。
"""
def __init__(self, rounds: int = 12):
"""
初始化密码处理器
Args:
rounds: bcrypt cost factor(默认 12,推荐范围 10-14)
"""
self._hasher = PasswordHasher(rounds=rounds)
self._validator = PasswordValidator(
min_length=8,
require_uppercase=True,
require_lowercase=True,
require_digit=True,
require_special=False,
)
def hash_password(self, password: str) -> str:
"""
哈希密码
Args:
password: 明文密码
Returns:
bcrypt 哈希字符串
Raises:
ValueError: 密码为空
"""
return self._hasher.hash_password(password)
def verify_password(self, password: str, hashed_password: str) -> bool:
"""
验证密码
Args:
password: 明文密码
hashed_password: 存储的哈希密码
Returns:
True 如果密码正确,否则 False
"""
return self._hasher.verify_password(password, hashed_password)
def needs_rehash(self, hashed_password: str) -> bool:
"""
检查哈希是否需要重新计算
Args:
hashed_password: 存储的哈希密码
Returns:
True 如果需要重新哈希
"""
return self._hasher.needs_rehash(hashed_password)
def validate_strength(self, password: str) -> tuple[bool, Optional[str]]:
"""
验证密码强度
Args:
password: 明文密码
Returns:
(是否有效, 错误信息)
"""
return self._validator.validate(password)
# 默认处理器实例
_default_handler: Optional[PasswordHandler] = None
def configure_password_handler(rounds: int = 12) -> PasswordHandler:
"""
配置全局密码处理器
Args:
rounds: bcrypt cost factor
Returns:
配置好的 PasswordHandler 实例
"""
global _default_handler
_default_handler = PasswordHandler(rounds=rounds)
return _default_handler
def get_password_handler() -> PasswordHandler:
"""
获取全局密码处理器
Returns:
PasswordHandler 实例
"""
global _default_handler
if _default_handler is None:
_default_handler = PasswordHandler()
return _default_handler