from passlib.context import CryptContext from jose import JWTError, jwt from datetime import datetime, timedelta from typing import Optional, Dict, Any, Union import secrets import string import re from ..config import settings # 密码上下文 pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") def verify_password(plain_password: str, hashed_password: str) -> bool: """验证密码""" return pwd_context.verify(plain_password, hashed_password) def get_password_hash(password: str) -> str: """生成密码哈希""" return pwd_context.hash(password) def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str: """创建访问令牌""" to_encode = data.copy() if expires_delta: expire = datetime.utcnow() + expires_delta else: expire = datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) to_encode.update({"exp": expire, "type": "access"}) encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM) return encoded_jwt def create_refresh_token(data: dict) -> str: """创建刷新令牌""" to_encode = data.copy() expire = datetime.utcnow() + timedelta(days=settings.REFRESH_TOKEN_EXPIRE_DAYS) to_encode.update({"exp": expire, "type": "refresh"}) encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM) return encoded_jwt def create_verification_token(email: str) -> str: """创建验证令牌""" to_encode = {"email": email, "type": "verify"} expire = datetime.utcnow() + timedelta(hours=settings.VERIFICATION_TOKEN_EXPIRE_HOURS) to_encode.update({"exp": expire}) encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM) return encoded_jwt def create_reset_token(email: str) -> str: """创建密码重置令牌""" to_encode = {"email": email, "type": "reset"} expire = datetime.utcnow() + timedelta(minutes=settings.RESET_TOKEN_EXPIRE_MINUTES) to_encode.update({"exp": expire}) encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM) return encoded_jwt def decode_token(token: str) -> Optional[Dict[str, Any]]: """解码令牌""" try: payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM]) return payload except JWTError: return None def generate_verification_code(length: int = 6) -> str: """生成验证码""" digits = string.digits return ''.join(secrets.choice(digits) for _ in range(length)) def validate_password_strength(password: str) -> tuple[bool, str]: """验证密码强度""" if len(password) < 8: return False, "Password must be at least 8 characters long" if not re.search(r"[A-Z]", password): return False, "Password must contain at least one uppercase letter" if not re.search(r"[a-z]", password): return False, "Password must contain at least one lowercase letter" if not re.search(r"\d", password): return False, "Password must contain at least one digit" if not re.search(r"[!@#$%^&*(),.?\":{}|<>]", password): return False, "Password must contain at least one special character" return True, "Password is strong"