From 27f4a9191a9553c0ed98d4e4b5feb1d1964745e4 Mon Sep 17 00:00:00 2001 From: Ivan Vasilev Date: Thu, 29 Oct 2026 23:51:21 +0300 Subject: [PATCH] Send the token with /ui/brand from the settings tab The route has been behind auth since aa848de, but the settings tab still called it without a token: the 401 "Unauthorized" made the panel treat the session as expired and log out on every visit to Settings. The mock now requires auth on /ui/brand too, like the server. --- awg-ui/mock-server.ts | 4 +++- awg-ui/src/tabs/settings/index.tsx | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/awg-ui/mock-server.ts b/awg-ui/mock-server.ts index 9bbc757..9e2e590 100644 --- a/awg-ui/mock-server.ts +++ b/awg-ui/mock-server.ts @@ -67,7 +67,9 @@ const devOut = (m: MK, d: Dev) => ({ ...d, ips: m.servers.filter(s => s !== 2).map(s => ({ server_id: s, ip: `10.9.0.${50 + d.id + s * 10}` })) }); const find = (id: string) => masters.find(m => m.id === Number(id) && !m.deleting); -app.get("/ui/brand", (_q, r) => r.json({ brand: "Forgetting", channel: "Beta", version: MOCK_VERSION })); +// Как на сервере: за авторизацией, без токена — 401 «Unauthorized» (на него панель выходит из сессии). +app.get("/ui/brand", (q, r) => { if (!q.headers.authorization) { r.status(401).json({ error: "Unauthorized" }); return; } + r.json({ brand: "Forgetting", channel: "Beta", version: MOCK_VERSION }); }); app.post("/login", (q, r) => q.body.user === "admin" && q.body.pass === "admin" ? r.json({ token: "mock." + crypto.randomBytes(8).toString("hex") + ".sig" }) : r.status(401).json({ error: "Неверный логин или пароль" })); app.post("/logout", (_q, r) => r.json({ ok: true })); app.get("/health", (q, r) => { diff --git a/awg-ui/src/tabs/settings/index.tsx b/awg-ui/src/tabs/settings/index.tsx index 0c02468..deca306 100644 --- a/awg-ui/src/tabs/settings/index.tsx +++ b/awg-ui/src/tabs/settings/index.tsx @@ -2,7 +2,6 @@ // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. import { useState, useEffect, useLayoutEffect, useCallback, useRef } from 'react'; -import axios from 'axios'; import { apiFetch, copyText, timeAgo, BRAND_FALLBACK, SETTINGS_SECTION_KEY, type Brand, type NodeInfo, type PageProps } from '../../lib/shared'; import { useTheme, setThemeMode, type ThemeMode } from '../../lib/theme'; import { IcoCheck, IcoCopy, IcoRefresh, IcoTrash, IcoPlus } from '../../components/icons'; @@ -138,7 +137,8 @@ export default function SettingsPage({ token, showMsg }: PageProps) { } catch { showMsg('Ошибка загрузки настроек'); } - axios.get('/ui/brand').then(({ data }) => setBrand({ + // /ui/brand за авторизацией: без токена 401 «Unauthorized», и App считал сессию истёкшей. + apiFetch('GET', '/ui/brand', token).then(data => setBrand({ brand: data.brand || BRAND_FALLBACK, channel: data.channel || '', version: data.version || '', })).catch(() => {}); apiFetch('GET', '/ui/nodes', token).then(r => setNodes(r.nodes ?? [])).catch(() => {});