Refactor authentication services to async password handling; optimize bulk operations and queries

- Updated `verify_password` and `get_password_hash` to their async counterparts to prevent event loop blocking.
- Replaced N+1 query patterns in `admin.py` and `session_async.py` with optimized bulk operations for improved performance.
- Enhanced `user_async.py` with bulk update and soft delete methods for efficient user management.
- Added eager loading support in CRUD operations to prevent N+1 query issues.
- Updated test cases with stronger password examples for better security representation.
This commit is contained in:
Felipe Cardoso
2025-11-01 03:53:22 +01:00
parent 819f3ba963
commit 3fe5d301f8
17 changed files with 397 additions and 163 deletions

View File

@@ -4,6 +4,8 @@ logging.getLogger('passlib').setLevel(logging.ERROR)
from datetime import datetime, timedelta, timezone
from typing import Any, Dict, Optional, Union
import uuid
import asyncio
from functools import partial
from jose import jwt, JWTError
from passlib.context import CryptContext
@@ -44,6 +46,49 @@ def get_password_hash(password: str) -> str:
return pwd_context.hash(password)
async def verify_password_async(plain_password: str, hashed_password: str) -> bool:
"""
Verify a password against a hash asynchronously.
Runs the CPU-intensive bcrypt operation in a thread pool to avoid
blocking the event loop.
Args:
plain_password: Plain text password to verify
hashed_password: Hashed password to verify against
Returns:
True if password matches, False otherwise
"""
loop = asyncio.get_event_loop()
return await loop.run_in_executor(
None,
partial(pwd_context.verify, plain_password, hashed_password)
)
async def get_password_hash_async(password: str) -> str:
"""
Generate a password hash asynchronously.
Runs the CPU-intensive bcrypt operation in a thread pool to avoid
blocking the event loop. This is especially important during user
registration and password changes.
Args:
password: Plain text password to hash
Returns:
Hashed password string
"""
loop = asyncio.get_event_loop()
return await loop.run_in_executor(
None,
pwd_context.hash,
password
)
def create_access_token(
subject: Union[str, Any],
expires_delta: Optional[timedelta] = None,