feat: Implement MFA authentication, add ride statistics model, and update various services, APIs, and tests across the application.

This commit is contained in:
pacnpal
2025-12-28 17:32:53 -05:00
parent aa56c46c27
commit c95f99ca10
452 changed files with 7948 additions and 6073 deletions

View File

@@ -12,7 +12,7 @@ Recent additions:
import logging
import re
from typing import Any, Dict, Optional
from typing import Any
from django.conf import settings
from django.contrib.auth import update_session_auth_hash
@@ -58,7 +58,7 @@ class AccountService:
old_password: str,
new_password: str,
request: HttpRequest,
) -> Dict[str, Any]:
) -> dict[str, Any]:
"""
Change user password with validation and notification.
@@ -146,7 +146,7 @@ class AccountService:
user: User,
new_email: str,
request: HttpRequest,
) -> Dict[str, Any]:
) -> dict[str, Any]:
"""
Initiate email change with verification.
@@ -234,7 +234,7 @@ class AccountService:
logger.error(f"Failed to send email verification: {e}")
@staticmethod
def verify_email_change(*, token: str) -> Dict[str, Any]:
def verify_email_change(*, token: str) -> dict[str, Any]:
"""
Verify email change token and update user email.
@@ -375,35 +375,35 @@ class UserDeletionService:
# Transfer all submissions to deleted user
# Reviews
if hasattr(user, "park_reviews"):
getattr(user, "park_reviews").update(user=deleted_user)
user.park_reviews.update(user=deleted_user)
if hasattr(user, "ride_reviews"):
getattr(user, "ride_reviews").update(user=deleted_user)
user.ride_reviews.update(user=deleted_user)
# Photos
if hasattr(user, "uploaded_park_photos"):
getattr(user, "uploaded_park_photos").update(uploaded_by=deleted_user)
user.uploaded_park_photos.update(uploaded_by=deleted_user)
if hasattr(user, "uploaded_ride_photos"):
getattr(user, "uploaded_ride_photos").update(uploaded_by=deleted_user)
user.uploaded_ride_photos.update(uploaded_by=deleted_user)
# Top Lists
if hasattr(user, "top_lists"):
getattr(user, "top_lists").update(user=deleted_user)
user.top_lists.update(user=deleted_user)
# Moderation submissions
if hasattr(user, "edit_submissions"):
getattr(user, "edit_submissions").update(user=deleted_user)
user.edit_submissions.update(user=deleted_user)
if hasattr(user, "photo_submissions"):
getattr(user, "photo_submissions").update(user=deleted_user)
user.photo_submissions.update(user=deleted_user)
# Moderation actions - these can be set to NULL since they're not user content
if hasattr(user, "moderated_park_reviews"):
getattr(user, "moderated_park_reviews").update(moderated_by=None)
user.moderated_park_reviews.update(moderated_by=None)
if hasattr(user, "moderated_ride_reviews"):
getattr(user, "moderated_ride_reviews").update(moderated_by=None)
user.moderated_ride_reviews.update(moderated_by=None)
if hasattr(user, "handled_submissions"):
getattr(user, "handled_submissions").update(handled_by=None)
user.handled_submissions.update(handled_by=None)
if hasattr(user, "handled_photos"):
getattr(user, "handled_photos").update(handled_by=None)
user.handled_photos.update(handled_by=None)
# Store user info for the summary
user_info = {
@@ -426,7 +426,7 @@ class UserDeletionService:
}
@classmethod
def can_delete_user(cls, user: User) -> tuple[bool, Optional[str]]:
def can_delete_user(cls, user: User) -> tuple[bool, str | None]:
"""
Check if a user can be safely deleted.