""" Third-party application configuration for thrillwiki project. This module configures third-party Django applications including: - django-allauth (authentication) - Celery (task queue) - Health checks - Tailwind CSS - Cloudflare Images - Road Trip service Why python-decouple? - Already used in base.py for consistency - Simpler API than django-environ - Sufficient for our configuration needs - Better separation of config from code """ from decouple import config # ============================================================================= # Django Allauth Configuration # ============================================================================= # https://django-allauth.readthedocs.io/ SITE_ID = 1 # Signup fields configuration # The asterisks indicate required fields ACCOUNT_SIGNUP_FIELDS = ["email*", "username*", "password1*", "password2*"] # Login methods - allow both email and username ACCOUNT_LOGIN_METHODS = {"email", "username"} # Email verification settings ACCOUNT_EMAIL_VERIFICATION = config( "ACCOUNT_EMAIL_VERIFICATION", default="mandatory" ) ACCOUNT_EMAIL_VERIFICATION_SUPPORTS_CHANGE = True ACCOUNT_EMAIL_VERIFICATION_SUPPORTS_RESEND = True # Security settings ACCOUNT_REAUTHENTICATION_REQUIRED = True ACCOUNT_EMAIL_NOTIFICATIONS = True ACCOUNT_EMAIL_UNKNOWN_ACCOUNTS = False # Redirect URLs LOGIN_REDIRECT_URL = config("LOGIN_REDIRECT_URL", default="/") ACCOUNT_LOGOUT_REDIRECT_URL = config("ACCOUNT_LOGOUT_REDIRECT_URL", default="/") # Custom adapters for extending allauth behavior ACCOUNT_ADAPTER = "apps.accounts.adapters.CustomAccountAdapter" SOCIALACCOUNT_ADAPTER = "apps.accounts.adapters.CustomSocialAccountAdapter" # Social account provider settings SOCIALACCOUNT_PROVIDERS = { "google": { "SCOPE": [ "profile", "email", ], "AUTH_PARAMS": {"access_type": "online"}, }, "discord": { "SCOPE": ["identify", "email"], "OAUTH_PKCE_ENABLED": True, }, } # Additional social account settings SOCIALACCOUNT_LOGIN_ON_GET = True SOCIALACCOUNT_AUTO_SIGNUP = False SOCIALACCOUNT_STORE_TOKENS = True # ============================================================================= # Celery Configuration # ============================================================================= # Celery task queue settings (actual Celery config is in config/celery.py) CELERY_BROKER_URL = config("REDIS_URL", default="redis://localhost:6379/1") CELERY_RESULT_BACKEND = config("REDIS_URL", default="redis://localhost:6379/1") # Task settings for test environments CELERY_TASK_ALWAYS_EAGER = config( "CELERY_TASK_ALWAYS_EAGER", default=False, cast=bool ) CELERY_TASK_EAGER_PROPAGATES = config( "CELERY_TASK_EAGER_PROPAGATES", default=False, cast=bool ) # ============================================================================= # Health Check Configuration # ============================================================================= # https://django-health-check.readthedocs.io/ HEALTH_CHECK = { "DISK_USAGE_MAX": config("HEALTH_CHECK_DISK_USAGE_MAX", default=90, cast=int), "MEMORY_MIN": config("HEALTH_CHECK_MEMORY_MIN", default=100, cast=int), } # Custom health check backends HEALTH_CHECK_BACKENDS = [ "health_check.db", "health_check.cache", "health_check.storage", "core.health_checks.custom_checks.CacheHealthCheck", "core.health_checks.custom_checks.DatabasePerformanceCheck", "core.health_checks.custom_checks.ApplicationHealthCheck", "core.health_checks.custom_checks.ExternalServiceHealthCheck", "core.health_checks.custom_checks.DiskSpaceHealthCheck", ] # ============================================================================= # Tailwind CSS Configuration # ============================================================================= # https://django-tailwind.readthedocs.io/ TAILWIND_CLI_CONFIG_FILE = "tailwind.config.js" TAILWIND_CLI_SRC_CSS = "static/css/src/input.css" TAILWIND_CLI_DIST_CSS = "css/tailwind.css" # ============================================================================= # Cloudflare Images Configuration # ============================================================================= # https://developers.cloudflare.com/images/ CLOUDFLARE_IMAGES = { "ACCOUNT_ID": config("CLOUDFLARE_IMAGES_ACCOUNT_ID", default=""), "API_TOKEN": config("CLOUDFLARE_IMAGES_API_TOKEN", default=""), "ACCOUNT_HASH": config("CLOUDFLARE_IMAGES_ACCOUNT_HASH", default=""), # Optional settings "DEFAULT_VARIANT": config("CLOUDFLARE_IMAGES_DEFAULT_VARIANT", default="public"), "UPLOAD_TIMEOUT": config("CLOUDFLARE_IMAGES_UPLOAD_TIMEOUT", default=300, cast=int), "WEBHOOK_SECRET": config("CLOUDFLARE_IMAGES_WEBHOOK_SECRET", default=""), "CLEANUP_EXPIRED_HOURS": config( "CLOUDFLARE_IMAGES_CLEANUP_HOURS", default=24, cast=int ), "MAX_FILE_SIZE": config( "CLOUDFLARE_IMAGES_MAX_FILE_SIZE", default=10 * 1024 * 1024, cast=int ), "ALLOWED_FORMATS": ["jpeg", "png", "gif", "webp"], "REQUIRE_SIGNED_URLS": config( "CLOUDFLARE_IMAGES_REQUIRE_SIGNED_URLS", default=False, cast=bool ), "DEFAULT_METADATA": {}, } # ============================================================================= # Road Trip Service Configuration # ============================================================================= # Settings for the road trip planning service using OpenStreetMap ROADTRIP_CACHE_TIMEOUT = config( "ROADTRIP_CACHE_TIMEOUT", default=3600 * 24, cast=int ) # 24 hours for geocoding ROADTRIP_ROUTE_CACHE_TIMEOUT = config( "ROADTRIP_ROUTE_CACHE_TIMEOUT", default=3600 * 6, cast=int ) # 6 hours for routes ROADTRIP_MAX_REQUESTS_PER_SECOND = config( "ROADTRIP_MAX_REQUESTS_PER_SECOND", default=1, cast=int ) # Respect OSM rate limits ROADTRIP_USER_AGENT = config( "ROADTRIP_USER_AGENT", default="ThrillWiki/1.0 (https://thrillwiki.com)" ) ROADTRIP_REQUEST_TIMEOUT = config( "ROADTRIP_REQUEST_TIMEOUT", default=10, cast=int ) # seconds ROADTRIP_MAX_RETRIES = config("ROADTRIP_MAX_RETRIES", default=3, cast=int) ROADTRIP_BACKOFF_FACTOR = config("ROADTRIP_BACKOFF_FACTOR", default=2, cast=int) # ============================================================================= # Autocomplete Configuration # ============================================================================= # django-autocomplete-light settings AUTOCOMPLETE_BLOCK_UNAUTHENTICATED = config( "AUTOCOMPLETE_BLOCK_UNAUTHENTICATED", default=False, cast=bool ) # ============================================================================= # Frontend Configuration # ============================================================================= FRONTEND_DOMAIN = config("FRONTEND_DOMAIN", default="https://thrillwiki.com")