diff --git a/backend/auth/user_store.py b/backend/auth/user_store.py index 2562fad..0c3309a 100644 --- a/backend/auth/user_store.py +++ b/backend/auth/user_store.py @@ -8,7 +8,7 @@ import logging import shutil import threading import uuid -from datetime import datetime, timedelta, timezone +from datetime import UTC, datetime, timedelta from pathlib import Path from .password import hash_password @@ -97,8 +97,8 @@ def create_user( "active": True, "language": "fr", # default UI language "avatar": None, # profile picture data-URL (#113) - "created_at": datetime.now(timezone.utc).isoformat(), - "password_changed_at": datetime.now(timezone.utc).timestamp(), + "created_at": datetime.now(UTC).isoformat(), + "password_changed_at": datetime.now(UTC).timestamp(), "last_login": None, "failed_attempts": 0, "locked_until": None, @@ -126,7 +126,7 @@ def update_user(username: str, updates: dict) -> dict: if "password" in safe_updates: safe_updates["password_hash"] = hash_password(safe_updates.pop("password")) # BUG-028: invalidate every token issued before this change. - safe_updates["password_changed_at"] = datetime.now(timezone.utc).timestamp() + safe_updates["password_changed_at"] = datetime.now(UTC).timestamp() data["users"][username].update(safe_updates) _write(data) @@ -148,7 +148,7 @@ def delete_user(username: str): def record_login_success(username: str): """Record a successful login: update last_login, reset failed attempts.""" update_user(username, { - "last_login": datetime.now(timezone.utc).isoformat(), + "last_login": datetime.now(UTC).isoformat(), "failed_attempts": 0, "locked_until": None, }) @@ -171,7 +171,7 @@ def record_login_failure(username: str) -> int: # Lock after 5 failed attempts (15 minutes) if attempts >= 5: locked_until = ( - datetime.now(timezone.utc) + timedelta(minutes=15) + datetime.now(UTC) + timedelta(minutes=15) ).isoformat() updates["locked_until"] = locked_until logger.warning(f"Account '{username}' locked after {attempts} failed attempts") @@ -189,7 +189,7 @@ def is_locked(username: str) -> bool: if not user or not user.get("locked_until"): return False locked_until = datetime.fromisoformat(user["locked_until"]) - if datetime.now(timezone.utc) > locked_until: + if datetime.now(UTC) > locked_until: # Lock expired — unlock update_user(username, {"locked_until": None, "failed_attempts": 0}) return False