""" Production settings for KeepItGoing SaaS. Use this for the hosted SaaS deployment. """ import os from .base import * # Security SECRET_KEY = os.environ['SECRET_KEY'] DEBUG = False # ALLOWED_HOSTS must be explicitly set in production if not os.environ.get('ALLOWED_HOSTS'): raise ValueError( "ALLOWED_HOSTS environment variable is required in production. " "Set to comma-separated list of allowed domains (e.g., 'example.com,www.example.com')" ) ALLOWED_HOSTS = os.environ['ALLOWED_HOSTS'].split(',') # Force HTTPS SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') SECURE_SSL_REDIRECT = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True SECURE_HSTS_SECONDS = 31536000 # 1 year SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_HSTS_PRELOAD = True # Security Headers SECURE_BROWSER_XSS_FILTER = True SECURE_CONTENT_TYPE_NOSNIFF = True X_FRAME_OPTIONS = 'DENY' # Prevents clickjacking SECURE_REFERRER_POLICY = 'strict-origin-when-cross-origin' # Cookie Security SESSION_COOKIE_HTTPONLY = True SESSION_COOKIE_SAMESITE = 'Strict' CSRF_COOKIE_HTTPONLY = True CSRF_COOKIE_SAMESITE = 'Strict' # Content Security Policy (CSP) # Note: Adjust as needed based on your frontend requirements CSP_DEFAULT_SRC = ("'self'",) CSP_SCRIPT_SRC = ("'self'",) # Remove 'unsafe-inline' if possible CSP_STYLE_SRC = ("'self'",) # Remove 'unsafe-inline' if possible CSP_IMG_SRC = ("'self'", "data:", "https:") CSP_FONT_SRC = ("'self'",) CSP_CONNECT_SRC = ("'self'",) CSP_FRAME_ANCESTORS = ("'none'",) # Prevents embedding in iframes CSP_BASE_URI = ("'self'",) CSP_FORM_ACTION = ("'self'",) # Database import dj_database_url DATABASES = { 'default': dj_database_url.config( default=os.environ.get('DATABASE_URL'), conn_max_age=600, conn_health_checks=True, ) } # Redis/Celery CELERY_BROKER_URL = os.environ['REDIS_URL'] CELERY_RESULT_BACKEND = os.environ['REDIS_URL'] # Cache CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.redis.RedisCache', 'LOCATION': os.environ['REDIS_URL'], } } # CORS CORS_ALLOWED_ORIGINS = os.environ.get('CORS_ALLOWED_ORIGINS', '').split(',') # CSRF CSRF_TRUSTED_ORIGINS = os.environ.get('CSRF_TRUSTED_ORIGINS', '').split(',') if os.environ.get('CSRF_TRUSTED_ORIGINS') else [] # Static files STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' # Email EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = os.environ.get('EMAIL_HOST', '') EMAIL_PORT = int(os.environ.get('EMAIL_PORT', 587)) EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER', '') EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD', '') EMAIL_USE_TLS = os.environ.get('EMAIL_USE_TLS', 'True').lower() == 'true' DEFAULT_FROM_EMAIL = os.environ.get('DEFAULT_FROM_EMAIL', 'noreply@keepitgoing.app') # SaaS mode enabled SAAS_MODE = True BILLING_ENABLED = True USAGE_LIMITS_ENABLED = True # Logging LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { 'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}', 'style': '{', }, }, 'handlers': { 'console': { 'class': 'logging.StreamHandler', 'formatter': 'verbose', }, }, 'root': { 'handlers': ['console'], 'level': 'WARNING', }, 'loggers': { 'django': { 'handlers': ['console'], 'level': 'WARNING', 'propagate': False, }, }, }