Files
rengine/api/app/core/security.py
T
Yogesh Ojha c6c5c61389 Refactor project and tag management, enhance error handling, and improve UI components
- Updated project slug generation to ensure uniqueness by checking active projects.
- Modified project retrieval functions to only fetch active projects.
- Introduced unique slug generation for tags associated with specific projects.
- Enhanced user authentication flow with improved error handling and session management.
- Added session expiration handling in the API client and SSE client for better user experience.
- Improved UI components for better accessibility and user feedback, including copy buttons and activity drawers.
- Refactored notification handling to ensure proper session management and state reset on logout.
- Removed unused enrichment components to streamline the codebase.
- Updated notification model to simplify JSONB handling and ensure proper expiration logic.
2026-05-23 14:33:19 +05:30

98 lines
2.3 KiB
Python

from datetime import UTC, datetime, timedelta
from typing import Any
from argon2 import PasswordHasher
from argon2.exceptions import VerificationError, VerifyMismatchError
from jose import JWTError, jwt
from app.config import settings
ph = PasswordHasher(
time_cost=2,
memory_cost=65536,
parallelism=4,
hash_len=32,
salt_len=16,
)
def hash_password(password: str) -> str:
"""
Hash a password using Argon2id.
Args:
password: Plain text password to hash
Returns:
Argon2 hash as a string
"""
return ph.hash(password)
def verify_password(plain_password: str, hashed_password: str) -> bool:
"""
Verify a password against its hash.
Args:
plain_password: Plain text password to verify
hashed_password: Argon2 hash to verify against
Returns:
True if password matches, False otherwise
"""
try:
ph.verify(hashed_password, plain_password)
return True
except (VerifyMismatchError, VerificationError):
return False
def create_token(
subject: str | Any,
token_type: str,
expires_delta: timedelta,
) -> str:
"""Create a JWT token with the given subject and expiration."""
expire = datetime.now(UTC) + expires_delta
to_encode = {
"exp": expire,
"sub": str(subject),
"type": token_type,
}
return jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
def create_access_token(subject: str | Any) -> str:
"""Create an access token for the given subject."""
return create_token(
subject=subject,
token_type="access", # noqa: S106
expires_delta=timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES),
)
def create_refresh_token(subject: str | Any) -> str:
"""Create a refresh token for the given subject."""
return create_token(
subject=subject,
token_type="refresh", # noqa: S106
expires_delta=timedelta(days=settings.REFRESH_TOKEN_EXPIRE_DAYS),
)
def decode_token(token: str) -> dict | None:
"""
Decode and validate a JWT token.
Returns:
Decoded payload dict if valid, None otherwise
"""
try:
return jwt.decode(
token,
settings.SECRET_KEY,
algorithms=[settings.ALGORITHM],
)
except JWTError:
return None