AI_Virtual_Wardrobe / app /core /security.py
mata01's picture
Initialize production-grade FastAPI backend with models, routes, celery workers, and test suite
b18b789
Raw
History Blame Contribute Delete
1.65 kB
from datetime import datetime, timedelta, timezone
from typing import Any, Union, Optional
import jwt
import bcrypt
from app.core.config import settings
def verify_password(plain_password: str, hashed_password: str) -> bool:
try:
return bcrypt.checkpw(plain_password.encode('utf-8'), hashed_password.encode('utf-8'))
except Exception:
return False
def get_password_hash(password: str) -> str:
salt = bcrypt.gensalt()
return bcrypt.hashpw(password.encode('utf-8'), salt).decode('utf-8')
def validate_password_strength(password: str) -> bool:
# Minimum 8 characters, maximum 128 characters
if len(password) < 8 or len(password) > 128:
return False
return True
def create_access_token(subject: Union[str, Any], expires_delta: Optional[timedelta] = None) -> str:
if expires_delta:
expire = datetime.now(timezone.utc) + expires_delta
else:
expire = datetime.now(timezone.utc) + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode = {"exp": expire, "sub": str(subject)}
encoded_jwt = jwt.encode(to_encode, settings.JWT_SECRET_KEY, algorithm=settings.ALGORITHM)
return encoded_jwt
def decode_access_token(token: str) -> Optional[str]:
try:
# Explicitly verify signature with the expected algorithm (rejection of 'none' algorithm is implicit by specifying algorithms parameter)
payload = jwt.decode(token, settings.JWT_SECRET_KEY, algorithms=[settings.ALGORITHM])
user_id: str = payload.get("sub")
if user_id is None:
return None
return user_id
except jwt.PyJWTError:
return None