Fixes: 1) Ensure `install.ps1` handles non-zero exit codes gracefully; 2) Remove redundant `vm.overcommit_memory` Docker sysctl setting; 3) Add explicit exit command to `starter.ps1` for clean terminations; Extra: Minor formatting and consistency improvements across ENTRYPOINT scripts;
348 lines
9.3 KiB
Python
348 lines
9.3 KiB
Python
import logging
|
|
from os import getenv, name
|
|
from pathlib import Path
|
|
|
|
EVIBES_VERSION = "2.9.1"
|
|
|
|
BASE_DIR = Path(__file__).resolve().parent.parent.parent
|
|
|
|
SECRET_KEY = getenv("SECRET_KEY", "SUPER_SECRET_KEY")
|
|
DEBUG = bool(int(getenv("DEBUG", "1")))
|
|
|
|
ALLOWED_HOSTS: set = {
|
|
"app",
|
|
"worker",
|
|
"beat",
|
|
"localhost",
|
|
"api.localhost",
|
|
"b2b.localhost",
|
|
"127.0.0.1",
|
|
"api.127.0.0.1",
|
|
"b2b.127.0.0.1",
|
|
}
|
|
|
|
if DEBUG:
|
|
ALLOWED_HOSTS.add("*")
|
|
else:
|
|
for entry in getenv("ALLOWED_HOSTS", "").split(" "):
|
|
ALLOWED_HOSTS.add(entry)
|
|
|
|
ALLOWED_HOSTS: tuple = tuple(ALLOWED_HOSTS)
|
|
|
|
CSRF_TRUSTED_ORIGINS: set = {
|
|
"http://127.0.0.1",
|
|
"http://api.localhost",
|
|
"http://b2b.localhost",
|
|
}
|
|
|
|
for entry in getenv("CSRF_TRUSTED_ORIGINS", "").split(" "):
|
|
CSRF_TRUSTED_ORIGINS.add(entry)
|
|
|
|
CSRF_TRUSTED_ORIGINS: tuple = tuple(CSRF_TRUSTED_ORIGINS)
|
|
|
|
if DEBUG:
|
|
CORS_ALLOW_ALL_ORIGINS = True
|
|
else:
|
|
CORS_ALLOWED_ORIGINS: set = {
|
|
"http://127.0.0.1",
|
|
"http://api.localhost",
|
|
"http://b2b.localhost",
|
|
}
|
|
for entry in getenv("CORS_ALLOWED_ORIGINS", "").split(" "):
|
|
CORS_ALLOWED_ORIGINS.add(entry)
|
|
|
|
CORS_ALLOWED_ORIGINS: tuple = tuple(CORS_ALLOWED_ORIGINS)
|
|
|
|
CORS_ALLOW_METHODS = (
|
|
"DELETE",
|
|
"GET",
|
|
"OPTIONS",
|
|
"PATCH",
|
|
"POST",
|
|
"PUT",
|
|
)
|
|
|
|
CORS_ALLOW_HEADERS = (
|
|
"accept",
|
|
"accept-encoding",
|
|
"accept-language",
|
|
"content-type",
|
|
"connection",
|
|
"user-agent",
|
|
"authorization",
|
|
"host",
|
|
"x-csrftoken",
|
|
"x-requested-with",
|
|
"x-evibes-auth",
|
|
"baggage",
|
|
"sentry-trace",
|
|
"dnt",
|
|
"sec-fetch-dest",
|
|
"sec-fetch-mode",
|
|
"sec-fetch-site",
|
|
"sec-gpc",
|
|
"origin",
|
|
"referer",
|
|
)
|
|
|
|
USE_X_FORWARDED_HOST = True
|
|
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") if not DEBUG else None
|
|
X_FRAME_OPTIONS = "SAMEORIGIN"
|
|
|
|
UNSAFE_CACHE_KEYS: list[str] = []
|
|
|
|
SITE_ID: int = 1
|
|
|
|
INSTALLED_APPS: list[str] = [
|
|
"django_prometheus",
|
|
"constance",
|
|
"jazzmin",
|
|
"modeltranslation",
|
|
"django.contrib.admin",
|
|
"django.contrib.admindocs",
|
|
"django.contrib.auth",
|
|
"django.contrib.contenttypes",
|
|
"django.contrib.sessions",
|
|
"django.contrib.messages",
|
|
"django.contrib.staticfiles",
|
|
"django.contrib.sitemaps",
|
|
"django.contrib.gis",
|
|
"django.contrib.humanize",
|
|
"health_check",
|
|
"health_check.db",
|
|
"health_check.cache",
|
|
"health_check.storage",
|
|
"health_check.contrib.migrations",
|
|
"health_check.contrib.psutil",
|
|
"health_check.contrib.db_heartbeat",
|
|
"cacheops",
|
|
"django_hosts",
|
|
"django_celery_beat",
|
|
"django_celery_results",
|
|
"django_extensions",
|
|
"django_redis",
|
|
"django_summernote",
|
|
"widget_tweaks",
|
|
"mptt",
|
|
"rest_framework",
|
|
"rest_framework_simplejwt",
|
|
"rest_framework_simplejwt.token_blacklist",
|
|
"drf_spectacular",
|
|
"drf_spectacular_sidecar",
|
|
"django_json_widget",
|
|
"django_elasticsearch_dsl",
|
|
"dbbackup",
|
|
"corsheaders",
|
|
"constance.backends.database",
|
|
"django_mailbox",
|
|
"graphene_django",
|
|
"core",
|
|
"payments",
|
|
"vibes_auth",
|
|
"blog",
|
|
]
|
|
|
|
MIDDLEWARE: list[str] = [
|
|
"evibes.middleware.BlockInvalidHostMiddleware",
|
|
"django_prometheus.middleware.PrometheusBeforeMiddleware",
|
|
"django_hosts.middleware.HostsRequestMiddleware",
|
|
"django.middleware.security.SecurityMiddleware",
|
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
|
"corsheaders.middleware.CorsMiddleware",
|
|
"evibes.middleware.CustomCommonMiddleware",
|
|
"django.middleware.csrf.CsrfViewMiddleware",
|
|
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
|
"django.contrib.messages.middleware.MessageMiddleware",
|
|
"django.contrib.admindocs.middleware.XViewMiddleware",
|
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
|
"evibes.middleware.CustomLocaleMiddleware",
|
|
"django_hosts.middleware.HostsResponseMiddleware",
|
|
"djangorestframework_camel_case.middleware.CamelCaseMiddleWare",
|
|
"django_prometheus.middleware.PrometheusAfterMiddleware",
|
|
]
|
|
|
|
TEMPLATES: list[dict] = [
|
|
{
|
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
|
"DIRS": [
|
|
BASE_DIR / "vibes_auth/templates",
|
|
BASE_DIR / "core/templates",
|
|
BASE_DIR / "payments/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",
|
|
],
|
|
},
|
|
},
|
|
]
|
|
|
|
USE_I18N: bool = True
|
|
|
|
LANGUAGES: tuple[tuple[str, str], ...] = (
|
|
("en-gb", "English (British)"),
|
|
("ar-ar", "العربية"),
|
|
("cs-cz", "Česky"),
|
|
("da-dk", "Dansk"),
|
|
("de-de", "Deutsch"),
|
|
("en-us", "English (American)"),
|
|
("es-es", "Español"),
|
|
("fr-fr", "Français"),
|
|
("hi-in", "हिंदी"),
|
|
("it-it", "Italiano"),
|
|
("ja-jp", "日本語"),
|
|
("kk-kz", "Қазақ"),
|
|
("nl-nl", "Nederlands"),
|
|
("pl-pl", "Polska"),
|
|
("pt-br", "Português"),
|
|
("ro-ro", "Română"),
|
|
("ru-ru", "Русский"),
|
|
("zh-hans", "简体中文"),
|
|
)
|
|
|
|
LANGUAGE_CODE: str = "en-gb"
|
|
|
|
CURRENCIES: tuple[tuple[str, str], ...] = (
|
|
("en-gb", "EUR"),
|
|
("ar-ar", "AED"),
|
|
("cs-cz", "CZK"),
|
|
("da-dk", "EUR"),
|
|
("de-de", "EUR"),
|
|
("en-us", "USD"),
|
|
("es-es", "EUR"),
|
|
("fr-fr", "EUR"),
|
|
("hi-in", "INR"),
|
|
("it-it", "EUR"),
|
|
("ja-jp", "JPY"),
|
|
("kk-kz", "KZT"),
|
|
("nl-nl", "EUR"),
|
|
("pl-pl", "PLN"),
|
|
("pt-br", "EUR"),
|
|
("ro-ro", "RON"),
|
|
("ru-ru", "RUB"),
|
|
("zh-hans", "CNY"),
|
|
)
|
|
|
|
CURRENCY_CODE: str = dict(CURRENCIES).get(LANGUAGE_CODE) # type: ignore [assignment]
|
|
|
|
MODELTRANSLATION_FALLBACK_LANGUAGES: tuple = (LANGUAGE_CODE, "en-us", "de-de")
|
|
|
|
ROOT_URLCONF: str = "evibes.urls"
|
|
|
|
WSGI_APPLICATION: str = "evibes.wsgi.application"
|
|
|
|
ASGI_APPLICATION: str = "evibes.asgi.application"
|
|
|
|
DEFAULT_AUTO_FIELD: str = "django.db.models.BigAutoField"
|
|
|
|
TIME_ZONE: str = getenv("TIME_ZONE", "Europe/London")
|
|
|
|
STATIC_URL: str = f"https://api.{getenv('EVIBES_BASE_DOMAIN')}/static/"
|
|
STATIC_ROOT: Path = BASE_DIR / "static"
|
|
|
|
MEDIA_URL: str = f"https://api.{getenv('EVIBES_BASE_DOMAIN')}/media/"
|
|
MEDIA_ROOT: Path = BASE_DIR / "media"
|
|
|
|
AUTH_USER_MODEL: str = "vibes_auth.User"
|
|
|
|
AUTH_PASSWORD_VALIDATORS: list[dict[str, str | int]] = [
|
|
{
|
|
"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",
|
|
},
|
|
]
|
|
|
|
APPEND_SLASH: bool = True
|
|
|
|
ROOT_HOSTCONF: str = "evibes.hosts"
|
|
DEFAULT_HOST: str = "api"
|
|
REDIS_PASSWORD: str = getenv("REDIS_PASSWORD", default="")
|
|
|
|
INTERNAL_IPS: list[str] = [
|
|
"127.0.0.1",
|
|
]
|
|
|
|
if getenv("SENTRY_DSN"):
|
|
import sentry_sdk
|
|
from sentry_sdk.integrations.celery import CeleryIntegration
|
|
from sentry_sdk.integrations.django import DjangoIntegration
|
|
from sentry_sdk.integrations.logging import LoggingIntegration
|
|
from sentry_sdk.integrations.redis import RedisIntegration
|
|
|
|
def scrub_sensitive(data):
|
|
if isinstance(data, dict):
|
|
cleaned = {}
|
|
for key, value in data.items():
|
|
if key.lower() in ("password", "confirm_password"):
|
|
cleaned[key] = "[FILTERED]"
|
|
else:
|
|
cleaned[key] = scrub_sensitive(value)
|
|
return cleaned
|
|
if isinstance(data, list):
|
|
return [scrub_sensitive(item) for item in data]
|
|
return data
|
|
|
|
def before_send(event, hint):
|
|
if hint:
|
|
pass
|
|
request = event.get("request", {})
|
|
if "data" in request:
|
|
request["data"] = scrub_sensitive(request["data"])
|
|
event["request"] = request
|
|
return event
|
|
|
|
ignore_errors: list[str] = []
|
|
|
|
sentry_sdk.init(
|
|
dsn=getenv("SENTRY_DSN"),
|
|
integrations=[
|
|
DjangoIntegration(),
|
|
LoggingIntegration(level=logging.INFO, event_level=logging.ERROR),
|
|
CeleryIntegration(),
|
|
RedisIntegration(),
|
|
],
|
|
environment="development" if DEBUG else "production",
|
|
release=f"evibes@{EVIBES_VERSION}",
|
|
traces_sample_rate=1.0 if DEBUG else 0.2,
|
|
profiles_sample_rate=1.0 if DEBUG else 0.1,
|
|
max_request_body_size="always",
|
|
before_send=before_send,
|
|
ignore_errors=ignore_errors,
|
|
debug=False,
|
|
)
|
|
|
|
SESSION_COOKIE_HTTPONLY: bool = True
|
|
CSRF_COOKIE_HTTPONLY: bool = True
|
|
LANGUAGE_COOKIE_HTTPONLY: bool = True
|
|
|
|
DATA_UPLOAD_MAX_NUMBER_FIELDS: int = 8888
|
|
|
|
ADMINS: list[tuple[str, ...]] = [("Egor Gorbunov", "contact@fureunoir.com")]
|
|
|
|
STORAGES: dict[str, dict[str, str | int | bool | None]] = {
|
|
"default": {
|
|
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
|
},
|
|
"staticfiles": {
|
|
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
|
|
},
|
|
"dbbackup": {
|
|
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
|
},
|
|
}
|
|
|
|
if name == "nt":
|
|
GDAL_LIBRARY_PATH = r"C:\OSGeo4W\bin\gdal311.dll"
|
|
GEOS_LIBRARY_PATH = r"C:\OSGeo4W\bin\geos_c.dll"
|