Serve bot_username at runtime instead of baking it into the SPA build
Auth.tsx and Profile.tsx read import.meta.env.VITE_BOT_USERNAME — a Vite build-time constant. This ЛК frontend is a single static bundle built once in CI and served identically by both prod and dev (no server-rendering to re-inject a value per environment, unlike the Next.js landing fix from earlier). So the Telegram Login Widget on the dev stand was rendering with whatever bot the CI build happened to be compiled with — in practice the fallback default, the prod bot's username — and Telegram correctly refused it with "Bot domain invalid" since that bot's registered domain is the prod domain, not dev.netrunner-vpn.com. Added GET /api/v1/config (unauthenticated, reads BOT_USERNAME from the server's actual environment on every request) and switched both files to fetch it at runtime instead of reading the baked-in env var. Verified locally: the dev container's /api/v1/config correctly returns its own dev bot's username, and a real headless Chrome run confirms the Login Widget script tag gets that value, not the hardcoded fallback. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,23 @@
|
||||
export const API_BASE = import.meta.env.VITE_API_BASE || "/api/v1";
|
||||
|
||||
let configPromise: Promise<{ bot_username: string }> | null = null;
|
||||
|
||||
/// Юзернейм бота — намеренно не `import.meta.env.VITE_BOT_USERNAME`: этот SPA
|
||||
/// собирается один раз в CI, и один и тот же статический бандл раздаётся и
|
||||
/// прод-, и dev-стендом — build-time значение зашилось бы в файлы намертво и
|
||||
/// не различалось бы между стендами (ровно так и вышло на практике: dev видел
|
||||
/// прод-бота, у которого в BotFather другой домен — виджет логина отвечал
|
||||
/// "Bot domain invalid"). `/api/v1/config` читает env на сервере заново на
|
||||
/// каждый запрос, поэтому корректно отдаёт "свой" бот для каждого стенда.
|
||||
export function getPublicConfig(): Promise<{ bot_username: string }> {
|
||||
if (!configPromise) {
|
||||
configPromise = fetch(`${API_BASE}/config`)
|
||||
.then((res) => res.json())
|
||||
.catch(() => ({ bot_username: "ntrnr_vpn_bot" }));
|
||||
}
|
||||
return configPromise;
|
||||
}
|
||||
|
||||
// Сессия живёт только в HttpOnly cookie, которую ставит сервер — JS её не видит
|
||||
// и не должен: раньше здесь читался `document.cookie` в расчёте на токен,
|
||||
// который сервер ставит как HttpOnly, поэтому чтение всегда возвращало null, а
|
||||
|
||||
Reference in New Issue
Block a user