Fix auth datetime comparison and bcrypt dependency

- Use timezone-aware datetimes (datetime.now(timezone.utc)) for session expiry comparison
- Add explicit bcrypt==4.0.1 dependency for passlib bcrypt backend
This commit is contained in:
Mondo Diaz
2026-01-08 15:14:54 -06:00
parent 2a68708a79
commit 696793c84f
2 changed files with 9 additions and 8 deletions

View File

@@ -5,7 +5,7 @@ Handles password hashing, session management, and API key operations.
import hashlib import hashlib
import secrets import secrets
from datetime import datetime, timedelta from datetime import datetime, timedelta, timezone
from typing import Optional from typing import Optional
from passlib.context import CryptContext from passlib.context import CryptContext
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
@@ -113,7 +113,7 @@ class AuthService:
def update_last_login(self, user: User) -> None: def update_last_login(self, user: User) -> None:
"""Update the user's last login timestamp.""" """Update the user's last login timestamp."""
user.last_login = datetime.utcnow() user.last_login = datetime.now(timezone.utc)
self.db.commit() self.db.commit()
def list_users(self, include_inactive: bool = False) -> list[User]: def list_users(self, include_inactive: bool = False) -> list[User]:
@@ -159,7 +159,7 @@ class AuthService:
session = UserSession( session = UserSession(
user_id=user.id, user_id=user.id,
token_hash=token_hash, token_hash=token_hash,
expires_at=datetime.utcnow() + timedelta(hours=SESSION_DURATION_HOURS), expires_at=datetime.now(timezone.utc) + timedelta(hours=SESSION_DURATION_HOURS),
user_agent=user_agent, user_agent=user_agent,
ip_address=ip_address, ip_address=ip_address,
) )
@@ -184,14 +184,14 @@ class AuthService:
if not session: if not session:
return None return None
if session.expires_at < datetime.utcnow(): if session.expires_at < datetime.now(timezone.utc):
# Session has expired, delete it # Session has expired, delete it
self.db.delete(session) self.db.delete(session)
self.db.commit() self.db.commit()
return None return None
# Update last accessed time # Update last accessed time
session.last_accessed = datetime.utcnow() session.last_accessed = datetime.now(timezone.utc)
self.db.commit() self.db.commit()
return session return session
@@ -213,7 +213,7 @@ class AuthService:
"""Delete all expired sessions. Returns count of deleted sessions.""" """Delete all expired sessions. Returns count of deleted sessions."""
count = ( count = (
self.db.query(UserSession) self.db.query(UserSession)
.filter(UserSession.expires_at < datetime.utcnow()) .filter(UserSession.expires_at < datetime.now(timezone.utc))
.delete() .delete()
) )
self.db.commit() self.db.commit()
@@ -268,11 +268,11 @@ class AuthService:
return None return None
# Check expiration # Check expiration
if api_key.expires_at and api_key.expires_at < datetime.utcnow(): if api_key.expires_at and api_key.expires_at < datetime.now(timezone.utc):
return None return None
# Update last used time # Update last used time
api_key.last_used = datetime.utcnow() api_key.last_used = datetime.now(timezone.utc)
self.db.commit() self.db.commit()
return api_key return api_key

View File

@@ -9,6 +9,7 @@ pydantic==2.5.3
pydantic-settings==2.1.0 pydantic-settings==2.1.0
python-jose[cryptography]==3.3.0 python-jose[cryptography]==3.3.0
passlib[bcrypt]==1.7.4 passlib[bcrypt]==1.7.4
bcrypt==4.0.1
# Test dependencies # Test dependencies
pytest>=7.4.0 pytest>=7.4.0