diff --git a/README.md b/README.md index fd9ce47..899db98 100644 --- a/README.md +++ b/README.md @@ -187,7 +187,7 @@ TOKEN=$(curl -s -X POST http://HOST:PORT/login \ | Метод | Ответ | |---|---| -| `GET /ui/brand` | `{ "brand": "Forgetting", "channel": "Beta", "version": "0.4.7" }` — **без авторизации**, панель берёт отсюда вордмарк на экране логина | +| `GET /ui/brand` | `{ "brand": "Forgetting", "channel": "Beta", "version": "0.4.7" }` — требует JWT панели (без авторизации выдавал бы панель сканерам). Вордмарк в шапке после входа | | `GET /health` | `{ "status", "server", "ip", "gen", "awg": { "status", "peers", "module", "tools" } }`. `200`, если интерфейс поднят, иначе `503` и `status: "degraded"` | | `GET /awg/status` | `{ "up": true, "peers": 3, "publicKey": "…" }` | diff --git a/awg-ui/index.html b/awg-ui/index.html index 53a3a4a..0fea124 100644 --- a/awg-ui/index.html +++ b/awg-ui/index.html @@ -3,7 +3,7 @@ - AWG Panel + Вход
diff --git a/awg-ui/server.ts b/awg-ui/server.ts index ed2fc4a..0eb3a22 100644 --- a/awg-ui/server.ts +++ b/awg-ui/server.ts @@ -206,9 +206,9 @@ app.post("/logout", requireAuth, (req: Request, res: Response) => { res.json({ ok: true }); }); -// Единственный роут без авторизации: вордмарк нужен уже на экране логина, -// до выдачи JWT. Наружу уходит только имя продукта и версия. -app.get("/ui/brand", (_req: Request, res: Response) => { +// За авторизацией: без неё сканер одним GET узнавал бы, что на порту панель Forgetting. +// Экран логина обходится без вордмарка. +app.get("/ui/brand", requireAuth, (_req: Request, res: Response) => { res.json({ brand: BRAND, channel: CHANNEL, version: VERSION }); }); diff --git a/awg-ui/src/App.tsx b/awg-ui/src/App.tsx index 666fa92..d75c953 100644 --- a/awg-ui/src/App.tsx +++ b/awg-ui/src/App.tsx @@ -185,17 +185,20 @@ export default function App() { return () => clearInterval(t); }, [token, loadNodes]); - // Имя продукта и версия — с сервера, до логина (роут без авторизации). - // Если не ответил, остаётся фолбэк из констант. + // Имя продукта и версия — с сервера, только после логина: роут за авторизацией, чтобы + // панель не опознавалась сканером. Если не ответил, остаётся фолбэк из констант. useEffect(() => { - axios.get('/ui/brand') + if (!token) return; + axios.get('/ui/brand', { headers: { Authorization: `Bearer ${token}` } }) .then(({ data }) => setBrand({ brand: data.brand || BRAND_FALLBACK, channel: data.channel || '', version: data.version || '', })) .catch(() => { /* остаётся фолбэк */ }); - }, []); + }, [token]); + + useEffect(() => { document.title = token ? brand.brand : 'Вход'; }, [token, brand.brand]); // Применять и сохранять тему useEffect(() => { @@ -249,7 +252,7 @@ export default function App() { {!token ? (
- {brand.brand} + Вход

Войдите, чтобы продолжить