zephyrdark 9f756331c4
All checks were successful
Deploy to Production / deploy (push) Successful in 1m9s
fix: remove passlib dependency and fix FastAPI deprecation warnings
- Replace passlib with direct bcrypt usage to eliminate the
  'module bcrypt has no attribute __about__' warning
- Change Query(regex=) to Query(pattern=) per FastAPI deprecation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 22:34:32 +09:00

61 lines
1.7 KiB
Python

"""
Security utilities for authentication.
"""
import hashlib
from datetime import datetime, timedelta, timezone
from typing import Optional
import bcrypt
import jwt
from jwt.exceptions import PyJWTError
from app.core.config import get_settings
settings = get_settings()
def sha256_hash(password: str) -> str:
"""SHA-256 hash a raw password (matches client-side hashing)."""
return hashlib.sha256(password.encode()).hexdigest()
def verify_password(sha256_password: str, hashed_password: str) -> bool:
"""Verify a SHA-256 hashed password against its bcrypt hash."""
return bcrypt.checkpw(
sha256_password.encode(), hashed_password.encode()
)
def get_password_hash(raw_password: str) -> str:
"""Hash a raw password: SHA-256 then bcrypt."""
return bcrypt.hashpw(
sha256_hash(raw_password).encode(), bcrypt.gensalt()
).decode()
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str:
"""Create a JWT access token."""
to_encode = data.copy()
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.update({"exp": expire})
encoded_jwt = jwt.encode(
to_encode, settings.jwt_secret, algorithm=settings.jwt_algorithm
)
return encoded_jwt
def decode_access_token(token: str) -> Optional[dict]:
"""Decode and verify a JWT access token."""
try:
payload = jwt.decode(
token, settings.jwt_secret, algorithms=[settings.jwt_algorithm]
)
return payload
except PyJWTError:
return None