""" Django settings for workout_challenge project. Generated by 'django-admin startproject' using Django 4.2.20. For more information on this file, see https://docs.djangoproject.com/en/4.2/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/4.2/ref/settings/ """ import os import datetime, pytz from pathlib import Path from urllib.parse import urlparse import sentry_sdk from sentry_sdk.integrations.django import DjangoIntegration from sentry_sdk.integrations.celery import CeleryIntegration # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent DATA_DIR = BASE_DIR / "data" QR_CODE_PATH = BASE_DIR.parent / "src-frontend" / "public" # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = os.environ.get("SECRET_KEY", 'django-insecure-y4cob-qij5d!!h6^oy8bt_xqtuo%3s$w(^=7wq%9w%ckd(--9t') # SECURITY WARNING: don't run with debug turned on in production! DEBUG = os.environ.get("DEBUG", "false").lower() == "true" print(f'Debug modus is turned {"on" if DEBUG else "off"}') MAIN_HOST = os.environ.get("MAIN_HOST", "http://localhost") HOSTS = os.environ.get("HOSTS", "http://localhost,http://127.0.0.1").split(",") CSRF_TRUSTED_ORIGINS = HOSTS ALLOWED_HOSTS = [urlparse(url).netloc for url in HOSTS] CORS_ALLOWED_ORIGINS = HOSTS CORS_ALLOW_ALL_ORIGINS = True if DEBUG else False CORS_ALLOW_CREDENTIALS = True # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'corsheaders', 'rest_framework', 'django_filters', 'celery', 'django_celery_beat', 'competition', 'workouts', 'custom_user', ] MIDDLEWARE = [ "corsheaders.middleware.CorsMiddleware", "django.middleware.common.CommonMiddleware", 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] AUTH_USER_MODEL = "custom_user.CustomUser" ROOT_URLCONF = 'workout_challenge.urls' MIGRATION_MODULES = { "competition": "data.db_migrations.competition", "workouts": "data.db_migrations.workouts", "custom_user": "data.db_migrations.custom_user", # "django_celery_beat": "data.db_migrations.django_celery_beat", # "django_celery_beat_periodictask": "data.db_migrations.django_celery_beat_periodictask", # "sessions": "data.db_migrations.sessions", # "auth": "data.db_migrations.auth", # "authtoken": "data.db_migrations.authtoken", # "admin": "data.db_migrations.admin", # "contenttypes": "data.db_migrations.contenttypes", } TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'workout_challenge.wsgi.application' # Database # https://docs.djangoproject.com/en/4.2/ref/settings/#databases DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", "NAME": DATA_DIR / 'db.sqlite3', "OPTIONS": { "timeout": 20, # seconds }, } if os.environ.get("POSTGRES_HOST", None) is None else { "ENGINE": "django.db.backends.postgresql", "NAME": os.environ.get("POSTGRES_DB", "postgres"), "USER": os.environ.get("POSTGRES_USER", "postgres"), "PASSWORD": os.environ.get("POSTGRES_PASSWORD", ""), "HOST": os.environ.get("POSTGRES_HOST", "localhost"), "PORT": "", } } # Password validation # https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': [ 'django_filters.rest_framework.DjangoFilterBackend', ], 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework_simplejwt.authentication.JWTAuthentication', ], 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ], } SIMPLE_JWT = { 'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=5), 'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=5), 'ROTATE_REFRESH_TOKENS': False, 'BLACKLIST_AFTER_ROTATION': True, 'UPDATE_LAST_LOGIN': False, } PASSWORD_RESET_TIMEOUT = 600 # seconds = 10 minutes # Internationalization # https://docs.djangoproject.com/en/4.2/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = CELERY_TIMEZONE = os.environ.get("TIME_ZONE", "Europe/London") TIME_ZONE_OBJ = pytz.timezone(TIME_ZONE) USE_I18N = True USE_TZ = True # Celery CELERY_BROKER_URL = 'redis://localhost:6379/0' CELERY_RESULT_BACKEND = 'redis://localhost:6379/0' CACHES = { 'default': ({ 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', } if DEBUG else { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://0.0.0.0:6379/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS": { "max_connections": 100, "retry_on_timeout": True }, "SOCKET_CONNECT_TIMEOUT": 5, "SOCKET_TIMEOUT": 5, } }) } # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.2/howto/static-files/ STATIC_URL = 'apistatic/' STATIC_ROOT = BASE_DIR / 'static' # Default primary key field type # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' # Strava API STRAVA_CLIENT_ID = int(os.environ.get("STRAVA_CLIENT_ID", 1234321)) STRAVA_CLIENT_SECRET = os.environ.get("STRAVA_CLIENT_SECRET", "ReplaceWithClientSecret") STRAVA_LIMIT_15MIN = int(os.environ.get("STRAVA_LIMIT_15MIN", 100)) STRAVA_LIMIT_DAY = int(os.environ.get("STRAVA_LIMIT_DAY", 1000)) # Sentry if (sentry_sdk_url := os.environ.get("REACT_APP_SENTRY_DSN", None)) is not None: sentry_sdk.init( dsn=sentry_sdk_url, environment="backend", send_default_pii=False, enable_tracing=True, traces_sample_rate=0.25, profiles_sample_rate=1.0, integrations=[ DjangoIntegration(), CeleryIntegration(monitor_beat_tasks=True), ], ) # Emails EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" EMAIL_HOST = os.environ.get("EMAIL_HOST", None) EMAIL_PORT = int(os.environ.get("EMAIL_PORT", 25)) EMAIL_HOST_USER = os.environ.get("EMAIL_HOST_USER", None) EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD", None) EMAIL_USE_TLS = None if (use_ssl := os.environ.get("EMAIL_USE_TLS", None)) is None else bool(use_ssl) EMAIL_USE_SSL = None if (use_ssl := os.environ.get("EMAIL_USE_SSL", None)) is None else bool(use_ssl) EMAIL_FROM = DEFAULT_FROM_EMAIL = os.environ.get("EMAIL_FROM", None) EMAIL_REPLY_TO = None if (reply_email := os.environ.get("EMAIL_REPLY_TO", None)) is None else reply_email.split(",") # OpenAI for AI quotes OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY", None)