mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-22 03:31:09 -05:00
feat: Implement avatar upload system with Cloudflare integration
- Added migration to transition avatar data from CloudflareImageField to ForeignKey structure in UserProfile. - Fixed UserProfileEvent avatar field to align with new avatar structure. - Created serializers for social authentication, including connected and available providers. - Developed request logging middleware for comprehensive request/response logging. - Updated moderation and parks migrations to remove outdated triggers and adjust foreign key relationships. - Enhanced rides migrations to ensure proper handling of image uploads and triggers. - Introduced a test script for the 3-step avatar upload process, ensuring functionality with Cloudflare. - Documented the fix for avatar upload issues, detailing root cause, implementation, and verification steps. - Implemented automatic deletion of Cloudflare images upon avatar, park, and ride photo changes or removals.
This commit is contained in:
@@ -64,6 +64,8 @@ DJANGO_APPS = [
|
||||
]
|
||||
|
||||
THIRD_PARTY_APPS = [
|
||||
# Django Cloudflare Images Toolkit - moved to top to avoid circular imports
|
||||
"django_cloudflareimages_toolkit",
|
||||
"rest_framework", # Django REST Framework
|
||||
# Token authentication (kept for backward compatibility)
|
||||
"rest_framework.authtoken",
|
||||
@@ -103,7 +105,7 @@ LOCAL_APPS = [
|
||||
"apps.parks",
|
||||
"apps.rides",
|
||||
"api", # Centralized API app (located at backend/api/)
|
||||
"apps.email_service",
|
||||
"django_forwardemail", # New PyPI package for email service
|
||||
"apps.moderation",
|
||||
]
|
||||
|
||||
@@ -171,10 +173,30 @@ else:
|
||||
|
||||
WSGI_APPLICATION = "thrillwiki.wsgi.application"
|
||||
|
||||
# Cloudflare Images Settings
|
||||
# Cloudflare Images Settings - Updated for django-cloudflareimages-toolkit
|
||||
CLOUDFLARE_IMAGES = {
|
||||
'ACCOUNT_ID': config("CLOUDFLARE_IMAGES_ACCOUNT_ID"),
|
||||
'API_TOKEN': config("CLOUDFLARE_IMAGES_API_TOKEN"),
|
||||
'ACCOUNT_HASH': config("CLOUDFLARE_IMAGES_ACCOUNT_HASH"),
|
||||
|
||||
# Optional settings
|
||||
'DEFAULT_VARIANT': 'public',
|
||||
'UPLOAD_TIMEOUT': 300,
|
||||
'WEBHOOK_SECRET': config("CLOUDFLARE_IMAGES_WEBHOOK_SECRET", default=""),
|
||||
'CLEANUP_EXPIRED_HOURS': 24,
|
||||
'MAX_FILE_SIZE': 10 * 1024 * 1024, # 10MB
|
||||
'ALLOWED_FORMATS': ['jpeg', 'png', 'gif', 'webp'],
|
||||
'REQUIRE_SIGNED_URLS': False,
|
||||
'DEFAULT_METADATA': {},
|
||||
}
|
||||
|
||||
# Storage configuration
|
||||
STORAGES = {
|
||||
"default": {
|
||||
"BACKEND": "cloudflare_images.storage.CloudflareImagesStorage",
|
||||
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
||||
"OPTIONS": {
|
||||
"location": str(BASE_DIR.parent / "shared" / "media"),
|
||||
},
|
||||
},
|
||||
"staticfiles": {
|
||||
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
|
||||
@@ -183,12 +205,6 @@ STORAGES = {
|
||||
},
|
||||
},
|
||||
}
|
||||
CLOUDFLARE_IMAGES_ACCOUNT_ID = config("CLOUDFLARE_IMAGES_ACCOUNT_ID")
|
||||
CLOUDFLARE_IMAGES_API_TOKEN = config("CLOUDFLARE_IMAGES_API_TOKEN")
|
||||
CLOUDFLARE_IMAGES_ACCOUNT_HASH = config("CLOUDFLARE_IMAGES_ACCOUNT_HASH")
|
||||
# CLOUDFLARE_IMAGES_DOMAIN should only be set if using a custom domain
|
||||
# When not set, it defaults to imagedelivery.net with the correct URL format
|
||||
# CLOUDFLARE_IMAGES_DOMAIN = config("CLOUDFLARE_IMAGES_DOMAIN", default=None)
|
||||
|
||||
# Password validation
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
@@ -299,6 +315,12 @@ ROADTRIP_BACKOFF_FACTOR = 2
|
||||
# Frontend URL Configuration
|
||||
FRONTEND_DOMAIN = config("FRONTEND_DOMAIN", default="https://thrillwiki.com")
|
||||
|
||||
# ForwardEmail Configuration
|
||||
FORWARD_EMAIL_BASE_URL = config(
|
||||
"FORWARD_EMAIL_BASE_URL", default="https://api.forwardemail.net")
|
||||
FORWARD_EMAIL_API_KEY = config("FORWARD_EMAIL_API_KEY", default="")
|
||||
FORWARD_EMAIL_DOMAIN = config("FORWARD_EMAIL_DOMAIN", default="")
|
||||
|
||||
# Django REST Framework Settings
|
||||
REST_FRAMEWORK = {
|
||||
"DEFAULT_AUTHENTICATION_CLASSES": [
|
||||
|
||||
@@ -53,8 +53,9 @@ CACHES = {
|
||||
CACHE_MIDDLEWARE_SECONDS = 1 # Very short cache for development
|
||||
CACHE_MIDDLEWARE_KEY_PREFIX = "thrillwiki_dev"
|
||||
|
||||
# Development email backend
|
||||
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
|
||||
# Development email backend - Use ForwardEmail for actual email sending
|
||||
# EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" # Console for debugging
|
||||
EMAIL_BACKEND = "django_forwardemail.backends.ForwardEmailBackend" # Actual email sending
|
||||
|
||||
# Security settings for development
|
||||
SECURE_SSL_REDIRECT = False
|
||||
@@ -63,7 +64,7 @@ CSRF_COOKIE_SECURE = False
|
||||
|
||||
# Development monitoring tools
|
||||
DEVELOPMENT_APPS = [
|
||||
"silk",
|
||||
# "silk", # Disabled for performance
|
||||
"nplusone.ext.django",
|
||||
"django_extensions",
|
||||
"widget_tweaks",
|
||||
@@ -76,11 +77,12 @@ for app in DEVELOPMENT_APPS:
|
||||
|
||||
# Development middleware
|
||||
DEVELOPMENT_MIDDLEWARE = [
|
||||
"silk.middleware.SilkyMiddleware",
|
||||
# "silk.middleware.SilkyMiddleware", # Disabled for performance
|
||||
"nplusone.ext.django.NPlusOneMiddleware",
|
||||
"core.middleware.performance_middleware.PerformanceMiddleware",
|
||||
"core.middleware.performance_middleware.QueryCountMiddleware",
|
||||
"core.middleware.nextjs.APIResponseMiddleware", # Add this
|
||||
"core.middleware.request_logging.RequestLoggingMiddleware", # Request logging
|
||||
]
|
||||
|
||||
# Add development middleware
|
||||
@@ -91,19 +93,7 @@ for middleware in DEVELOPMENT_MIDDLEWARE:
|
||||
# Debug toolbar configuration
|
||||
INTERNAL_IPS = ["127.0.0.1", "::1"]
|
||||
|
||||
# Silk configuration for development
|
||||
# Disable profiler to avoid silk_profile installation issues
|
||||
SILKY_PYTHON_PROFILER = False
|
||||
SILKY_PYTHON_PROFILER_BINARY = False # Disable binary profiler
|
||||
SILKY_PYTHON_PROFILER_RESULT_PATH = (
|
||||
BASE_DIR / "profiles"
|
||||
) # Not needed when profiler is disabled
|
||||
SILKY_AUTHENTICATION = True # Require login to access Silk
|
||||
SILKY_AUTHORISATION = True # Enable authorization
|
||||
SILKY_MAX_REQUEST_BODY_SIZE = -1 # Don't limit request body size
|
||||
# Limit response body size to 1KB for performance
|
||||
SILKY_MAX_RESPONSE_BODY_SIZE = 1024
|
||||
SILKY_META = True # Record metadata about requests
|
||||
# Silk configuration disabled for performance
|
||||
|
||||
# NPlusOne configuration
|
||||
NPLUSONE_LOGGER = logging.getLogger("nplusone")
|
||||
@@ -153,22 +143,22 @@ LOGGING = {
|
||||
"loggers": {
|
||||
"django": {
|
||||
"handlers": ["file"],
|
||||
"level": "INFO",
|
||||
"level": "WARNING", # Reduced from INFO
|
||||
"propagate": False,
|
||||
},
|
||||
"django.db.backends": {
|
||||
"handlers": ["console"],
|
||||
"level": "DEBUG",
|
||||
"level": "WARNING", # Reduced from DEBUG
|
||||
"propagate": False,
|
||||
},
|
||||
"thrillwiki": {
|
||||
"handlers": ["console", "file"],
|
||||
"level": "DEBUG",
|
||||
"level": "INFO", # Reduced from DEBUG
|
||||
"propagate": False,
|
||||
},
|
||||
"performance": {
|
||||
"handlers": ["performance"],
|
||||
"level": "INFO",
|
||||
"level": "WARNING", # Reduced from INFO
|
||||
"propagate": False,
|
||||
},
|
||||
"query_optimization": {
|
||||
@@ -178,7 +168,12 @@ LOGGING = {
|
||||
},
|
||||
"nplusone": {
|
||||
"handlers": ["console"],
|
||||
"level": "WARNING",
|
||||
"level": "ERROR", # Reduced from WARNING
|
||||
"propagate": False,
|
||||
},
|
||||
"request_logging": {
|
||||
"handlers": ["console"],
|
||||
"level": "INFO",
|
||||
"propagate": False,
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user