from pathlib import Path import os from django.core.exceptions import ImproperlyConfigured BASE_DIR = Path(__file__).resolve().parent.parent def env_bool(name: str, default: bool = False) -> bool: return os.getenv(name, str(default)).lower() in {"1", "true", "yes", "on"} SECRET_KEY = os.getenv("SECRET_KEY", "development-only-change-me") DEBUG = env_bool("DEBUG", True) if not DEBUG and SECRET_KEY == "development-only-change-me": raise ImproperlyConfigured("SECRET_KEY muss im Produktionsbetrieb gesetzt sein.") ALLOWED_HOSTS = [value.strip() for value in os.getenv("ALLOWED_HOSTS", "localhost,127.0.0.1").split(",") if value.strip()] CSRF_TRUSTED_ORIGINS = [value.strip() for value in os.getenv("CSRF_TRUSTED_ORIGINS", "").split(",") if value.strip()] INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "rest_framework", "rest_framework_api_key", "inventory", ] MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "whitenoise.middleware.WhiteNoiseMiddleware", "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", ] ROOT_URLCONF = "csr_inventory.urls" TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [], "APP_DIRS": True, "OPTIONS": { "context_processors": [ "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", "inventory.context_processors.navigation_context", ], }, } ] WSGI_APPLICATION = "csr_inventory.wsgi.application" DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql", "NAME": os.getenv("POSTGRES_DB", "csr_inventory"), "USER": os.getenv("POSTGRES_USER", "csr_inventory"), "PASSWORD": os.getenv("POSTGRES_PASSWORD", ""), "HOST": os.getenv("POSTGRES_HOST", "localhost"), "PORT": os.getenv("POSTGRES_PORT", "5432"), "CONN_MAX_AGE": 60, "OPTIONS": {"connect_timeout": 5}, } } 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"}, ] LANGUAGE_CODE = "de-de" TIME_ZONE = os.getenv("TIME_ZONE", "Europe/Berlin") USE_I18N = True USE_TZ = True STATIC_URL = "/static/" STATIC_ROOT = BASE_DIR / "staticfiles" MEDIA_URL = "/media/" MEDIA_ROOT = BASE_DIR / "media" DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" LOGIN_URL = "login" LOGIN_REDIRECT_URL = "inventory:device-list" LOGOUT_REDIRECT_URL = "login" DATA_UPLOAD_MAX_MEMORY_SIZE = int(os.getenv("MAX_UPLOAD_SIZE", str(10 * 1024 * 1024))) FILE_UPLOAD_MAX_MEMORY_SIZE = DATA_UPLOAD_MAX_MEMORY_SIZE SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") SESSION_COOKIE_SECURE = env_bool("SECURE_COOKIES", not DEBUG) CSRF_COOKIE_SECURE = env_bool("SECURE_COOKIES", not DEBUG) SESSION_COOKIE_HTTPONLY = True SESSION_COOKIE_SAMESITE = "Lax" CSRF_COOKIE_HTTPONLY = False CSRF_COOKIE_SAMESITE = "Lax" SECURE_CONTENT_TYPE_NOSNIFF = True SECURE_REFERRER_POLICY = "same-origin" X_FRAME_OPTIONS = "DENY" SECURE_HSTS_SECONDS = 31536000 if not DEBUG else 0 SECURE_HSTS_INCLUDE_SUBDOMAINS = not DEBUG SECURE_HSTS_PRELOAD = not DEBUG SECURE_SSL_REDIRECT = env_bool("SECURE_SSL_REDIRECT", not DEBUG) STORAGES = { "default": {"BACKEND": "django.core.files.storage.FileSystemStorage"}, "staticfiles": { "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage" if DEBUG else "whitenoise.storage.CompressedManifestStaticFilesStorage" }, } # Die API verwendet absichtlich keine Browser-Sitzung. Ohne einen gültigen, # widerrufbaren API-Schlüssel wird jede API-Anfrage abgewiesen. REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ["inventory.api_auth.InventoryAPIKeyAuthentication"], "DEFAULT_PERMISSION_CLASSES": ["inventory.api_auth.InventoryAPIPermission"], "DEFAULT_RENDERER_CLASSES": ["rest_framework.renderers.JSONRenderer"], "DEFAULT_PARSER_CLASSES": ["rest_framework.parsers.JSONParser"], "DEFAULT_PAGINATION_CLASS": "inventory.api_pagination.PagedDeviceResults", "PAGE_SIZE": 50, "DEFAULT_THROTTLE_CLASSES": [ "rest_framework.throttling.AnonRateThrottle", "inventory.api_auth.APIClientRateThrottle", ], "DEFAULT_THROTTLE_RATES": { "anon": os.getenv("API_ANON_RATE", "20/min"), "api_client": os.getenv("API_CLIENT_RATE", "300/min"), }, } LOGGING = { "version": 1, "disable_existing_loggers": False, "formatters": {"standard": {"format": "{levelname} {asctime} {name}: {message}", "style": "{"}}, "handlers": {"console": {"class": "logging.StreamHandler", "formatter": "standard"}}, "root": {"handlers": ["console"], "level": os.getenv("LOG_LEVEL", "WARNING")}, }