2024-01-09 15:30:36 +01:00
|
|
|
"""
|
2024-03-07 19:46:46 +01:00
|
|
|
Django settings for impress project.
|
2024-01-09 15:30:36 +01:00
|
|
|
|
|
|
|
|
Generated by 'django-admin startproject' using Django 3.1.5.
|
|
|
|
|
|
|
|
|
|
For more information on this file, see
|
|
|
|
|
https://docs.djangoproject.com/en/3.1/topics/settings/
|
|
|
|
|
|
|
|
|
|
For the full list of settings and their values, see
|
|
|
|
|
https://docs.djangoproject.com/en/3.1/ref/settings/
|
|
|
|
|
"""
|
2024-08-20 16:42:27 +02:00
|
|
|
|
2024-01-09 15:30:36 +01:00
|
|
|
import os
|
2024-11-18 12:31:49 +01:00
|
|
|
import tomllib
|
2024-11-22 11:55:30 +01:00
|
|
|
from socket import gethostbyname, gethostname
|
2024-01-09 15:30:36 +01:00
|
|
|
|
|
|
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
|
|
|
|
|
|
import sentry_sdk
|
|
|
|
|
from configurations import Configuration, values
|
|
|
|
|
from sentry_sdk.integrations.django import DjangoIntegration
|
2025-03-04 17:19:53 +01:00
|
|
|
from sentry_sdk.integrations.logging import ignore_logger
|
2024-01-09 15:30:36 +01:00
|
|
|
|
|
|
|
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
|
|
|
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
|
DATA_DIR = os.path.join("/", "data")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_release():
|
|
|
|
|
"""
|
|
|
|
|
Get the current release of the application
|
|
|
|
|
"""
|
|
|
|
|
try:
|
2024-11-18 12:31:49 +01:00
|
|
|
with open(os.path.join(BASE_DIR, "pyproject.toml"), "rb") as f:
|
|
|
|
|
pyproject_data = tomllib.load(f)
|
|
|
|
|
return pyproject_data["project"]["version"]
|
|
|
|
|
except (FileNotFoundError, KeyError):
|
2024-01-09 15:30:36 +01:00
|
|
|
return "NA" # Default: not available
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Base(Configuration):
|
|
|
|
|
"""
|
2024-02-24 12:26:57 +01:00
|
|
|
This is the base configuration every configuration (aka environment) should inherit from. It
|
2024-01-09 15:30:36 +01:00
|
|
|
is recommended to configure third-party applications by creating a configuration mixins in
|
|
|
|
|
./configurations and compose the Base configuration with those mixins.
|
|
|
|
|
|
|
|
|
|
It depends on an environment variable that SHOULD be defined:
|
|
|
|
|
|
|
|
|
|
* DJANGO_SECRET_KEY
|
|
|
|
|
|
|
|
|
|
You may also want to override default configuration by setting the following environment
|
|
|
|
|
variables:
|
|
|
|
|
|
2024-11-15 09:29:07 +01:00
|
|
|
* SENTRY_DSN
|
2024-01-09 15:30:36 +01:00
|
|
|
* DB_NAME
|
|
|
|
|
* DB_HOST
|
|
|
|
|
* DB_PASSWORD
|
|
|
|
|
* DB_USER
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
DEBUG = False
|
|
|
|
|
USE_SWAGGER = False
|
|
|
|
|
|
|
|
|
|
API_VERSION = "v1.0"
|
|
|
|
|
|
|
|
|
|
# Security
|
|
|
|
|
ALLOWED_HOSTS = values.ListValue([])
|
|
|
|
|
SECRET_KEY = values.Value(None)
|
2024-12-01 11:25:01 +01:00
|
|
|
SERVER_TO_SERVER_API_TOKENS = values.ListValue([])
|
2024-01-09 15:30:36 +01:00
|
|
|
|
|
|
|
|
# Application definition
|
2024-03-07 19:46:46 +01:00
|
|
|
ROOT_URLCONF = "impress.urls"
|
|
|
|
|
WSGI_APPLICATION = "impress.wsgi.application"
|
2024-01-09 15:30:36 +01:00
|
|
|
|
|
|
|
|
# Database
|
|
|
|
|
DATABASES = {
|
|
|
|
|
"default": {
|
|
|
|
|
"ENGINE": values.Value(
|
|
|
|
|
"django.db.backends.postgresql_psycopg2",
|
|
|
|
|
environ_name="DB_ENGINE",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
),
|
2024-02-09 19:32:12 +01:00
|
|
|
"NAME": values.Value(
|
2024-03-07 19:46:46 +01:00
|
|
|
"impress", environ_name="DB_NAME", environ_prefix=None
|
2024-02-09 19:32:12 +01:00
|
|
|
),
|
2024-01-09 15:30:36 +01:00
|
|
|
"USER": values.Value("dinum", environ_name="DB_USER", environ_prefix=None),
|
|
|
|
|
"PASSWORD": values.Value(
|
|
|
|
|
"pass", environ_name="DB_PASSWORD", environ_prefix=None
|
|
|
|
|
),
|
|
|
|
|
"HOST": values.Value(
|
|
|
|
|
"localhost", environ_name="DB_HOST", environ_prefix=None
|
|
|
|
|
),
|
|
|
|
|
"PORT": values.Value(5432, environ_name="DB_PORT", environ_prefix=None),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
|
|
|
|
|
|
|
|
|
|
# Static files (CSS, JavaScript, Images)
|
|
|
|
|
STATIC_URL = "/static/"
|
|
|
|
|
STATIC_ROOT = os.path.join(DATA_DIR, "static")
|
|
|
|
|
MEDIA_URL = "/media/"
|
|
|
|
|
MEDIA_ROOT = os.path.join(DATA_DIR, "media")
|
2024-11-15 11:31:09 +01:00
|
|
|
MEDIA_BASE_URL = values.Value(
|
|
|
|
|
None, environ_name="MEDIA_BASE_URL", environ_prefix=None
|
|
|
|
|
)
|
2024-01-09 15:30:36 +01:00
|
|
|
|
|
|
|
|
SITE_ID = 1
|
|
|
|
|
|
|
|
|
|
STORAGES = {
|
|
|
|
|
"default": {
|
2024-04-06 09:09:46 +02:00
|
|
|
"BACKEND": "storages.backends.s3.S3Storage",
|
2024-01-09 15:30:36 +01:00
|
|
|
},
|
|
|
|
|
"staticfiles": {
|
2024-04-06 09:09:46 +02:00
|
|
|
"BACKEND": values.Value(
|
|
|
|
|
"whitenoise.storage.CompressedManifestStaticFilesStorage",
|
|
|
|
|
environ_name="STORAGES_STATICFILES_BACKEND",
|
|
|
|
|
),
|
2024-01-09 15:30:36 +01:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-06 09:09:46 +02:00
|
|
|
# Media
|
|
|
|
|
AWS_S3_ENDPOINT_URL = values.Value(
|
|
|
|
|
environ_name="AWS_S3_ENDPOINT_URL", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
AWS_S3_ACCESS_KEY_ID = values.Value(
|
|
|
|
|
environ_name="AWS_S3_ACCESS_KEY_ID", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
AWS_S3_SECRET_ACCESS_KEY = values.Value(
|
|
|
|
|
environ_name="AWS_S3_SECRET_ACCESS_KEY", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
AWS_S3_REGION_NAME = values.Value(
|
|
|
|
|
environ_name="AWS_S3_REGION_NAME", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
AWS_STORAGE_BUCKET_NAME = values.Value(
|
|
|
|
|
"impress-media-storage",
|
|
|
|
|
environ_name="AWS_STORAGE_BUCKET_NAME",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
)
|
|
|
|
|
|
2024-08-19 22:35:48 +02:00
|
|
|
# Document images
|
|
|
|
|
DOCUMENT_IMAGE_MAX_SIZE = values.Value(
|
|
|
|
|
10 * (2**20), # 10MB
|
|
|
|
|
environ_name="DOCUMENT_IMAGE_MAX_SIZE",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
)
|
2024-10-07 20:10:42 +02:00
|
|
|
|
|
|
|
|
DOCUMENT_UNSAFE_MIME_TYPES = [
|
|
|
|
|
# Executable Files
|
|
|
|
|
"application/x-msdownload",
|
|
|
|
|
"application/x-bat",
|
|
|
|
|
"application/x-dosexec",
|
|
|
|
|
"application/x-sh",
|
|
|
|
|
"application/x-ms-dos-executable",
|
|
|
|
|
"application/x-msi",
|
|
|
|
|
"application/java-archive",
|
|
|
|
|
"application/octet-stream",
|
|
|
|
|
# Dynamic Web Pages
|
|
|
|
|
"application/x-httpd-php",
|
|
|
|
|
"application/x-asp",
|
|
|
|
|
"application/x-aspx",
|
|
|
|
|
"application/jsp",
|
|
|
|
|
"application/xhtml+xml",
|
|
|
|
|
"application/x-python-code",
|
|
|
|
|
"application/x-perl",
|
|
|
|
|
"text/html",
|
|
|
|
|
"text/javascript",
|
|
|
|
|
"text/x-php",
|
|
|
|
|
# System Files
|
|
|
|
|
"application/x-msdownload",
|
|
|
|
|
"application/x-sys",
|
|
|
|
|
"application/x-drv",
|
|
|
|
|
"application/cpl",
|
|
|
|
|
"application/x-apple-diskimage",
|
|
|
|
|
# Script Files
|
|
|
|
|
"application/javascript",
|
|
|
|
|
"application/x-vbscript",
|
|
|
|
|
"application/x-powershell",
|
|
|
|
|
"application/x-shellscript",
|
|
|
|
|
# Compressed/Archive Files
|
|
|
|
|
"application/zip",
|
|
|
|
|
"application/x-tar",
|
|
|
|
|
"application/gzip",
|
|
|
|
|
"application/x-bzip2",
|
|
|
|
|
"application/x-7z-compressed",
|
|
|
|
|
"application/x-rar",
|
|
|
|
|
"application/x-rar-compressed",
|
|
|
|
|
"application/x-compress",
|
|
|
|
|
"application/x-lzma",
|
|
|
|
|
# Macros in Documents
|
|
|
|
|
"application/vnd.ms-word",
|
|
|
|
|
"application/vnd.ms-excel",
|
|
|
|
|
"application/vnd.ms-powerpoint",
|
|
|
|
|
"application/vnd.ms-word.document.macroenabled.12",
|
|
|
|
|
"application/vnd.ms-excel.sheet.macroenabled.12",
|
|
|
|
|
"application/vnd.ms-powerpoint.presentation.macroenabled.12",
|
|
|
|
|
# Disk Images & Virtual Disk Files
|
|
|
|
|
"application/x-iso9660-image",
|
|
|
|
|
"application/x-vmdk",
|
|
|
|
|
"application/x-apple-diskimage",
|
|
|
|
|
"application/x-dmg",
|
|
|
|
|
# Other Dangerous MIME Types
|
|
|
|
|
"application/x-ms-application",
|
|
|
|
|
"application/x-msdownload",
|
|
|
|
|
"application/x-shockwave-flash",
|
|
|
|
|
"application/x-silverlight-app",
|
|
|
|
|
"application/x-java-vm",
|
|
|
|
|
"application/x-bittorrent",
|
|
|
|
|
"application/hta",
|
|
|
|
|
"application/x-csh",
|
|
|
|
|
"application/x-ksh",
|
|
|
|
|
"application/x-ms-regedit",
|
|
|
|
|
"application/x-msdownload",
|
|
|
|
|
"application/xml",
|
2024-08-19 22:35:48 +02:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# Document versions
|
|
|
|
|
DOCUMENT_VERSIONS_PAGE_SIZE = 50
|
2024-04-08 23:37:15 +02:00
|
|
|
|
2024-01-09 15:30:36 +01:00
|
|
|
# Internationalization
|
|
|
|
|
# https://docs.djangoproject.com/en/3.1/topics/i18n/
|
|
|
|
|
|
|
|
|
|
# Languages
|
|
|
|
|
LANGUAGE_CODE = values.Value("en-us")
|
2025-03-04 16:08:10 +01:00
|
|
|
# cookie & language is set from frontend
|
|
|
|
|
LANGUAGE_COOKIE_NAME = "docs_language"
|
|
|
|
|
LANGUAGE_COOKIE_PATH = "/"
|
2024-01-09 15:30:36 +01:00
|
|
|
|
|
|
|
|
DRF_NESTED_MULTIPART_PARSER = {
|
|
|
|
|
# output of parser is converted to querydict
|
|
|
|
|
# if is set to False, dict python is returned
|
|
|
|
|
"querydict": False,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Careful! Languages should be ordered by priority, as this tuple is used to get
|
|
|
|
|
# fallback/default languages throughout the app.
|
|
|
|
|
LANGUAGES = values.SingleNestedTupleValue(
|
|
|
|
|
(
|
2025-03-04 16:08:10 +01:00
|
|
|
("en-us", "English"),
|
|
|
|
|
("fr-fr", "Français"),
|
|
|
|
|
("de-de", "Deutsch"),
|
2024-01-09 15:30:36 +01:00
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
LOCALE_PATHS = (os.path.join(BASE_DIR, "locale"),)
|
|
|
|
|
|
|
|
|
|
TIME_ZONE = "UTC"
|
|
|
|
|
USE_I18N = True
|
|
|
|
|
USE_TZ = True
|
|
|
|
|
|
|
|
|
|
# Templates
|
|
|
|
|
TEMPLATES = [
|
|
|
|
|
{
|
|
|
|
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
|
|
|
|
"DIRS": [os.path.join(BASE_DIR, "templates")],
|
|
|
|
|
"OPTIONS": {
|
|
|
|
|
"context_processors": [
|
|
|
|
|
"django.contrib.auth.context_processors.auth",
|
|
|
|
|
"django.contrib.messages.context_processors.messages",
|
|
|
|
|
"django.template.context_processors.csrf",
|
|
|
|
|
"django.template.context_processors.debug",
|
|
|
|
|
"django.template.context_processors.i18n",
|
|
|
|
|
"django.template.context_processors.media",
|
|
|
|
|
"django.template.context_processors.request",
|
|
|
|
|
"django.template.context_processors.tz",
|
|
|
|
|
],
|
|
|
|
|
"loaders": [
|
|
|
|
|
"django.template.loaders.filesystem.Loader",
|
|
|
|
|
"django.template.loaders.app_directories.Loader",
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
MIDDLEWARE = [
|
|
|
|
|
"django.middleware.security.SecurityMiddleware",
|
|
|
|
|
"whitenoise.middleware.WhiteNoiseMiddleware",
|
|
|
|
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
|
|
|
|
"django.middleware.locale.LocaleMiddleware",
|
|
|
|
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
|
|
|
|
"corsheaders.middleware.CorsMiddleware",
|
|
|
|
|
"django.middleware.common.CommonMiddleware",
|
|
|
|
|
"django.middleware.csrf.CsrfViewMiddleware",
|
|
|
|
|
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
|
|
|
|
"django.contrib.messages.middleware.MessageMiddleware",
|
2024-04-12 13:55:51 +02:00
|
|
|
"dockerflow.django.middleware.DockerflowMiddleware",
|
2024-01-09 15:30:36 +01:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
AUTHENTICATION_BACKENDS = [
|
|
|
|
|
"django.contrib.auth.backends.ModelBackend",
|
2024-04-09 23:33:30 +02:00
|
|
|
"core.authentication.backends.OIDCAuthenticationBackend",
|
2024-01-09 15:30:36 +01:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# Django applications from the highest priority to the lowest
|
|
|
|
|
INSTALLED_APPS = [
|
2024-03-07 19:46:46 +01:00
|
|
|
# impress
|
2024-01-09 15:30:36 +01:00
|
|
|
"core",
|
|
|
|
|
"demo",
|
|
|
|
|
"drf_spectacular",
|
|
|
|
|
# Third party apps
|
|
|
|
|
"corsheaders",
|
2025-01-02 17:20:09 +01:00
|
|
|
"django_filters",
|
2024-01-09 15:30:36 +01:00
|
|
|
"dockerflow.django",
|
|
|
|
|
"rest_framework",
|
|
|
|
|
"parler",
|
2024-12-16 16:58:14 +01:00
|
|
|
"treebeard",
|
2024-01-09 15:30:36 +01:00
|
|
|
"easy_thumbnails",
|
|
|
|
|
# Django
|
|
|
|
|
"django.contrib.admin",
|
|
|
|
|
"django.contrib.auth",
|
|
|
|
|
"django.contrib.contenttypes",
|
|
|
|
|
"django.contrib.postgres",
|
|
|
|
|
"django.contrib.sessions",
|
|
|
|
|
"django.contrib.sites",
|
|
|
|
|
"django.contrib.messages",
|
|
|
|
|
"django.contrib.staticfiles",
|
2024-02-24 00:21:10 +01:00
|
|
|
# OIDC third party
|
|
|
|
|
"mozilla_django_oidc",
|
2024-01-09 15:30:36 +01:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# Cache
|
|
|
|
|
CACHES = {
|
|
|
|
|
"default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache"},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
REST_FRAMEWORK = {
|
|
|
|
|
"DEFAULT_AUTHENTICATION_CLASSES": (
|
2024-02-24 00:21:10 +01:00
|
|
|
"mozilla_django_oidc.contrib.drf.OIDCAuthentication",
|
|
|
|
|
"rest_framework.authentication.SessionAuthentication",
|
2024-01-09 15:30:36 +01:00
|
|
|
),
|
|
|
|
|
"DEFAULT_PARSER_CLASSES": [
|
|
|
|
|
"rest_framework.parsers.JSONParser",
|
|
|
|
|
"nested_multipart_parser.drf.DrfNestedParser",
|
|
|
|
|
],
|
|
|
|
|
"EXCEPTION_HANDLER": "core.api.exception_handler",
|
|
|
|
|
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
|
|
|
|
|
"PAGE_SIZE": 20,
|
|
|
|
|
"DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.URLPathVersioning",
|
|
|
|
|
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SPECTACULAR_SETTINGS = {
|
2024-03-07 19:46:46 +01:00
|
|
|
"TITLE": "Impress API",
|
|
|
|
|
"DESCRIPTION": "This is the impress API schema.",
|
2024-01-09 15:30:36 +01:00
|
|
|
"VERSION": "1.0.0",
|
|
|
|
|
"SERVE_INCLUDE_SCHEMA": False,
|
|
|
|
|
"ENABLE_DJANGO_DEPLOY_CHECK": values.BooleanValue(
|
|
|
|
|
default=False,
|
|
|
|
|
environ_name="SPECTACULAR_SETTINGS_ENABLE_DJANGO_DEPLOY_CHECK",
|
|
|
|
|
),
|
|
|
|
|
"COMPONENT_SPLIT_REQUEST": True,
|
|
|
|
|
# OTHER SETTINGS
|
|
|
|
|
"SWAGGER_UI_DIST": "SIDECAR", # shorthand to use the sidecar instead
|
|
|
|
|
"SWAGGER_UI_FAVICON_HREF": "SIDECAR",
|
|
|
|
|
"REDOC_DIST": "SIDECAR",
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-02 17:20:09 +01:00
|
|
|
TRASHBIN_CUTOFF_DAYS = values.Value(
|
|
|
|
|
30, environ_name="TRASHBIN_CUTOFF_DAYS", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
|
2024-01-09 15:30:36 +01:00
|
|
|
# Mail
|
|
|
|
|
EMAIL_BACKEND = values.Value("django.core.mail.backends.smtp.EmailBackend")
|
2024-12-13 17:48:08 +01:00
|
|
|
EMAIL_BRAND_NAME = values.Value(None)
|
2024-01-09 15:30:36 +01:00
|
|
|
EMAIL_HOST = values.Value(None)
|
|
|
|
|
EMAIL_HOST_USER = values.Value(None)
|
|
|
|
|
EMAIL_HOST_PASSWORD = values.Value(None)
|
2024-12-13 17:48:08 +01:00
|
|
|
EMAIL_LOGO_IMG = values.Value(None)
|
2024-01-09 15:30:36 +01:00
|
|
|
EMAIL_PORT = values.PositiveIntegerValue(None)
|
|
|
|
|
EMAIL_USE_TLS = values.BooleanValue(False)
|
2024-08-13 14:24:50 +02:00
|
|
|
EMAIL_USE_SSL = values.BooleanValue(False)
|
2024-01-09 15:30:36 +01:00
|
|
|
EMAIL_FROM = values.Value("from@example.com")
|
|
|
|
|
|
|
|
|
|
AUTH_USER_MODEL = "core.User"
|
2024-05-13 23:31:00 +02:00
|
|
|
INVITATION_VALIDITY_DURATION = 604800 # 7 days, in seconds
|
2024-01-09 15:30:36 +01:00
|
|
|
|
|
|
|
|
# CORS
|
|
|
|
|
CORS_ALLOW_CREDENTIALS = True
|
2024-01-10 15:07:05 +01:00
|
|
|
CORS_ALLOW_ALL_ORIGINS = values.BooleanValue(True)
|
2024-01-09 15:30:36 +01:00
|
|
|
CORS_ALLOWED_ORIGINS = values.ListValue([])
|
|
|
|
|
CORS_ALLOWED_ORIGIN_REGEXES = values.ListValue([])
|
|
|
|
|
|
|
|
|
|
# Sentry
|
2024-11-15 09:29:07 +01:00
|
|
|
SENTRY_DSN = values.Value(None, environ_name="SENTRY_DSN", environ_prefix=None)
|
2024-01-09 15:30:36 +01:00
|
|
|
|
2024-11-15 11:36:40 +01:00
|
|
|
# Collaboration
|
2024-11-28 16:35:48 +01:00
|
|
|
COLLABORATION_API_URL = values.Value(
|
|
|
|
|
None, environ_name="COLLABORATION_API_URL", environ_prefix=None
|
|
|
|
|
)
|
2024-11-18 08:05:54 +01:00
|
|
|
COLLABORATION_SERVER_SECRET = values.Value(
|
|
|
|
|
None, environ_name="COLLABORATION_SERVER_SECRET", environ_prefix=None
|
|
|
|
|
)
|
2024-12-03 15:07:21 +01:00
|
|
|
COLLABORATION_WS_URL = values.Value(
|
|
|
|
|
None, environ_name="COLLABORATION_WS_URL", environ_prefix=None
|
2024-11-15 11:36:40 +01:00
|
|
|
)
|
|
|
|
|
|
2024-11-15 11:43:10 +01:00
|
|
|
# Frontend
|
|
|
|
|
FRONTEND_THEME = values.Value(
|
|
|
|
|
None, environ_name="FRONTEND_THEME", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
|
2025-01-21 14:16:00 +01:00
|
|
|
# Posthog
|
|
|
|
|
POSTHOG_KEY = values.DictValue(
|
|
|
|
|
None, environ_name="POSTHOG_KEY", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
|
2024-11-25 14:35:02 +01:00
|
|
|
# Crisp
|
|
|
|
|
CRISP_WEBSITE_ID = values.Value(
|
|
|
|
|
None, environ_name="CRISP_WEBSITE_ID", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
|
2024-01-09 15:30:36 +01:00
|
|
|
# Easy thumbnails
|
|
|
|
|
THUMBNAIL_EXTENSION = "webp"
|
|
|
|
|
THUMBNAIL_TRANSPARENCY_EXTENSION = "webp"
|
2024-09-03 11:21:25 +02:00
|
|
|
THUMBNAIL_DEFAULT_STORAGE_ALIAS = "default"
|
2024-01-09 15:30:36 +01:00
|
|
|
THUMBNAIL_ALIASES = {}
|
|
|
|
|
|
|
|
|
|
# Celery
|
|
|
|
|
CELERY_BROKER_URL = values.Value("redis://redis:6379/0")
|
|
|
|
|
CELERY_BROKER_TRANSPORT_OPTIONS = values.DictValue({})
|
|
|
|
|
|
2024-02-24 00:21:10 +01:00
|
|
|
# Session
|
|
|
|
|
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
|
2024-04-12 13:54:44 +02:00
|
|
|
SESSION_CACHE_ALIAS = "default"
|
2024-02-24 00:21:10 +01:00
|
|
|
SESSION_COOKIE_AGE = 60 * 60 * 12
|
|
|
|
|
|
|
|
|
|
# OIDC - Authorization Code Flow
|
|
|
|
|
OIDC_CREATE_USER = values.BooleanValue(
|
|
|
|
|
default=True,
|
|
|
|
|
environ_name="OIDC_CREATE_USER",
|
|
|
|
|
)
|
|
|
|
|
OIDC_RP_SIGN_ALGO = values.Value(
|
|
|
|
|
"RS256", environ_name="OIDC_RP_SIGN_ALGO", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
OIDC_RP_CLIENT_ID = values.Value(
|
|
|
|
|
"impress", environ_name="OIDC_RP_CLIENT_ID", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
OIDC_RP_CLIENT_SECRET = values.Value(
|
|
|
|
|
None,
|
|
|
|
|
environ_name="OIDC_RP_CLIENT_SECRET",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
)
|
|
|
|
|
OIDC_OP_JWKS_ENDPOINT = values.Value(
|
|
|
|
|
environ_name="OIDC_OP_JWKS_ENDPOINT", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
OIDC_OP_AUTHORIZATION_ENDPOINT = values.Value(
|
|
|
|
|
environ_name="OIDC_OP_AUTHORIZATION_ENDPOINT", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
OIDC_OP_TOKEN_ENDPOINT = values.Value(
|
|
|
|
|
None, environ_name="OIDC_OP_TOKEN_ENDPOINT", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
OIDC_OP_USER_ENDPOINT = values.Value(
|
|
|
|
|
None, environ_name="OIDC_OP_USER_ENDPOINT", environ_prefix=None
|
|
|
|
|
)
|
✨(backend) support Agent Connect Logout flow
The default Logout view provided by Mozilla Django OIDC is not suitable
for the Agent Connect Logout flow.
Previously, when a user was logging-out, only its Django session was ended.
However, its session in the OIDC provider was still active.
Agent Connect implements a 'session/end' endpoint, that allows services to
end user session when they logout.
Agent Connect logout triggers cannot work with the default views implemented
by the dependency Mozilla Django OIDC. In their implementation, they decided
to end Django Session before redirecting to the OIDC provider.
The Django session needs to be retained during the logout process.
An OIDC state is saved to the request session, pass to Agent Connect Logout
endpoint, and verified when the backend receives the Logout callback from Agent
Connect. It seems to follow OIDC specifications.
If for any reason, the Logout flow cannot be initiated with Agent Connect,
(missing ID token in cache, unauthenticated user, etc), the user is redirected
to the final URL, without interacting with Agent Connect.
2024-04-10 00:17:57 +02:00
|
|
|
OIDC_OP_LOGOUT_ENDPOINT = values.Value(
|
|
|
|
|
None, environ_name="OIDC_OP_LOGOUT_ENDPOINT", environ_prefix=None
|
|
|
|
|
)
|
2024-02-24 00:21:10 +01:00
|
|
|
OIDC_AUTH_REQUEST_EXTRA_PARAMS = values.DictValue(
|
|
|
|
|
{}, environ_name="OIDC_AUTH_REQUEST_EXTRA_PARAMS", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
OIDC_RP_SCOPES = values.Value(
|
|
|
|
|
"openid email", environ_name="OIDC_RP_SCOPES", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
LOGIN_REDIRECT_URL = values.Value(
|
|
|
|
|
None, environ_name="LOGIN_REDIRECT_URL", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
LOGIN_REDIRECT_URL_FAILURE = values.Value(
|
|
|
|
|
None, environ_name="LOGIN_REDIRECT_URL_FAILURE", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
LOGOUT_REDIRECT_URL = values.Value(
|
|
|
|
|
None, environ_name="LOGOUT_REDIRECT_URL", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
OIDC_USE_NONCE = values.BooleanValue(
|
|
|
|
|
default=True, environ_name="OIDC_USE_NONCE", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
OIDC_REDIRECT_REQUIRE_HTTPS = values.BooleanValue(
|
|
|
|
|
default=False, environ_name="OIDC_REDIRECT_REQUIRE_HTTPS", environ_prefix=None
|
|
|
|
|
)
|
|
|
|
|
OIDC_REDIRECT_ALLOWED_HOSTS = values.ListValue(
|
|
|
|
|
default=[], environ_name="OIDC_REDIRECT_ALLOWED_HOSTS", environ_prefix=None
|
✨(backend) support Agent Connect Logout flow
The default Logout view provided by Mozilla Django OIDC is not suitable
for the Agent Connect Logout flow.
Previously, when a user was logging-out, only its Django session was ended.
However, its session in the OIDC provider was still active.
Agent Connect implements a 'session/end' endpoint, that allows services to
end user session when they logout.
Agent Connect logout triggers cannot work with the default views implemented
by the dependency Mozilla Django OIDC. In their implementation, they decided
to end Django Session before redirecting to the OIDC provider.
The Django session needs to be retained during the logout process.
An OIDC state is saved to the request session, pass to Agent Connect Logout
endpoint, and verified when the backend receives the Logout callback from Agent
Connect. It seems to follow OIDC specifications.
If for any reason, the Logout flow cannot be initiated with Agent Connect,
(missing ID token in cache, unauthenticated user, etc), the user is redirected
to the final URL, without interacting with Agent Connect.
2024-04-10 00:17:57 +02:00
|
|
|
)
|
|
|
|
|
OIDC_STORE_ID_TOKEN = values.BooleanValue(
|
|
|
|
|
default=True, environ_name="OIDC_STORE_ID_TOKEN", environ_prefix=None
|
|
|
|
|
)
|
2024-10-03 23:47:20 +02:00
|
|
|
OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION = values.BooleanValue(
|
|
|
|
|
default=True,
|
|
|
|
|
environ_name="OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
)
|
|
|
|
|
|
2025-01-10 09:50:48 +01:00
|
|
|
# WARNING: Enabling this setting allows multiple user accounts to share the same email
|
|
|
|
|
# address. This may cause security issues and is not recommended for production use when
|
|
|
|
|
# email is activated as fallback for identification (see previous setting).
|
|
|
|
|
OIDC_ALLOW_DUPLICATE_EMAILS = values.BooleanValue(
|
|
|
|
|
default=False,
|
|
|
|
|
environ_name="OIDC_ALLOW_DUPLICATE_EMAILS",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
)
|
|
|
|
|
|
2024-12-27 20:49:55 +01:00
|
|
|
USER_OIDC_ESSENTIAL_CLAIMS = values.ListValue(
|
|
|
|
|
default=[], environ_name="USER_OIDC_ESSENTIAL_CLAIMS", environ_prefix=None
|
2024-12-21 08:55:26 +01:00
|
|
|
)
|
2024-11-18 08:05:54 +01:00
|
|
|
USER_OIDC_FIELDS_TO_FULLNAME = values.ListValue(
|
|
|
|
|
default=["first_name", "last_name"],
|
|
|
|
|
environ_name="USER_OIDC_FIELDS_TO_FULLNAME",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
)
|
|
|
|
|
USER_OIDC_FIELD_TO_SHORTNAME = values.Value(
|
|
|
|
|
default="first_name",
|
|
|
|
|
environ_name="USER_OIDC_FIELD_TO_SHORTNAME",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
)
|
|
|
|
|
|
✨(backend) support Agent Connect Logout flow
The default Logout view provided by Mozilla Django OIDC is not suitable
for the Agent Connect Logout flow.
Previously, when a user was logging-out, only its Django session was ended.
However, its session in the OIDC provider was still active.
Agent Connect implements a 'session/end' endpoint, that allows services to
end user session when they logout.
Agent Connect logout triggers cannot work with the default views implemented
by the dependency Mozilla Django OIDC. In their implementation, they decided
to end Django Session before redirecting to the OIDC provider.
The Django session needs to be retained during the logout process.
An OIDC state is saved to the request session, pass to Agent Connect Logout
endpoint, and verified when the backend receives the Logout callback from Agent
Connect. It seems to follow OIDC specifications.
If for any reason, the Logout flow cannot be initiated with Agent Connect,
(missing ID token in cache, unauthenticated user, etc), the user is redirected
to the final URL, without interacting with Agent Connect.
2024-04-10 00:17:57 +02:00
|
|
|
ALLOW_LOGOUT_GET_METHOD = values.BooleanValue(
|
|
|
|
|
default=True, environ_name="ALLOW_LOGOUT_GET_METHOD", environ_prefix=None
|
2024-02-24 00:21:10 +01:00
|
|
|
)
|
2024-11-18 08:05:54 +01:00
|
|
|
|
|
|
|
|
# AI service
|
2024-09-20 22:42:46 +02:00
|
|
|
AI_API_KEY = values.Value(None, environ_name="AI_API_KEY", environ_prefix=None)
|
|
|
|
|
AI_BASE_URL = values.Value(None, environ_name="AI_BASE_URL", environ_prefix=None)
|
|
|
|
|
AI_MODEL = values.Value(None, environ_name="AI_MODEL", environ_prefix=None)
|
2025-02-11 08:45:21 +01:00
|
|
|
AI_ALLOW_REACH_FROM = values.Value(
|
|
|
|
|
choices=("public", "authenticated", "restricted"),
|
|
|
|
|
default="authenticated",
|
|
|
|
|
environ_name="AI_ALLOW_REACH_FROM",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
)
|
2024-09-20 22:42:46 +02:00
|
|
|
AI_DOCUMENT_RATE_THROTTLE_RATES = {
|
|
|
|
|
"minute": 5,
|
|
|
|
|
"hour": 100,
|
|
|
|
|
"day": 500,
|
|
|
|
|
}
|
|
|
|
|
AI_USER_RATE_THROTTLE_RATES = {
|
|
|
|
|
"minute": 3,
|
|
|
|
|
"hour": 50,
|
|
|
|
|
"day": 200,
|
|
|
|
|
}
|
2024-02-24 00:21:10 +01:00
|
|
|
|
2024-12-15 18:31:43 +01:00
|
|
|
# Y provider microservice
|
|
|
|
|
Y_PROVIDER_API_KEY = values.Value(
|
|
|
|
|
environ_name="Y_PROVIDER_API_KEY",
|
2024-12-01 11:25:01 +01:00
|
|
|
environ_prefix=None,
|
|
|
|
|
)
|
2024-12-15 18:31:43 +01:00
|
|
|
Y_PROVIDER_API_BASE_URL = values.Value(
|
|
|
|
|
environ_name="Y_PROVIDER_API_BASE_URL",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Conversion endpoint
|
|
|
|
|
CONVERSION_API_ENDPOINT = values.Value(
|
|
|
|
|
default="convert-markdown",
|
|
|
|
|
environ_name="CONVERSION_API_ENDPOINT",
|
2024-12-01 11:25:01 +01:00
|
|
|
environ_prefix=None,
|
|
|
|
|
)
|
|
|
|
|
CONVERSION_API_CONTENT_FIELD = values.Value(
|
|
|
|
|
default="content",
|
|
|
|
|
environ_name="CONVERSION_API_CONTENT_FIELD",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
)
|
|
|
|
|
CONVERSION_API_TIMEOUT = values.Value(
|
|
|
|
|
default=30,
|
|
|
|
|
environ_name="CONVERSION_API_TIMEOUT",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
)
|
2024-12-13 12:21:55 +01:00
|
|
|
CONVERSION_API_SECURE = values.Value(
|
|
|
|
|
default=False,
|
|
|
|
|
environ_name="CONVERSION_API_SECURE",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
)
|
2024-12-01 11:25:01 +01:00
|
|
|
|
2024-11-12 09:12:19 +01:00
|
|
|
# Logging
|
|
|
|
|
# We want to make it easy to log to console but by default we log production
|
|
|
|
|
# to Sentry and don't want to log to console.
|
|
|
|
|
LOGGING = {
|
|
|
|
|
"version": 1,
|
|
|
|
|
"disable_existing_loggers": False,
|
|
|
|
|
"handlers": {
|
|
|
|
|
"console": {
|
|
|
|
|
"class": "logging.StreamHandler",
|
|
|
|
|
"level": values.Value(
|
|
|
|
|
"ERROR",
|
|
|
|
|
environ_name="LOGGING_LEVEL_HANDLERS_CONSOLE",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
# Override root logger to send it to console
|
|
|
|
|
"root": {
|
|
|
|
|
"handlers": ["console"],
|
|
|
|
|
"level": values.Value(
|
|
|
|
|
"INFO", environ_name="LOGGING_LEVEL_LOGGERS_ROOT", environ_prefix=None
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
"loggers": {
|
|
|
|
|
"core": {
|
|
|
|
|
"handlers": ["console"],
|
|
|
|
|
"level": values.Value(
|
|
|
|
|
"INFO",
|
|
|
|
|
environ_name="LOGGING_LEVEL_LOGGERS_APP",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
),
|
|
|
|
|
"propagate": False,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-09 15:30:36 +01:00
|
|
|
# pylint: disable=invalid-name
|
|
|
|
|
@property
|
|
|
|
|
def ENVIRONMENT(self):
|
|
|
|
|
"""Environment in which the application is launched."""
|
|
|
|
|
return self.__class__.__name__.lower()
|
|
|
|
|
|
|
|
|
|
# pylint: disable=invalid-name
|
|
|
|
|
@property
|
|
|
|
|
def RELEASE(self):
|
|
|
|
|
"""
|
|
|
|
|
Return the release information.
|
|
|
|
|
|
|
|
|
|
Delegate to the module function to enable easier testing.
|
|
|
|
|
"""
|
|
|
|
|
return get_release()
|
|
|
|
|
|
|
|
|
|
# pylint: disable=invalid-name
|
|
|
|
|
@property
|
|
|
|
|
def PARLER_LANGUAGES(self):
|
|
|
|
|
"""
|
|
|
|
|
Return languages for Parler computed from the LANGUAGES and LANGUAGE_CODE settings.
|
|
|
|
|
"""
|
|
|
|
|
return {
|
|
|
|
|
self.SITE_ID: tuple({"code": code} for code, _name in self.LANGUAGES),
|
|
|
|
|
"default": {
|
|
|
|
|
"fallbacks": [self.LANGUAGE_CODE],
|
|
|
|
|
"hide_untranslated": False,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def post_setup(cls):
|
|
|
|
|
"""Post setup configuration.
|
|
|
|
|
This is the place where you can configure settings that require other
|
|
|
|
|
settings to be loaded.
|
|
|
|
|
"""
|
|
|
|
|
super().post_setup()
|
|
|
|
|
|
|
|
|
|
# The SENTRY_DSN setting should be available to activate sentry for an environment
|
|
|
|
|
if cls.SENTRY_DSN is not None:
|
|
|
|
|
sentry_sdk.init(
|
|
|
|
|
dsn=cls.SENTRY_DSN,
|
|
|
|
|
environment=cls.__name__.lower(),
|
|
|
|
|
release=get_release(),
|
|
|
|
|
integrations=[DjangoIntegration()],
|
|
|
|
|
)
|
2025-03-04 17:19:53 +01:00
|
|
|
sentry_sdk.set_tag("application", "backend")
|
|
|
|
|
|
|
|
|
|
# Ignore the logs added by the DockerflowMiddleware
|
|
|
|
|
ignore_logger("request.summary")
|
2024-01-09 15:30:36 +01:00
|
|
|
|
2025-01-10 09:50:48 +01:00
|
|
|
if (
|
|
|
|
|
cls.OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION
|
|
|
|
|
and cls.OIDC_ALLOW_DUPLICATE_EMAILS
|
|
|
|
|
):
|
|
|
|
|
raise ValueError(
|
|
|
|
|
"Both OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION and "
|
|
|
|
|
"OIDC_ALLOW_DUPLICATE_EMAILS cannot be set to True simultaneously. "
|
|
|
|
|
)
|
|
|
|
|
|
2024-01-09 15:30:36 +01:00
|
|
|
|
|
|
|
|
class Build(Base):
|
|
|
|
|
"""Settings used when the application is built.
|
|
|
|
|
|
|
|
|
|
This environment should not be used to run the application. Just to build it with non-blocking
|
|
|
|
|
settings.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
SECRET_KEY = values.Value("DummyKey")
|
|
|
|
|
STORAGES = {
|
|
|
|
|
"default": {
|
|
|
|
|
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
|
|
|
|
},
|
|
|
|
|
"staticfiles": {
|
|
|
|
|
"BACKEND": values.Value(
|
|
|
|
|
"whitenoise.storage.CompressedManifestStaticFilesStorage",
|
|
|
|
|
environ_name="STORAGES_STATICFILES_BACKEND",
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Development(Base):
|
|
|
|
|
"""
|
|
|
|
|
Development environment settings
|
|
|
|
|
|
|
|
|
|
We set DEBUG to True and configure the server to respond from all hosts.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
ALLOWED_HOSTS = ["*"]
|
|
|
|
|
CORS_ALLOW_ALL_ORIGINS = True
|
2024-04-10 12:28:10 +02:00
|
|
|
CSRF_TRUSTED_ORIGINS = ["http://localhost:8072", "http://localhost:3000"]
|
2024-01-09 15:30:36 +01:00
|
|
|
DEBUG = True
|
|
|
|
|
|
2024-03-07 19:46:46 +01:00
|
|
|
SESSION_COOKIE_NAME = "impress_sessionid"
|
2024-01-09 15:30:36 +01:00
|
|
|
|
|
|
|
|
USE_SWAGGER = True
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
# pylint: disable=invalid-name
|
|
|
|
|
self.INSTALLED_APPS += ["django_extensions", "drf_spectacular_sidecar"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Test(Base):
|
|
|
|
|
"""Test environment settings"""
|
|
|
|
|
|
|
|
|
|
PASSWORD_HASHERS = [
|
|
|
|
|
"django.contrib.auth.hashers.MD5PasswordHasher",
|
|
|
|
|
]
|
|
|
|
|
USE_SWAGGER = True
|
|
|
|
|
|
|
|
|
|
CELERY_TASK_ALWAYS_EAGER = values.BooleanValue(True)
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
# pylint: disable=invalid-name
|
|
|
|
|
self.INSTALLED_APPS += ["drf_spectacular_sidecar"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ContinuousIntegration(Test):
|
|
|
|
|
"""
|
|
|
|
|
Continuous Integration environment settings
|
|
|
|
|
|
|
|
|
|
nota bene: it should inherit from the Test environment.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Production(Base):
|
|
|
|
|
"""
|
|
|
|
|
Production environment settings
|
|
|
|
|
|
|
|
|
|
You must define the ALLOWED_HOSTS environment variable in Production
|
|
|
|
|
configuration (and derived configurations):
|
|
|
|
|
ALLOWED_HOSTS=["foo.com", "foo.fr"]
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
# Security
|
2024-11-22 11:55:30 +01:00
|
|
|
# Add allowed host from environment variables.
|
|
|
|
|
# The machine hostname is added by default,
|
|
|
|
|
# it makes the application pingable by a load balancer on the same machine by example
|
|
|
|
|
ALLOWED_HOSTS = [
|
|
|
|
|
*values.ListValue([], environ_name="ALLOWED_HOSTS"),
|
|
|
|
|
gethostbyname(gethostname()),
|
|
|
|
|
]
|
2024-01-09 15:30:36 +01:00
|
|
|
CSRF_TRUSTED_ORIGINS = values.ListValue([])
|
|
|
|
|
SECURE_BROWSER_XSS_FILTER = True
|
|
|
|
|
SECURE_CONTENT_TYPE_NOSNIFF = True
|
|
|
|
|
|
|
|
|
|
# SECURE_PROXY_SSL_HEADER allows to fix the scheme in Django's HttpRequest
|
|
|
|
|
# object when your application is behind a reverse proxy.
|
|
|
|
|
#
|
|
|
|
|
# Keep this SECURE_PROXY_SSL_HEADER configuration only if :
|
|
|
|
|
# - your Django app is behind a proxy.
|
|
|
|
|
# - your proxy strips the X-Forwarded-Proto header from all incoming requests
|
|
|
|
|
# - Your proxy sets the X-Forwarded-Proto header and sends it to Django
|
|
|
|
|
#
|
|
|
|
|
# In other cases, you should comment the following line to avoid security issues.
|
|
|
|
|
# SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
2024-04-12 14:27:50 +02:00
|
|
|
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
2024-09-30 09:29:35 +02:00
|
|
|
SECURE_HSTS_SECONDS = 60
|
|
|
|
|
SECURE_HSTS_PRELOAD = True
|
|
|
|
|
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
|
|
|
|
|
SECURE_SSL_REDIRECT = True
|
|
|
|
|
SECURE_REDIRECT_EXEMPT = [
|
|
|
|
|
"^__lbheartbeat__",
|
|
|
|
|
"^__heartbeat__",
|
|
|
|
|
]
|
2024-01-09 15:30:36 +01:00
|
|
|
|
|
|
|
|
# Modern browsers require to have the `secure` attribute on cookies with `Samesite=none`
|
|
|
|
|
CSRF_COOKIE_SECURE = True
|
|
|
|
|
SESSION_COOKIE_SECURE = True
|
|
|
|
|
|
|
|
|
|
# Privacy
|
|
|
|
|
SECURE_REFERRER_POLICY = "same-origin"
|
|
|
|
|
|
2024-04-12 13:54:44 +02:00
|
|
|
CACHES = {
|
|
|
|
|
"default": {
|
|
|
|
|
"BACKEND": "django_redis.cache.RedisCache",
|
|
|
|
|
"LOCATION": values.Value(
|
|
|
|
|
"redis://redis:6379/1",
|
|
|
|
|
environ_name="REDIS_URL",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
),
|
2025-01-02 17:20:09 +01:00
|
|
|
"TIMEOUT": values.IntegerValue(
|
|
|
|
|
30, # timeout in seconds
|
|
|
|
|
environ_name="CACHES_DEFAULT_TIMEOUT",
|
|
|
|
|
environ_prefix=None,
|
|
|
|
|
),
|
2024-04-12 13:54:44 +02:00
|
|
|
"OPTIONS": {
|
|
|
|
|
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-09 15:30:36 +01:00
|
|
|
|
|
|
|
|
class Feature(Production):
|
|
|
|
|
"""
|
|
|
|
|
Feature environment settings
|
|
|
|
|
|
|
|
|
|
nota bene: it should inherit from the Production environment.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Staging(Production):
|
|
|
|
|
"""
|
|
|
|
|
Staging environment settings
|
|
|
|
|
|
|
|
|
|
nota bene: it should inherit from the Production environment.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PreProduction(Production):
|
|
|
|
|
"""
|
|
|
|
|
Pre-production environment settings
|
|
|
|
|
|
|
|
|
|
nota bene: it should inherit from the Production environment.
|
|
|
|
|
"""
|
2024-02-24 12:44:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class Demo(Production):
|
|
|
|
|
"""
|
|
|
|
|
Demonstration environment settings
|
|
|
|
|
|
|
|
|
|
nota bene: it should inherit from the Production environment.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
STORAGES = {
|
|
|
|
|
"default": {
|
|
|
|
|
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
|
|
|
|
},
|
|
|
|
|
"staticfiles": {
|
|
|
|
|
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
|
|
|
|
|
},
|
|
|
|
|
}
|