Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33dd488971 | ||
|
|
27f4a9191a | ||
|
|
1ea2eda04a |
@@ -377,7 +377,7 @@ TOKEN=$(curl -s -X POST http://HOST:PORT/login \
|
||||
|
||||
| Метод | Ответ |
|
||||
|---|---|
|
||||
| `GET /ui/brand` | `{ "brand": "Forgetting", "channel": "Beta", "version": "0.5.0" }` — **без авторизации**, панель берёт отсюда вордмарк на экране логина |
|
||||
| `GET /ui/brand` | `{ "brand": "Forgetting", "channel": "Beta", "version": "0.5.1" }` — имя и версия панели для вордмарка; за авторизацией, чтобы сканер не опознал панель |
|
||||
| `GET /health` | `{ "status", "server", "ip", "gen", "awg": { "status", "peers", "module", "tools" } }`. `200`, если интерфейс поднят, иначе `503` и `status: "degraded"` |
|
||||
| `GET /awg/status` | `{ "up": true, "peers": 3, "publicKey": "…" }` |
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "awg-agent",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.1",
|
||||
"private": true,
|
||||
"description": "Агент ноды: держит исходящее WSS-соединение к core и исполняет запросы на локальном awg-ctrl",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "awg-control",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.1",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -15,7 +15,7 @@ const now = () => Math.floor(Date.now() / 1000);
|
||||
const rnd = (n: number) => Math.floor(Math.random() * n);
|
||||
const b64 = (n: number) => crypto.randomBytes(n).toString("base64");
|
||||
const GEN = "3.1";
|
||||
const MOCK_VERSION = "0.5.0";
|
||||
const MOCK_VERSION = "0.5.1";
|
||||
|
||||
// ── пользователи (vpn://) ──
|
||||
interface U { name: string; ip: string; pub_key: string; vpn_key: string; key_gen: string; online: boolean; lastHandshake: number; rx: number; tx: number }
|
||||
@@ -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) => {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "awg-ui",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
+15
-3
@@ -174,13 +174,25 @@ export default function App() {
|
||||
|
||||
// Восстановить сессию из сохранённого токена
|
||||
useEffect(() => {
|
||||
// Сбрасываем сессию только на 401: сетевой сбой или 502, пока панель перезапускается,
|
||||
// раньше тоже выкидывали на экран входа. В остальных случаях пробуем снова через 5 с.
|
||||
const saved = localStorage.getItem(TOKEN_KEY);
|
||||
if (saved) {
|
||||
startSession(saved).catch(() => {
|
||||
if (!saved) return;
|
||||
let timer: ReturnType<typeof setTimeout> | undefined;
|
||||
let alive = true;
|
||||
const attempt = () => {
|
||||
startSession(saved).catch(e => {
|
||||
if (!alive) return;
|
||||
if (axios.isAxiosError(e) && e.response?.status === 401) {
|
||||
localStorage.removeItem(TOKEN_KEY);
|
||||
setToken('');
|
||||
});
|
||||
} else {
|
||||
timer = setTimeout(attempt, 5000);
|
||||
}
|
||||
});
|
||||
};
|
||||
attempt();
|
||||
return () => { alive = false; clearTimeout(timer); };
|
||||
}, [startSession]);
|
||||
|
||||
// Состояние серверов (онлайн, пиры) обновляем раз в 15 с, пока открыта панель.
|
||||
|
||||
@@ -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(() => {});
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "awg-cli",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.1",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"tsx": "^4.7.0",
|
||||
|
||||
+1
-1
@@ -188,7 +188,7 @@ trap 'exec >&- 2>&-; wait "$LOG_PID" 2>/dev/null || true; exec 3>&-
|
||||
# ⚠️ Дублирует .env из репозитория: установщик собирает URL релиза и печатает
|
||||
# баннер ДО того, как архив с .env скачан, поэтому взять их оттуда не может.
|
||||
# При бампе версии правь оба места.
|
||||
VERSION="0.5.0"
|
||||
VERSION="0.5.1"
|
||||
CHANNEL="${CHANNEL:-Beta}"
|
||||
|
||||
# Откуда брать архив и как называется продукт. По умолчанию — релизы на GitHub; источник
|
||||
|
||||
Reference in New Issue
Block a user