vbv/server/config/settings/base.py

721 lines
27 KiB
Python

"""
Base settings to build other settings files upon.
"""
import logging
import os
from pathlib import Path
import structlog
from environs import Env
from vbv_lernwelt.core.utils import structlog_add_app_info
SERVER_ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent.parent
APPS_DIR = SERVER_ROOT_DIR / "vbv_lernwelt"
env = Env()
env.read_env()
# set to "development" for local development
APP_ENVIRONMENT = env("IT_APP_ENVIRONMENT")
# GENERAL
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#debug
DEBUG = env.bool("IT_DJANGO_DEBUG", True if APP_ENVIRONMENT == "development" else False)
# Local time zone. Choices are
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# though not all of them may be available with every OS.
# In Windows, this must be set to your system time zone.
TIME_ZONE = "Europe/Zurich"
# https://docs.djangoproject.com/en/dev/ref/settings/#language-code
LANGUAGE_CODE = "de-CH"
# https://docs.djangoproject.com/en/dev/ref/settings/#site-id
SITE_ID = 1
# https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n
USE_I18N = True
# https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n
USE_L10N = True
# https://docs.djangoproject.com/en/dev/ref/settings/#use-tz
USE_TZ = True
# https://docs.djangoproject.com/en/dev/ref/settings/#locale-paths
LOCALE_PATHS = [str(SERVER_ROOT_DIR / "locale")]
# DATABASES
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#databases
DATABASES = {
"default": env.dj_db_url(
"DATABASE_URL",
default="postgres://postgres@localhost:5432/vbv_lernwelt",
)
}
DATABASES["default"]["ATOMIC_REQUESTS"] = True # noqa F405
DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=60) # noqa F405
# https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-DEFAULT_AUTO_FIELD
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
# URLS
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf
ROOT_URLCONF = "config.urls"
# https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application
WSGI_APPLICATION = "config.wsgi.application"
# APPS
# ------------------------------------------------------------------------------
DJANGO_APPS = [
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.sites",
"django.contrib.messages",
"django.contrib.staticfiles",
# "django.contrib.humanize", # Handy template tags
"django.contrib.admin",
"django.forms",
]
THIRD_PARTY_APPS = [
"rest_framework",
"rest_framework.authtoken",
"corsheaders",
"drf_spectacular",
"wagtail.contrib.forms",
"wagtail.contrib.redirects",
"wagtail.contrib.styleguide",
"wagtail.embeds",
"wagtail.sites",
"wagtail.users",
"wagtail.snippets",
"wagtail.documents",
"wagtail.images",
"wagtail.search",
"wagtail.admin",
"wagtail",
# 'wagtail.locales',
"wagtail_localize",
"wagtail_localize.locales",
"wagtail.api.v2",
"modelcluster",
"taggit",
"storages",
"grapple",
"graphene_django",
]
LOCAL_APPS = [
"vbv_lernwelt.core",
"vbv_lernwelt.sso",
"vbv_lernwelt.course",
"vbv_lernwelt.learnpath",
"vbv_lernwelt.competence",
"vbv_lernwelt.media_library",
"vbv_lernwelt.feedback",
"vbv_lernwelt.files",
]
# https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
# MIGRATIONS
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#migration-modules
MIGRATION_MODULES = {"sites": "vbv_lernwelt.contrib.sites.migrations"}
# AUTHENTICATION
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#authentication-backends
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
]
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-user-model
AUTH_USER_MODEL = "core.User"
# https://docs.djangoproject.com/en/dev/ref/settings/#login-redirect-url
# https://docs.djangoproject.com/en/dev/ref/settings/#login-url
# FIXME make configurable!?
# LOGIN_URL = "/sso/login/"
LOGIN_URL = "/login"
LOGIN_REDIRECT_URL = "/"
ALLOW_LOCAL_LOGIN = env.bool("IT_ALLOW_LOCAL_LOGIN", default=DEBUG)
# PASSWORDS
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#password-hashers
PASSWORD_HASHERS = [
# https://docs.djangoproject.com/en/dev/topics/auth/passwords/#using-argon2-with-django
"django.contrib.auth.hashers.Argon2PasswordHasher",
"django.contrib.auth.hashers.PBKDF2PasswordHasher",
"django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
"django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
]
# https://docs.djangoproject.com/en/dev/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"},
]
# MIDDLEWARE
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#middleware
MIDDLEWARE = [
"vbv_lernwelt.core.middleware.security.GetIpBehindReverseProxyMiddleWare",
"django.middleware.security.SecurityMiddleware",
"corsheaders.middleware.CorsMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.locale.LocaleMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.common.BrokenLinkEmailsMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"csp.middleware.CSPMiddleware",
"vbv_lernwelt.core.middleware.auth.AuthenticationRequiredMiddleware",
"vbv_lernwelt.core.middleware.security.SecurityRequestResponseLoggingMiddleware",
"wagtail.contrib.redirects.middleware.RedirectMiddleware",
"vbv_lernwelt.core.middleware.auth.UserLoggedInCookieMiddleWare",
]
# STATIC
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#static-root
STATIC_ROOT = str(SERVER_ROOT_DIR / "staticfiles")
# https://docs.djangoproject.com/en/dev/ref/settings/#static-url
STATIC_URL = "/static/"
# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
STATICFILES_DIRS = [str(APPS_DIR / "static")]
# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
STATICFILES_FINDERS = [
"django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
]
USE_AWS = env("USE_AWS", False)
AWS_STORAGE_BUCKET_NAME = env("AWS_STORAGE_BUCKET_NAME", "")
AWS_ACCESS_KEY_ID = env("AWS_ACCESS_KEY_ID", "")
AWS_SECRET_ACCESS_KEY = env("AWS_SECRET_ACCESS_KEY", "")
AWS_S3_CUSTOM_DOMAIN = "%s.s3.amazonaws.com" % AWS_STORAGE_BUCKET_NAME
# MEDIA
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#media-root
MEDIA_ROOT = str(APPS_DIR / "media")
# https://docs.djangoproject.com/en/dev/ref/settings/#media-url
if USE_AWS:
# https://wagtail.org/blog/amazon-s3-for-media-files/
MEDIA_URL = "https://%s/" % AWS_S3_CUSTOM_DOMAIN
DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
else:
MEDIA_URL = "/server/media/"
IT_SERVE_VUE = env.bool("IT_SERVE_VUE", DEBUG)
IT_SERVE_VUE_URL = env("IT_SERVE_VUE_URL", "http://localhost:5173")
# WAGTAIL
# ------------------------------------------------------------------------------
WAGTAIL_SITE_NAME = "VBV Lernwelt"
WAGTAIL_I18N_ENABLED = True
LANGUAGES = [
("en-US", "English (American)"),
("fr-CH", "Swiss French"),
("de-CH", "Swiss German"),
("it-CH", "Swiss Italian"),
]
WAGTAILDOCS_DOCUMENT_MODEL = "media_library.LibraryDocument"
WAGTAIL_CONTENT_LANGUAGES = [
("fr-CH", "Swiss French"),
("de-CH", "Swiss German"),
("it-CH", "Swiss Italian"),
]
WAGTAILSEARCH_BACKENDS = {
"default": {
"BACKEND": "wagtail.search.backends.database",
}
}
# TEMPLATES
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#templates
TEMPLATES = [
{
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND
"BACKEND": "django.template.backends.django.DjangoTemplates",
# https://docs.djangoproject.com/en/dev/ref/settings/#dirs
"DIRS": [str(APPS_DIR / "templates")],
# https://docs.djangoproject.com/en/dev/ref/settings/#app-dirs
"APP_DIRS": True,
"OPTIONS": {
# https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.template.context_processors.i18n",
"django.template.context_processors.media",
"django.template.context_processors.static",
"django.template.context_processors.tz",
"django.contrib.messages.context_processors.messages",
],
},
}
]
# https://docs.djangoproject.com/en/dev/ref/settings/#form-renderer
FORM_RENDERER = "django.forms.renderers.TemplatesSetting"
# FIXTURES
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#fixture-dirs
FIXTURE_DIRS = (str(APPS_DIR / "fixtures"),)
# SECURITY
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-httponly
SESSION_COOKIE_HTTPONLY = True
# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-httponly
CSRF_COOKIE_HTTPONLY = False
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-browser-xss-filter
SECURE_BROWSER_XSS_FILTER = True
# https://docs.djangoproject.com/en/dev/ref/settings/#x-frame-options
X_FRAME_OPTIONS = "DENY"
# EMAIL
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
# FIXME how to send emails?
EMAIL_BACKEND = env(
"DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.console.EmailBackend"
)
# https://docs.djangoproject.com/en/dev/ref/settings/#email-timeout
EMAIL_TIMEOUT = 5
# ADMIN
# ------------------------------------------------------------------------------
# Django Admin URL.
ADMIN_URL = "server/admin/"
# https://docs.djangoproject.com/en/dev/ref/settings/#admins
ADMINS = [("""Daniel Egger""", "info@iterativ.ch")]
# https://docs.djangoproject.com/en/dev/ref/settings/#managers
MANAGERS = ADMINS
# LOGGING
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#logging
# See https://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.
logging_conf_default = "IT_DJANGO_LOGGING_CONF_JSON_FILE"
if DEBUG:
logging_conf_default = "IT_DJANGO_LOGGING_CONF_CONSOLE_COLOR"
IT_DJANGO_LOGGING_CONF = env("IT_DJANGO_LOGGING_CONF", default=logging_conf_default)
if IT_DJANGO_LOGGING_CONF == "IT_DJANGO_LOGGING_CONF_CONSOLE_COLOR":
timestamper = structlog.processors.TimeStamper(fmt="%Y-%m-%d %H:%M:%S")
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"colored": {
"()": structlog.stdlib.ProcessorFormatter,
"processor": structlog.dev.ConsoleRenderer(colors=True),
"foreign_pre_chain": [
structlog.stdlib.add_log_level,
timestamper,
],
},
},
"handlers": {
"default": {
"class": "logging.StreamHandler",
"formatter": "colored",
},
},
"loggers": {
"": {
"handlers": ["default"],
"level": "INFO",
"propagate": True,
},
"vbv_lernwelt": {
"handlers": ["default"],
"level": "DEBUG",
"propagate": False,
},
},
}
structlog.configure(
processors=[
structlog.threadlocal.merge_threadlocal,
structlog.stdlib.add_log_level,
structlog.stdlib.PositionalArgumentsFormatter(),
timestamper,
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
],
context_class=dict,
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=structlog.stdlib.BoundLogger,
cache_logger_on_first_use=True,
)
else:
shared_processors = [
structlog.threadlocal.merge_threadlocal,
structlog.stdlib.add_log_level,
structlog.stdlib.add_logger_name,
structlog_add_app_info,
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.CallsiteParameterAdder(),
]
LOGGING = {
"version": 1,
"disable_existing_loggers": True,
"formatters": {
"json": {
"()": structlog.stdlib.ProcessorFormatter,
"processors": [
structlog.stdlib.ProcessorFormatter.remove_processors_meta,
structlog.processors.JSONRenderer(),
],
"foreign_pre_chain": shared_processors,
},
},
"handlers": {
"file": {
"class": "concurrent_log_handler.ConcurrentRotatingFileHandler",
"filename": f"{SERVER_ROOT_DIR}/log/myservice.log",
"maxBytes": 1024 * 1024 * 100,
"backupCount": 50,
"formatter": "json",
},
"console": {
"level": "DEBUG",
"class": "logging.StreamHandler",
"formatter": "json",
},
},
"loggers": {
"": {
"handlers": ["console", "file"],
"level": "INFO",
},
"django": {
"handlers": ["console", "file"],
"level": "WARNING",
"propagate": False,
},
"vbv_lernwelt": {
"handlers": ["console", "file"],
"level": "DEBUG",
"propagate": False,
},
"sentry_sdk": {
"level": "ERROR",
"handlers": ["console", "file"],
"propagate": False,
},
},
}
structlog.configure(
processors=shared_processors
+ [
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
],
context_class=dict,
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=structlog.stdlib.BoundLogger,
cache_logger_on_first_use=True,
)
# django-rest-framework
# -------------------------------------------------------------------------------
# django-rest-framework - https://www.django-rest-framework.org/api-guide/settings/
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.SessionAuthentication",
"rest_framework.authentication.TokenAuthentication",
),
"DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
"TEST_REQUEST_DEFAULT_FORMAT": "json",
"DEFAULT_THROTTLE_CLASSES": [
"rest_framework.throttling.AnonRateThrottle",
"vbv_lernwelt.core.utils.HourUserRateThrottle",
"vbv_lernwelt.core.utils.DayUserRateThrottle",
],
"DEFAULT_THROTTLE_RATES": {
"anon": "200/day",
"hour-throttle": "400/hour",
"day-throttle": "2000/day",
},
}
# django-cors-headers - https://github.com/adamchainz/django-cors-headers#setup
CORS_URLS_REGEX = r"^/api/.*$"
# django-csp
CSP_DEFAULT_SRC = [
"'self'",
"'unsafe-inline'",
"'unsafe-eval'",
"ws://localhost:5173",
"ws://127.0.0.1:5173",
"localhost:8000",
"localhost:8001",
"blob:",
"data:",
"http://*",
]
CSP_FRAME_ANCESTORS = ("'self'",)
SPECTACULAR_SETTINGS = {
"TITLE": "VBV Lernwelt API",
"DESCRIPTION": "Documentation of API endpoints of VBV Lernwelt",
"VERSION": "1.0.0",
"SERVE_PERMISSIONS": ["rest_framework.permissions.IsAdminUser"],
"SERVERS": [
{"url": "https://127.0.0.1:8000", "description": "Local Development server"},
{"url": "https://vbv-lernwelt.iterativ.ch", "description": "Production server"},
],
}
# Your stuff...
# ------------------------------------------------------------------------------
if DEBUG:
SECRET_KEY = env(
"IT_DJANGO_SECRET_KEY",
default="J9FiYN31FuY7lHrmx9Mpai3GGpTVCxakEclOfCLretDe7bTf2DtTsgazJ0aIMtbq",
)
else:
SECRET_KEY = env("IT_DJANGO_SECRET_KEY")
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
ALLOWED_HOSTS = env.list(
"IT_DJANGO_ALLOWED_HOSTS", default=["localhost", "0.0.0.0", "127.0.0.1"]
)
# CACHES
CACHES = {
"default": {
"BACKEND": env(
"IT_DJANGO_CACHE_BACKEND",
default="django.core.cache.backends.db.DatabaseCache",
),
"LOCATION": env("IT_DJANGO_CACHE_LOCATION", default="django_cache_table"),
},
}
if "django_redis.cache.RedisCache" in env("IT_DJANGO_CACHE_BACKEND", default=""):
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": env("IT_DJANGO_CACHE_LOCATION"),
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"IGNORE_EXCEPTIONS": True,
},
},
}
CACHES["api_page_cache"] = {
"BACKEND": "django.core.cache.backends.db.DatabaseCache",
"LOCATION": "django_cache_table_api_page",
}
# OAuth/OpenId Connect
IT_OAUTH_TENANT_ID = env.str("IT_OAUTH_TENANT_ID", default=None)
if IT_OAUTH_TENANT_ID:
IT_OAUTH_AUTHORIZE_PARAMS = {"tenant_id": IT_OAUTH_TENANT_ID}
else:
IT_OAUTH_AUTHORIZE_PARAMS = {}
OAUTH = {
"client_name": env("IT_OAUTH_CLIENT_NAME", default="lernetz"),
"client_id": env("IT_OAUTH_CLIENT_ID", default="iterativ"),
"client_secret": env("IT_OAUTH_CLIENT_SECRET", default=""),
"authorize_params": IT_OAUTH_AUTHORIZE_PARAMS,
"access_token_params": IT_OAUTH_AUTHORIZE_PARAMS,
"api_base_url": env(
"IT_OAUTH_API_BASE_URL",
default="https://sso.test.b.lernetz.host/auth/realms/vbv/protocol/openid-connect/",
),
"local_redirect_uri": env(
"IT_OAUTH_LOCAL_DIRECT_URI", default="http://localhost:8000/sso/callback/"
),
"server_metadata_url": env(
"IT_OAUTH_SERVER_METADATA_URL",
default="https://sso.test.b.lernetz.host/auth/realms/vbv/.well-known/openid-configuration",
),
"client_kwargs": {
"scope": env("IT_OAUTH_SCOPE", default=""),
"token_endpoint_auth_method": "client_secret_post",
"token_placement": "body",
},
}
GRAPHENE = {"SCHEMA": "grapple.schema.schema", "SCHEMA_OUTPUT": "schema.graphql"}
GRAPPLE = {
"EXPOSE_GRAPHIQL": DEBUG,
"APPS": ["core", "course", "learnpath", "competence", "media_library"],
}
if APP_ENVIRONMENT == "development":
# http://whitenoise.evans.io/en/latest/django.html#using-whitenoise-in-development
INSTALLED_APPS = ["whitenoise.runserver_nostatic"] + INSTALLED_APPS # noqa F405
# django-debug-toolbar
# ------------------------------------------------------------------------------
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#prerequisites
# INSTALLED_APPS += ["debug_toolbar"] # noqa F405
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#middleware
# MIDDLEWARE += ["debug_toolbar.middleware.DebugToolbarMiddleware"] # noqa F405
# https://django-debug-toolbar.readthedocs.io/en/latest/configuration.html#debug-toolbar-config
# DEBUG_TOOLBAR_CONFIG = {
# "DISABLE_PANELS": ["debug_toolbar.panels.redirects.RedirectsPanel"],
# "SHOW_TEMPLATE_CONTEXT": True,
# }
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#internal-ips
INTERNAL_IPS = ["127.0.0.1", "10.0.2.2"]
if env.bool("IT_DJANGO_LOCAL_DOCKER", False):
import socket
hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
INTERNAL_IPS += [".".join(ip.split(".")[:-1] + ["1"]) for ip in ips]
try:
_, _, ips = socket.gethostbyname_ex("node")
INTERNAL_IPS.extend(ips)
except socket.gaierror:
# The node container isn't started (yet?)
pass
# django-extensions
# ------------------------------------------------------------------------------
# https://django-extensions.readthedocs.io/en/latest/installation_instructions.html#configuration
INSTALLED_APPS += ["django_extensions", "django_watchfiles"] # noqa F405
# S3 BUCKET CONFIGURATION
FILE_UPLOAD_STORAGE = env("FILE_UPLOAD_STORAGE", default="local") # local | s3
if FILE_UPLOAD_STORAGE == "local":
FILE_MAX_SIZE = env.int("FILE_MAX_SIZE", default=5242880)
if FILE_UPLOAD_STORAGE == "s3":
# Using django-storages
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html
DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
AWS_S3_ACCESS_KEY_ID = env("AWS_S3_ACCESS_KEY_ID")
AWS_S3_SECRET_ACCESS_KEY = env("AWS_S3_SECRET_ACCESS_KEY")
AWS_STORAGE_BUCKET_NAME = env("AWS_STORAGE_BUCKET_NAME")
AWS_S3_REGION_NAME = env("AWS_S3_REGION_NAME")
AWS_S3_SIGNATURE_VERSION = env("AWS_S3_SIGNATURE_VERSION", default="s3v4")
FILE_MAX_SIZE = env.int("FILE_MAX_SIZE", default=5242880) # 5MB
# https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#canned-acl
AWS_DEFAULT_ACL = env("AWS_DEFAULT_ACL", default="private")
AWS_PRESIGNED_EXPIRY = env.int("AWS_PRESIGNED_EXPIRY", default=60) # seconds
if APP_ENVIRONMENT in ["production", "caprover"] or APP_ENVIRONMENT.startswith(
"caprover"
):
# SECURITY
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-ssl-redirect
SECURE_SSL_REDIRECT = env.bool("IT_DJANGO_SECURE_SSL_REDIRECT", default=True)
# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-secure
SESSION_COOKIE_SECURE = True
# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-secure
CSRF_COOKIE_SECURE = True
# https://docs.djangoproject.com/en/dev/topics/security/#ssl-https
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-seconds
# TODO: set this to 60 seconds first and then to 518400 once you prove the former works
SECURE_HSTS_SECONDS = 60
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-include-subdomains
SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool(
"DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True
)
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-preload
SECURE_HSTS_PRELOAD = env.bool("DJANGO_SECURE_HSTS_PRELOAD", default=True)
# https://docs.djangoproject.com/en/dev/ref/middleware/#x-content-type-options-nosniff
SECURE_CONTENT_TYPE_NOSNIFF = env.bool(
"DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True
)
# STATIC
# ------------------------
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
# MEDIA
# ------------------------------------------------------------------------------
# EMAIL
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#default-from-email
DEFAULT_FROM_EMAIL = env(
"DJANGO_DEFAULT_FROM_EMAIL",
default="VBV Lernwelt <info@iterativ.ch>",
)
# https://docs.djangoproject.com/en/dev/ref/settings/#server-email
SERVER_EMAIL = env("IT_DJANGO_SERVER_EMAIL", default=DEFAULT_FROM_EMAIL)
# https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix
EMAIL_SUBJECT_PREFIX = env(
"DJANGO_EMAIL_SUBJECT_PREFIX",
default="[VBV Lernwelt]",
)
# ADMIN
# ------------------------------------------------------------------------------
# Django Admin URL regex.
ADMIN_URL = env("IT_DJANGO_ADMIN_URL", "admin/")
# Anymail
# ------------------------------------------------------------------------------
# https://anymail.readthedocs.io/en/stable/installation/#installing-anymail
# INSTALLED_APPS += ["anymail"] # noqa F405
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
# https://anymail.readthedocs.io/en/stable/installation/#anymail-settings-reference
# https://anymail.readthedocs.io/en/stable/esps
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
ANYMAIL = {}
# Sentry
# ------------------------------------------------------------------------------
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.logging import LoggingIntegration
from sentry_sdk.integrations.redis import RedisIntegration
SENTRY_DSN = env("IT_SENTRY_DSN")
SENTRY_LOG_LEVEL = env.int("DJANGO_SENTRY_LOG_LEVEL", logging.INFO)
sentry_logging = LoggingIntegration(
level=SENTRY_LOG_LEVEL, # Capture info and above as breadcrumbs
event_level=logging.ERROR, # Send errors as events
)
integrations = [sentry_logging, DjangoIntegration(), RedisIntegration()]
# pylint: disable=abstract-class-instantiated
sentry_sdk.init(
dsn=SENTRY_DSN,
integrations=integrations,
environment=env("SENTRY_ENVIRONMENT", default="production"),
traces_sample_rate=env.float("SENTRY_TRACES_SAMPLE_RATE", default=0.0),
)
# Your stuff...
# ------------------------------------------------------------------------------