feat: Implement initial schema and add various API, service, and management command enhancements across the application.

This commit is contained in:
pacnpal
2026-01-01 15:13:01 -05:00
parent c95f99ca10
commit b243b17af7
413 changed files with 11164 additions and 17433 deletions

View File

@@ -187,6 +187,7 @@ class PublicUserSerializer(serializers.ModelSerializer):
Public user serializer for viewing other users' profiles.
Only exposes public information.
"""
profile = UserProfileSerializer(read_only=True)
class Meta:
@@ -228,37 +229,21 @@ class UserPreferencesSerializer(serializers.Serializer):
"""Serializer for user preferences and settings."""
theme_preference = RichChoiceFieldSerializer(
choice_group="theme_preferences",
domain="accounts",
help_text="User's theme preference"
)
email_notifications = serializers.BooleanField(
default=True, help_text="Whether to receive email notifications"
)
push_notifications = serializers.BooleanField(
default=False, help_text="Whether to receive push notifications"
choice_group="theme_preferences", domain="accounts", help_text="User's theme preference"
)
email_notifications = serializers.BooleanField(default=True, help_text="Whether to receive email notifications")
push_notifications = serializers.BooleanField(default=False, help_text="Whether to receive push notifications")
privacy_level = RichChoiceFieldSerializer(
choice_group="privacy_levels",
domain="accounts",
default="public",
help_text="Profile visibility level",
)
show_email = serializers.BooleanField(
default=False, help_text="Whether to show email on profile"
)
show_real_name = serializers.BooleanField(
default=True, help_text="Whether to show real name on profile"
)
show_statistics = serializers.BooleanField(
default=True, help_text="Whether to show ride statistics on profile"
)
allow_friend_requests = serializers.BooleanField(
default=True, help_text="Whether to allow friend requests"
)
allow_messages = serializers.BooleanField(
default=True, help_text="Whether to allow direct messages"
)
show_email = serializers.BooleanField(default=False, help_text="Whether to show email on profile")
show_real_name = serializers.BooleanField(default=True, help_text="Whether to show real name on profile")
show_statistics = serializers.BooleanField(default=True, help_text="Whether to show ride statistics on profile")
allow_friend_requests = serializers.BooleanField(default=True, help_text="Whether to allow friend requests")
allow_messages = serializers.BooleanField(default=True, help_text="Whether to allow direct messages")
# === NOTIFICATION SETTINGS SERIALIZERS ===
@@ -363,39 +348,17 @@ class PrivacySettingsSerializer(serializers.Serializer):
default="public",
help_text="Overall profile visibility",
)
show_email = serializers.BooleanField(
default=False, help_text="Show email address on profile"
)
show_real_name = serializers.BooleanField(
default=True, help_text="Show real name on profile"
)
show_join_date = serializers.BooleanField(
default=True, help_text="Show join date on profile"
)
show_statistics = serializers.BooleanField(
default=True, help_text="Show ride statistics on profile"
)
show_reviews = serializers.BooleanField(
default=True, help_text="Show reviews on profile"
)
show_photos = serializers.BooleanField(
default=True, help_text="Show uploaded photos on profile"
)
show_top_lists = serializers.BooleanField(
default=True, help_text="Show top lists on profile"
)
allow_friend_requests = serializers.BooleanField(
default=True, help_text="Allow others to send friend requests"
)
allow_messages = serializers.BooleanField(
default=True, help_text="Allow others to send direct messages"
)
allow_profile_comments = serializers.BooleanField(
default=False, help_text="Allow others to comment on profile"
)
search_visibility = serializers.BooleanField(
default=True, help_text="Allow profile to appear in search results"
)
show_email = serializers.BooleanField(default=False, help_text="Show email address on profile")
show_real_name = serializers.BooleanField(default=True, help_text="Show real name on profile")
show_join_date = serializers.BooleanField(default=True, help_text="Show join date on profile")
show_statistics = serializers.BooleanField(default=True, help_text="Show ride statistics on profile")
show_reviews = serializers.BooleanField(default=True, help_text="Show reviews on profile")
show_photos = serializers.BooleanField(default=True, help_text="Show uploaded photos on profile")
show_top_lists = serializers.BooleanField(default=True, help_text="Show top lists on profile")
allow_friend_requests = serializers.BooleanField(default=True, help_text="Allow others to send friend requests")
allow_messages = serializers.BooleanField(default=True, help_text="Allow others to send direct messages")
allow_profile_comments = serializers.BooleanField(default=False, help_text="Allow others to comment on profile")
search_visibility = serializers.BooleanField(default=True, help_text="Allow profile to appear in search results")
activity_visibility = RichChoiceFieldSerializer(
choice_group="privacy_levels",
domain="accounts",
@@ -431,21 +394,13 @@ class SecuritySettingsSerializer(serializers.Serializer):
two_factor_enabled = serializers.BooleanField(
default=False, help_text="Whether two-factor authentication is enabled"
)
login_notifications = serializers.BooleanField(
default=True, help_text="Send notifications for new logins"
)
login_notifications = serializers.BooleanField(default=True, help_text="Send notifications for new logins")
session_timeout = serializers.IntegerField(
default=30, min_value=5, max_value=180, help_text="Session timeout in days"
)
require_password_change = serializers.BooleanField(
default=False, help_text="Whether password change is required"
)
last_password_change = serializers.DateTimeField(
read_only=True, help_text="When password was last changed"
)
active_sessions = serializers.IntegerField(
read_only=True, help_text="Number of active sessions"
)
require_password_change = serializers.BooleanField(default=False, help_text="Whether password change is required")
last_password_change = serializers.DateTimeField(read_only=True, help_text="When password was last changed")
active_sessions = serializers.IntegerField(read_only=True, help_text="Number of active sessions")
login_history_retention = serializers.IntegerField(
default=90,
min_value=30,
@@ -699,7 +654,7 @@ class ThemePreferenceSerializer(serializers.ModelSerializer):
"id": 1,
"notification_type": "submission_approved",
"title": "Your submission has been approved!",
"message": "Your photo submission for Cedar Point has been approved and is now live on the site.",
"detail": "Your photo submission for Cedar Point has been approved and is now live on the site.",
"priority": "normal",
"is_read": False,
"read_at": None,
@@ -866,15 +821,11 @@ class MarkNotificationsReadSerializer(serializers.Serializer):
def validate_notification_ids(self, value):
"""Validate that all notification IDs belong to the requesting user."""
user = self.context["request"].user
valid_ids = UserNotification.objects.filter(
id__in=value, user=user
).values_list("id", flat=True)
valid_ids = UserNotification.objects.filter(id__in=value, user=user).values_list("id", flat=True)
invalid_ids = set(value) - set(valid_ids)
if invalid_ids:
raise serializers.ValidationError(
f"Invalid notification IDs: {list(invalid_ids)}"
)
raise serializers.ValidationError(f"Invalid notification IDs: {list(invalid_ids)}")
return value
@@ -901,9 +852,8 @@ class AvatarUploadSerializer(serializers.Serializer):
raise serializers.ValidationError("No file provided")
# Check file size constraints (max 10MB for Cloudflare Images)
if hasattr(value, 'size') and value.size > 10 * 1024 * 1024:
raise serializers.ValidationError(
"Image file too large. Maximum size is 10MB.")
if hasattr(value, "size") and value.size > 10 * 1024 * 1024:
raise serializers.ValidationError("Image file too large. Maximum size is 10MB.")
# Try to validate with PIL
try:
@@ -926,13 +876,13 @@ class AvatarUploadSerializer(serializers.Serializer):
# Check image dimensions (max 12,000x12,000 for Cloudflare Images)
if image.size[0] > 12000 or image.size[1] > 12000:
raise serializers.ValidationError(
"Image dimensions too large. Maximum is 12,000x12,000 pixels.")
raise serializers.ValidationError("Image dimensions too large. Maximum is 12,000x12,000 pixels.")
# Check if it's a supported format
if image.format not in ['JPEG', 'PNG', 'GIF', 'WEBP']:
if image.format not in ["JPEG", "PNG", "GIF", "WEBP"]:
raise serializers.ValidationError(
f"Unsupported image format: {image.format}. Supported formats: JPEG, PNG, GIF, WebP.")
f"Unsupported image format: {image.format}. Supported formats: JPEG, PNG, GIF, WebP."
)
except serializers.ValidationError:
raise # Re-raise validation errors