Время: один пояс приложения из .env и на сервере, и на фронте
APP_TZ_OFFSET_HOURS влиял только на «дату игры», а фронт показывал время в захардкоженных +3 — при другом значении дата и время партии противоречили друг другу. Теперь /api/auth/config отдаёт tz_offset_hours, App.tsx выставляет его в format.ts до первой отрисовки страниц, и в нём же показывается всё время и вводятся даты объявлений (запасное значение +3, если конфиг недоступен). Пояс устройства не учитывается — решение владельца. Валидатор ограничивает смещение −12..14. #68 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LqSoRj99iwVEH5U5fnZgsd
This commit is contained in:
@@ -42,8 +42,9 @@ class Settings(BaseSettings):
|
||||
# от этого зависят Secure-cookie и проверка секретов при старте.
|
||||
local_public: str = "local"
|
||||
|
||||
# Часовой пояс приложения (фиксированное смещение, по умолчанию МСК +3).
|
||||
# Хранение всегда в UTC; смещение применяется к «дате игры» и отображению.
|
||||
# Часовой пояс приложения (фиксированное смещение, по умолчанию МСК +3). Хранение всегда
|
||||
# в UTC; смещение применяется к «дате игры» (timeutil.app_today) и к отображению времени
|
||||
# на фронте — оно приходит туда в GET /api/auth/config (#68).
|
||||
app_tz_offset_hours: int = 3
|
||||
|
||||
# ── БД: структура общая, файлы РАЗНЫЕ для dev и prod; выбор по app_env ─────
|
||||
@@ -139,6 +140,15 @@ class Settings(BaseSettings):
|
||||
)
|
||||
return value
|
||||
|
||||
@field_validator("app_tz_offset_hours")
|
||||
@classmethod
|
||||
def _known_tz_offset(cls, value: int) -> int:
|
||||
"""Реальные пояса — от −12 до +14: опечатка в .env — ошибка старта, а не время,
|
||||
сдвинутое на сутки."""
|
||||
if not -12 <= value <= 14:
|
||||
raise ValueError(f"APP_TZ_OFFSET_HOURS={value} вне диапазона −12..14")
|
||||
return value
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _forbid_default_secrets_when_published(self) -> "Settings":
|
||||
"""Fail-fast: опубликованное приложение не стартует с дефолтными/слабыми
|
||||
|
||||
@@ -28,6 +28,7 @@ def auth_config() -> s.AuthConfig:
|
||||
return s.AuthConfig(
|
||||
methods=enabled_methods(),
|
||||
telegram_bot_username=settings.telegram_bot_username,
|
||||
tz_offset_hours=settings.app_tz_offset_hours,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@ class AuthConfig(BaseModel):
|
||||
# Доступные методы входа: ["password","telegram"] в проде, плюс "stub" в деве.
|
||||
methods: list[str] = []
|
||||
telegram_bot_username: str | None = None
|
||||
# Пояс приложения (APP_TZ_OFFSET_HOURS): в нём сервер считает «дату игры», а фронт
|
||||
# показывает время всем игрокам — независимо от пояса устройства (#68).
|
||||
tz_offset_hours: int
|
||||
|
||||
|
||||
# Верхняя граница длины пароля на входе API: отсекает мегабайтные тела до bcrypt.
|
||||
|
||||
Reference in New Issue
Block a user