удаление test-контура (дополнение)
This commit is contained in:
+19
-10
@@ -4,7 +4,7 @@ from __future__ import annotations
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
|
||||
from pydantic import model_validator
|
||||
from pydantic import field_validator, model_validator
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
# Единый .env лежит в КОРНЕ репозитория (рядом с .env.example) — читается одинаково
|
||||
@@ -18,6 +18,9 @@ _DEFAULT_SECRET_KEY = "change-me-dev-secret-not-for-production"
|
||||
_DEFAULT_ADMIN_PASSWORD = "change-me-admin-password"
|
||||
_MIN_SECRET_KEY_LENGTH = 32
|
||||
|
||||
# Допустимые окружения. Отдельного test-контура нет: всё проверяется в development.
|
||||
_APP_ENVS = ("development", "production")
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
model_config = SettingsConfigDict(
|
||||
@@ -27,14 +30,13 @@ class Settings(BaseSettings):
|
||||
case_sensitive=False,
|
||||
)
|
||||
|
||||
# ── Главный переключатель окружения: development | test | production ───────
|
||||
# ── Главный переключатель окружения: development | production ─────────────
|
||||
# development — нативный dev (uvicorn + vite), БД в ./data/dev/, вход Telegram+ник.
|
||||
# test — прод-клон в Docker локально (порт 8080), ведёт себя как прод.
|
||||
# production — Docker на Pi; контейнер форсит это значение, игнорируя .env.
|
||||
app_env: str = "development"
|
||||
log_level: str = "INFO"
|
||||
|
||||
# Публикация локального окружения (dev/test) наружу через VPS-туннель.
|
||||
# Публикация локального dev-окружения наружу через VPS-туннель.
|
||||
# Читает ЛАУНЧЕР (run.ps1/run.sh): local — только localhost; vps — плюс SSH-туннель
|
||||
# на forbidden-stars.ru. Влияет на cookie_secure (vps ⇒ снаружи HTTPS ⇒ Secure-cookie).
|
||||
local_public: str = "local"
|
||||
@@ -91,17 +93,13 @@ class Settings(BaseSettings):
|
||||
стартовый bootstrap в lifespan и синхронизацию админа из .env."""
|
||||
return self.app_env.lower() == "development"
|
||||
|
||||
@property
|
||||
def is_test(self) -> bool:
|
||||
return self.app_env.lower() == "test"
|
||||
|
||||
@property
|
||||
def is_production(self) -> bool:
|
||||
return self.app_env.lower() == "production"
|
||||
|
||||
@property
|
||||
def database_url(self) -> str:
|
||||
"""БД: dev — отдельный файл дева; test и prod — том контейнера (/data)."""
|
||||
"""БД: dev — отдельный файл дева; prod — том контейнера (/data)."""
|
||||
return self.dev_database_url if self.is_development else self.prod_database_url
|
||||
|
||||
@property
|
||||
@@ -122,13 +120,24 @@ class Settings(BaseSettings):
|
||||
def cookie_domain_value(self) -> str | None:
|
||||
return self.cookie_domain or None
|
||||
|
||||
@field_validator("app_env")
|
||||
@classmethod
|
||||
def _known_app_env(cls, value: str) -> str:
|
||||
"""Неизвестное окружение — ошибка старта, а не молчаливое «почти прод»: любое
|
||||
значение, кроме development, выбирает прод-пути к данным и выключает dev-вход."""
|
||||
if value.lower() not in _APP_ENVS:
|
||||
raise ValueError(
|
||||
f"APP_ENV={value!r} не поддерживается — допустимо: {', '.join(_APP_ENVS)}"
|
||||
)
|
||||
return value
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _forbid_default_secrets_in_prod(self) -> "Settings":
|
||||
"""Fail-fast: в production не стартуем с дефолтными/слабыми секретами (#59).
|
||||
|
||||
Деплой, скопировавший .env.example дословно (или забывший поле), иначе поднялся бы
|
||||
с общеизвестным ключом подписи JWT (подделка любого токена, включая админский) и
|
||||
известным паролем администратора. В dev/test проверка не мешает — там дефолты норма."""
|
||||
известным паролем администратора. В dev проверка не мешает — там дефолты норма."""
|
||||
if self.app_env.lower() != "production":
|
||||
return self
|
||||
problems: list[str] = []
|
||||
|
||||
Reference in New Issue
Block a user