Files
netrunner-backend/frontend/README.md
T
2026-07-05 14:23:31 +07:00

50 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Netrunner — фронтенд
SPA-клиент (React 19 + TypeScript + Vite) для Netrunner Control Plane. Собирается в
статику и раздаётся самим бэкендом ([`../src/api.rs`](../src/api.rs) — `ServeDir` с
SPA-фолбэком на `index.html`), поэтому в проде отдельного веб-сервера для фронта нет.
## Экраны (`src/*.tsx`)
| Файл | Роут | Что делает |
|---|---|---|
| `Auth.tsx` | `/` | Вход: Telegram Login Widget, генерация/логин Ghost-seed (с обязательным скачиванием + подтверждением сохранения seed перед переходом дальше). Хранит терминальный лог событий для киберпанк-эстетики. |
| `Profile.tsx` | `/profile` | Личный кабинет: баланс, статус подписки, покупка тарифа через TON Connect, реферальная ссылка. Также цель WebApp-ссылок из бота («Личный Кабинет»/«Тарифы»/«Синдикат»). |
| `HackGame.tsx` | `/hack` | Обёртка над npm-пакетом `cyberhack` (мини-игра). Server-authoritative: сначала `POST /users/hack/start` за доской, сгенерированной сервером, по завершении партии шлёт путь кликов на `POST /users/hack/result` — сервер сам считает очки. |
| `AdminDashboard.tsx` | `/admin` | Список всех VPN-нод (`GET /admin/nodes`, любой статус) + форма добавления ноды + force-restart/удаление. Доступ ограничен `admin_guard` на бэкенде; сам роут на фронте не проверяет роль (полагается на то, что API откажет не-админу `401/403`). |
`App.tsx` — роутинг (`react-router-dom`), провайдер `TonConnectUIProvider` и мост
`useBootstrapTokenExchange`: если в URL есть `#token=` (пришли из бота), сразу меняет
его на cookie-сессию через `POST /auth/exchange` и чистит URL.
`api.ts` — единая обёртка `apiFetch` над `/api/v1/*`: всегда с cookie
(`credentials: "same-origin"`), при первом `401` тихо пробует `POST /auth/refresh` и
повторяет запрос один раз, при провале — редирект на `/`.
## Аутентификация на фронте
Сессия — только HttpOnly-cookie (`nrxp_token`/`nrxp_refresh`), которую полностью
контролирует сервер; фронт её не читает и не хранит нигде сам (ни `localStorage`, ни
JS-видимая cookie). Раньше `api.ts` пытался читать `nrxp_token` через `document.cookie`
для простановки в `Authorization: Bearer`, но сервер ставил её `HttpOnly` — то есть JS
физически не мог её увидеть, и все "авторизованные" запросы уходили без токена вообще.
Подробности серверной части — в [`../src/modules/auth/README.md`](../src/modules/auth/README.md).
## Разработка
```bash
pnpm install
pnpm dev # dev-сервер Vite; бэкенд отдельно на :8080 (см. VITE_API_BASE)
pnpm build # tsc -b && vite build -> dist/
pnpm lint
```
Переменные окружения (`.env.production` / Vite `import.meta.env`):
`VITE_API_BASE` (по умолчанию `/api/v1`).
Юзернейм бота (для Telegram Login Widget и реферальной ссылки) **не** build-time
переменная — этот SPA собирается один раз в CI и раздаётся одинаково и прод-, и
dev-стендом, так что зашитое в бандл значение не различалось бы между ними. Вместо
`VITE_BOT_USERNAME` `Auth.tsx`/`Profile.tsx` берут его рантаймом через
`GET /api/v1/config` (`api.ts::getPublicConfig`), который читает `BOT_USERNAME` из
окружения сервера заново на каждый запрос.