From 29bb30bce5ff6b3d031e0cbcf87e83be70236615 Mon Sep 17 00:00:00 2001 From: Fedor Date: Tue, 21 Jul 2026 12:34:09 +0300 Subject: [PATCH] Add env-based host configuration --- .env.example | 7 ++++ docs/react-dev-backend.md | 31 ++++++++++++++ procollab/settings.py | 51 ++++++++++++++---------- procollab/settings_helpers.py | 5 +++ procollab/tests/__init__.py | 0 procollab/tests/test_settings_helpers.py | 28 +++++++++++++ 6 files changed, 101 insertions(+), 21 deletions(-) create mode 100644 docs/react-dev-backend.md create mode 100644 procollab/settings_helpers.py create mode 100644 procollab/tests/__init__.py create mode 100644 procollab/tests/test_settings_helpers.py diff --git a/.env.example b/.env.example index 4b46938a..800cd674 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,13 @@ DEBUG= DJANGO_SECRET_KEY= +# Дополнительные домены для изолированных dev-контуров; в боевом окружении переменные необязательны. +EXTRA_ALLOWED_HOSTS= +EXTRA_CSRF_TRUSTED_ORIGINS= +# Пример для react-dev: +# EXTRA_ALLOWED_HOSTS=api-react-dev.procollab.ru,react-dev.procollab.ru +# EXTRA_CSRF_TRUSTED_ORIGINS=https://api-react-dev.procollab.ru,https://react-dev.procollab.ru + EMAIL_USER= EMAIL_BACKEND=anymail.backends.unisender_go.EmailBackend VERIFY_EMAIL_REDIRECT_URL=https://app.procollab.ru/auth/verification/ diff --git a/docs/react-dev-backend.md b/docs/react-dev-backend.md new file mode 100644 index 00000000..7564ad79 --- /dev/null +++ b/docs/react-dev-backend.md @@ -0,0 +1,31 @@ +# React Dev Backend + +## Назначение + +Дополнительные домены отдельных dev-контуров настраиваются через окружение. Это позволяет обновлять backend из репозитория без локальных изменений `procollab/settings.py`. + +Базовые значения `ALLOWED_HOSTS` и `CSRF_TRUSTED_ORIGINS` остаются прежними. Если новые переменные не заданы или пусты, поведение dev и production не меняется. + +## Настройка react-dev + +В окружении процесса или контейнера `api-react-dev` задаются: + +```dotenv +EXTRA_ALLOWED_HOSTS=api-react-dev.procollab.ru,react-dev.procollab.ru +EXTRA_CSRF_TRUSTED_ORIGINS=https://api-react-dev.procollab.ru,https://react-dev.procollab.ru +``` + +После изменения окружения настройки применятся при следующем запуске backend-процесса. Этот документ не описывает и не инициирует deploy. + +## Правила разбора + +- значения разделяются запятыми; +- пробелы по краям удаляются; +- пустые элементы игнорируются; +- дополнительные значения добавляются после базовых; +- для `EXTRA_ALLOWED_HOSTS` указываются домены без схемы; +- для `EXTRA_CSRF_TRUSTED_ORIGINS` указываются полные origins со схемой `http://` или `https://`. + +## Ограничения + +Настройка не меняет API endpoints, сущности, статусы или бизнес-логику. Она не выполняет проверку доступности доменов и не управляет nginx, Docker или инфраструктурой. Корректность формата trusted origins дополнительно проверяется стандартными проверками Django при запуске. diff --git a/procollab/settings.py b/procollab/settings.py index 4ae97cd7..32498e15 100644 --- a/procollab/settings.py +++ b/procollab/settings.py @@ -6,6 +6,8 @@ from decouple import config +from procollab.settings_helpers import extend_with_env_list + mimetypes.add_type("application/javascript", ".js", True) mimetypes.add_type("text/css", ".css", True) mimetypes.add_type("text/html", ".html", True) @@ -23,28 +25,35 @@ TAGGIT_CASE_INSENSITIVE = True -CSRF_TRUSTED_ORIGINS = [ - "http://localhost:8000", - "http://127.0.0.1:8000", - "http://0.0.0.0:8000", - "https://api.procollab.ru", - "https://procollab.ru", - "https://www.procollab.ru", - "https://app.procollab.ru", - "https://dev.procollab.ru", -] +# Дополнительные домены позволяют отдельным dev-контурам обходиться без локальных правок settings.py. +CSRF_TRUSTED_ORIGINS = extend_with_env_list( + [ + "http://localhost:8000", + "http://127.0.0.1:8000", + "http://0.0.0.0:8000", + "https://api.procollab.ru", + "https://procollab.ru", + "https://www.procollab.ru", + "https://app.procollab.ru", + "https://dev.procollab.ru", + ], + config("EXTRA_CSRF_TRUSTED_ORIGINS", default="", cast=str), +) -ALLOWED_HOSTS = [ - "127.0.0.1:8000", - "127.0.0.1", - "localhost", - "0.0.0.0", - "api.procollab.ru", - "app.procollab.ru", - "dev.procollab.ru", - "procollab.ru", - "web", # From Docker -] +ALLOWED_HOSTS = extend_with_env_list( + [ + "127.0.0.1:8000", + "127.0.0.1", + "localhost", + "0.0.0.0", + "api.procollab.ru", + "app.procollab.ru", + "dev.procollab.ru", + "procollab.ru", + "web", # Имя сервиса в Docker + ], + config("EXTRA_ALLOWED_HOSTS", default="", cast=str), +) PASSWORD_HASHERS = [ "django.contrib.auth.hashers.BCryptSHA256PasswordHasher", diff --git a/procollab/settings_helpers.py b/procollab/settings_helpers.py new file mode 100644 index 00000000..e367d669 --- /dev/null +++ b/procollab/settings_helpers.py @@ -0,0 +1,5 @@ +def extend_with_env_list(base_values: list[str], raw_value: str) -> list[str]: + """Добавляет к базовому списку непустые значения из env-строки через запятую.""" + extra_values = [value.strip() for value in raw_value.split(",") if value.strip()] + + return [*base_values, *extra_values] diff --git a/procollab/tests/__init__.py b/procollab/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/procollab/tests/test_settings_helpers.py b/procollab/tests/test_settings_helpers.py new file mode 100644 index 00000000..b4976c00 --- /dev/null +++ b/procollab/tests/test_settings_helpers.py @@ -0,0 +1,28 @@ +from unittest import TestCase + +from procollab.settings_helpers import extend_with_env_list + + +class ExtendWithEnvListTests(TestCase): + def test_keeps_base_values_when_env_value_is_empty(self): + base_values = ["localhost", "procollab.ru"] + + result = extend_with_env_list(base_values, "") + + self.assertEqual(result, base_values) + self.assertIsNot(result, base_values) + + def test_trims_and_appends_non_empty_values(self): + result = extend_with_env_list( + ["localhost"], + " api-react-dev.procollab.ru, ,react-dev.procollab.ru ,", + ) + + self.assertEqual( + result, + [ + "localhost", + "api-react-dev.procollab.ru", + "react-dev.procollab.ru", + ], + )