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.
This commit is contained in:
@@ -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}` })) });
|
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);
|
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("/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.post("/logout", (_q, r) => r.json({ ok: true }));
|
||||||
app.get("/health", (q, r) => {
|
app.get("/health", (q, r) => {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
// This source code is licensed under the MIT license found in the
|
// This source code is licensed under the MIT license found in the
|
||||||
// LICENSE file in the root directory of this source tree.
|
// LICENSE file in the root directory of this source tree.
|
||||||
import { useState, useEffect, useLayoutEffect, useCallback, useRef } from 'react';
|
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 { 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 { useTheme, setThemeMode, type ThemeMode } from '../../lib/theme';
|
||||||
import { IcoCheck, IcoCopy, IcoRefresh, IcoTrash, IcoPlus } from '../../components/icons';
|
import { IcoCheck, IcoCopy, IcoRefresh, IcoTrash, IcoPlus } from '../../components/icons';
|
||||||
@@ -138,7 +137,8 @@ export default function SettingsPage({ token, showMsg }: PageProps) {
|
|||||||
} catch {
|
} catch {
|
||||||
showMsg('Ошибка загрузки настроек');
|
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 || '',
|
brand: data.brand || BRAND_FALLBACK, channel: data.channel || '', version: data.version || '',
|
||||||
})).catch(() => {});
|
})).catch(() => {});
|
||||||
apiFetch('GET', '/ui/nodes', token).then(r => setNodes(r.nodes ?? [])).catch(() => {});
|
apiFetch('GET', '/ui/nodes', token).then(r => setNodes(r.nodes ?? [])).catch(() => {});
|
||||||
|
|||||||
Reference in New Issue
Block a user