"""Django settings for IoT PreTester 4.6 Demo.""" import os from pathlib import Path from django.core.exceptions import ImproperlyConfigured BASE_DIR = Path(__file__).resolve().parent.parent def env_bool(name: str, default: bool = False) -> bool: return os.environ.get(name, str(default)).strip().lower() in {"1", "true", "yes"} DEBUG = env_bool("DEBUG", False) SECRET_KEY = os.environ.get("SECRET_KEY") if not SECRET_KEY: if DEBUG: SECRET_KEY = "django-insecure-iot-pretester-4.6-demo-local-only" else: raise ImproperlyConfigured("SECRET_KEY must be configured when DEBUG is disabled.") ALLOWED_HOSTS = [ host.strip() for host in os.environ.get("ALLOWED_HOSTS", "localhost,127.0.0.1").split(",") if host.strip() ] INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "corsheaders", "rest_framework", "IoTAnalyzer", ] MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "corsheaders.middleware.CorsMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", "IoTAnalyzer.middleware.RequestLogMiddleware", ] ROOT_URLCONF = "IoTPreTester.urls" WSGI_APPLICATION = "IoTPreTester.wsgi.application" 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", ] }, } ] DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", "NAME": os.environ.get("DATABASE_PATH", BASE_DIR / "db.sqlite3"), "OPTIONS": {"timeout": 30}, } } 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"}, ] PASSWORD_HASHERS = [ "django.contrib.auth.hashers.BCryptSHA256PasswordHasher", "django.contrib.auth.hashers.PBKDF2PasswordHasher", ] REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": [ "IoTAnalyzer.authentication.DemoSessionAuthentication", ], "DEFAULT_PERMISSION_CLASSES": [ "rest_framework.permissions.IsAuthenticated", ], "DEFAULT_THROTTLE_CLASSES": [ "rest_framework.throttling.UserRateThrottle", ], "DEFAULT_THROTTLE_RATES": {"user": "20/second"}, } CORS_ALLOW_ALL_ORIGINS = env_bool("CORS_ALLOW_ALL_ORIGINS", False) CORS_ALLOWED_ORIGINS = [ origin.strip() for origin in os.environ.get("CORS_ALLOWED_ORIGINS", "http://localhost:3000").split(",") if origin.strip() ] CORS_ALLOW_CREDENTIALS = True LANGUAGE_CODE = "en-us" TIME_ZONE = "UTC" USE_I18N = True USE_TZ = True STATIC_URL = "static/" STATIC_ROOT = BASE_DIR / "staticfiles" CAPTURE_UPLOAD_DIR = Path( os.environ.get("CAPTURE_UPLOAD_DIR", BASE_DIR.parent / "uploads") ) def env_int(name: str, default: int) -> int: try: return int(os.environ.get(name, default)) except (TypeError, ValueError): return default # Bounds for a single capture analysis pass. 0 disables the packet limit and # reads the capture completely; large captures then take correspondingly longer. CAPTURE_PACKET_LIMIT = env_int("CAPTURE_PACKET_LIMIT", 0) CAPTURE_MAX_TEXT_PAYLOADS = env_int("CAPTURE_MAX_TEXT_PAYLOADS", 20000) CAPTURE_MAX_PAYLOAD_CHARS = env_int("CAPTURE_MAX_PAYLOAD_CHARS", 16384) # --- Logging ----------------------------------------------------------------- # Console output goes to the container log; backend.log keeps a rotating copy. # Every capture analysis additionally writes .analysis.log next to # the upload, which the API exposes for troubleshooting. LOG_DIR = Path(os.environ.get("LOG_DIR", BASE_DIR.parent / "logs")) LOG_LEVEL = os.environ.get("LOG_LEVEL", "info").upper() try: LOG_DIR.mkdir(parents=True, exist_ok=True) _FILE_LOGGING = True except OSError: _FILE_LOGGING = False LOGGING = { "version": 1, "disable_existing_loggers": False, "formatters": { "standard": { "format": "%(asctime)s %(levelname)-7s [%(name)s] %(message)s", "datefmt": "%Y-%m-%d %H:%M:%S", }, }, "handlers": { "console": { "class": "logging.StreamHandler", "formatter": "standard", "stream": "ext://sys.stdout", }, **({ "file": { "class": "logging.handlers.RotatingFileHandler", "formatter": "standard", "filename": str(LOG_DIR / "backend.log"), "maxBytes": 10 * 1024 * 1024, "backupCount": 5, "encoding": "utf-8", }, } if _FILE_LOGGING else {}), }, "root": { "handlers": ["console"] + (["file"] if _FILE_LOGGING else []), "level": LOG_LEVEL, }, "loggers": { "django": {"level": "INFO", "propagate": True}, "django.request": {"level": "WARNING", "propagate": True}, "django.server": {"level": "INFO", "propagate": True}, "IoTAnalyzer": {"level": LOG_LEVEL, "propagate": True}, "analyzer": {"level": LOG_LEVEL, "propagate": True}, }, } DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" APPEND_SLASH = False SESSION_COOKIE_HTTPONLY = True SESSION_COOKIE_SAMESITE = "Lax" X_FRAME_OPTIONS = "DENY" SECURE_CONTENT_TYPE_NOSNIFF = True if not DEBUG: SESSION_COOKIE_SECURE = env_bool("SESSION_COOKIE_SECURE", False) CSRF_COOKIE_SECURE = env_bool("CSRF_COOKIE_SECURE", False)