""" Basis-Settings. Werden von dev.py und production.py erweitert. """ from pathlib import Path import environ BASE_DIR = Path(__file__).resolve().parent.parent.parent env = environ.Env( DJANGO_DEBUG=(bool, False), USE_X_FORWARDED_HOST=(bool, True), JOB_RETENTION_DAYS=(int, 30), ) # --- Core -------------------------------------------------------------------- SECRET_KEY = env("DJANGO_SECRET_KEY", default="dev-insecure-change-me") DEBUG = env("DJANGO_DEBUG") ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=["*"]) CSRF_TRUSTED_ORIGINS = env.list("CSRF_TRUSTED_ORIGINS", default=[]) # Hinter dem äußeren Reverse-Proxy USE_X_FORWARDED_HOST = env("USE_X_FORWARDED_HOST") _proxy_header = env("SECURE_PROXY_SSL_HEADER", default="") if _proxy_header: name, value = _proxy_header.split(",", 1) SECURE_PROXY_SSL_HEADER = (name.strip(), value.strip()) # --- Apps -------------------------------------------------------------------- INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", # 3rd party "django_celery_beat", "django_celery_results", "django_htmx", "axes", # local "mailmerge", ] MIDDLEWARE = [ "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", "django_htmx.middleware.HtmxMiddleware", "axes.middleware.AxesMiddleware", ] ROOT_URLCONF = "config.urls" TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [BASE_DIR / "templates"], "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 = "config.wsgi.application" # --- Database ---------------------------------------------------------------- DATABASES = { "default": env.db_url( "DATABASE_URL", default="sqlite:///" + str(BASE_DIR / "db.sqlite3") ), } # --- Auth -------------------------------------------------------------------- AUTH_PASSWORD_VALIDATORS = [ {"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"}, {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", "OPTIONS": {"min_length": 12}}, {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"}, {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"}, ] PASSWORD_HASHERS = [ "django.contrib.auth.hashers.Argon2PasswordHasher", "django.contrib.auth.hashers.PBKDF2PasswordHasher", ] AUTHENTICATION_BACKENDS = [ "axes.backends.AxesStandaloneBackend", "django.contrib.auth.backends.ModelBackend", ] LOGIN_URL = "/accounts/login/" LOGIN_REDIRECT_URL = "/" LOGOUT_REDIRECT_URL = "/accounts/login/" # django-axes – Brute-Force-Schutz AXES_FAILURE_LIMIT = 5 AXES_COOLOFF_TIME = 1 # Stunde AXES_LOCKOUT_PARAMETERS = ["username", "ip_address"] # --- I18N / TZ --------------------------------------------------------------- LANGUAGE_CODE = "de-at" TIME_ZONE = "Europe/Vienna" USE_I18N = True USE_TZ = True # --- Static / Media ---------------------------------------------------------- STATIC_URL = "/static/" STATIC_ROOT = BASE_DIR / "staticfiles" MEDIA_URL = "/media/" MEDIA_ROOT = BASE_DIR / "media" # --- Celery ------------------------------------------------------------------ CELERY_BROKER_URL = env("CELERY_BROKER_URL", default="redis://redis:6379/0") CELERY_RESULT_BACKEND = env("CELERY_RESULT_BACKEND", default="django-db") CELERY_TASK_TRACK_STARTED = True CELERY_TASK_TIME_LIMIT = 600 # 10 Minuten Hard-Timeout CELERY_TASK_SOFT_TIME_LIMIT = 540 CELERY_WORKER_PREFETCH_MULTIPLIER = 1 CELERY_TIMEZONE = TIME_ZONE # --- App --------------------------------------------------------------------- JOB_RETENTION_DAYS = env("JOB_RETENTION_DAYS") DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" # --- Security Defaults ------------------------------------------------------- SESSION_COOKIE_HTTPONLY = True SESSION_COOKIE_SAMESITE = "Lax" CSRF_COOKIE_HTTPONLY = False # Bleibt false, damit JS/HTMX-Forms funktionieren CSRF_COOKIE_SAMESITE = "Lax" X_FRAME_OPTIONS = "DENY" SECURE_CONTENT_TYPE_NOSNIFF = True SECURE_REFERRER_POLICY = "strict-origin-when-cross-origin"