mirror of
https://github.com/andrey271192/amnezia_web-PRO.git
synced 2026-09-20 14:42:00 +00:00
fix: keep disconnect dates in the clients metadata snapshot
Даты «Задать дату» (lastDisconnectedAt) и отключение по расписанию (scheduledTunnelDisconnectAt) тоже живут в clientsTable и терялись при затирании. Снимок хранит и их, но возвращает только когда запись реально затёрли (пропал creationDate) — иначе воскресало бы снятое в панели расписание. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,8 +11,17 @@
|
|||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
/** Поля userData, которые ведёт панель и которые нельзя терять. */
|
/** Поля, которые панель сама никогда не стирает: пустое значение = потеря. */
|
||||||
export const META_FIELDS = ["clientName", "creationDate", "last_config", "allowedIps"];
|
export const STABLE_FIELDS = ["clientName", "creationDate", "last_config", "allowedIps"];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Даты, которые панель штатно снимает («Задать дату», отключение по расписанию).
|
||||||
|
* Их возвращаем только когда запись действительно затёрли, иначе воскресим
|
||||||
|
* снятое расписание.
|
||||||
|
*/
|
||||||
|
export const DATE_FIELDS = ["lastDisconnectedAt", "scheduledTunnelDisconnectAt"];
|
||||||
|
|
||||||
|
export const META_FIELDS = [...STABLE_FIELDS, ...DATE_FIELDS];
|
||||||
|
|
||||||
/** «Client 17» — дефолтное имя от приложения, оно не ценнее сохранённого. */
|
/** «Client 17» — дефолтное имя от приложения, оно не ценнее сохранённого. */
|
||||||
export function isPlaceholderName(name) {
|
export function isPlaceholderName(name) {
|
||||||
@@ -58,7 +67,9 @@ export function healClientsMeta(clients, meta) {
|
|||||||
if (!id) return row;
|
if (!id) return row;
|
||||||
const userData = { ...(row.userData || {}) };
|
const userData = { ...(row.userData || {}) };
|
||||||
const saved = nextMeta[id] || {};
|
const saved = nextMeta[id] || {};
|
||||||
for (const field of META_FIELDS) {
|
// Приложение сносит creationDate целиком — по нему и опознаём затирание.
|
||||||
|
const wiped = !isMeaningful("creationDate", userData.creationDate) && isMeaningful("creationDate", saved.creationDate);
|
||||||
|
for (const field of wiped ? META_FIELDS : STABLE_FIELDS) {
|
||||||
if (!isMeaningful(field, userData[field]) && isMeaningful(field, saved[field])) {
|
if (!isMeaningful(field, userData[field]) && isMeaningful(field, saved[field])) {
|
||||||
userData[field] = saved[field];
|
userData[field] = saved[field];
|
||||||
restored++;
|
restored++;
|
||||||
@@ -69,6 +80,7 @@ export function healClientsMeta(clients, meta) {
|
|||||||
if (isMeaningful(field, userData[field])) keep[field] = userData[field];
|
if (isMeaningful(field, userData[field])) keep[field] = userData[field];
|
||||||
}
|
}
|
||||||
if (Object.keys(keep).length) nextMeta[id] = keep;
|
if (Object.keys(keep).length) nextMeta[id] = keep;
|
||||||
|
else delete nextMeta[id];
|
||||||
return { ...row, userData };
|
return { ...row, userData };
|
||||||
});
|
});
|
||||||
return { clients: healed, restored, meta: nextMeta, metaChanged: JSON.stringify(nextMeta) !== before };
|
return { clients: healed, restored, meta: nextMeta, metaChanged: JSON.stringify(nextMeta) !== before };
|
||||||
|
|||||||
@@ -3,7 +3,15 @@ import assert from "assert";
|
|||||||
import { healClientsMeta, isPlaceholderName } from "./clients-meta.mjs";
|
import { healClientsMeta, isPlaceholderName } from "./clients-meta.mjs";
|
||||||
|
|
||||||
const good = [
|
const good = [
|
||||||
{ clientId: "A=", userData: { clientName: "Mama", creationDate: "Sat Jun 27 2026", last_config: "{...}" } },
|
{
|
||||||
|
clientId: "A=",
|
||||||
|
userData: {
|
||||||
|
clientName: "Mama",
|
||||||
|
creationDate: "Sat Jun 27 2026",
|
||||||
|
last_config: "{...}",
|
||||||
|
lastDisconnectedAt: "2027-05-06T10:00:00.000Z",
|
||||||
|
},
|
||||||
|
},
|
||||||
{ clientId: "B=", userData: { clientName: "teplici", creationDate: "Sat Jul 04 2026" } },
|
{ clientId: "B=", userData: { clientName: "teplici", creationDate: "Sat Jul 04 2026" } },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -22,9 +30,18 @@ const wiped = [
|
|||||||
const fixed = healClientsMeta(wiped, snap.meta);
|
const fixed = healClientsMeta(wiped, snap.meta);
|
||||||
assert.equal(fixed.clients[0].userData.clientName, "Mama");
|
assert.equal(fixed.clients[0].userData.clientName, "Mama");
|
||||||
assert.equal(fixed.clients[0].userData.last_config, "{...}");
|
assert.equal(fixed.clients[0].userData.last_config, "{...}");
|
||||||
|
assert.equal(fixed.clients[0].userData.lastDisconnectedAt, "2027-05-06T10:00:00.000Z");
|
||||||
assert.equal(fixed.clients[1].userData.creationDate, "Sat Jul 04 2026");
|
assert.equal(fixed.clients[1].userData.creationDate, "Sat Jul 04 2026");
|
||||||
assert.equal(fixed.clients[2].userData.clientName, "Client 2");
|
assert.equal(fixed.clients[2].userData.clientName, "Client 2");
|
||||||
assert.equal(fixed.restored, 5);
|
assert.equal(fixed.restored, 6);
|
||||||
|
|
||||||
|
// 2б. Дату сняли в панели (запись целая) — снимок её не воскрешает и забывает.
|
||||||
|
const cleared = healClientsMeta(
|
||||||
|
[{ clientId: "A=", userData: { clientName: "Mama", creationDate: "Sat Jun 27 2026", last_config: "{...}" } }],
|
||||||
|
snap.meta
|
||||||
|
);
|
||||||
|
assert.equal(cleared.clients[0].userData.lastDisconnectedAt, undefined);
|
||||||
|
assert.equal(cleared.meta["A="].lastDisconnectedAt, undefined);
|
||||||
|
|
||||||
// 3. Повторный прогон уже целой таблицы ничего не чинит и не переписывает снимок.
|
// 3. Повторный прогон уже целой таблицы ничего не чинит и не переписывает снимок.
|
||||||
const again = healClientsMeta(fixed.clients, fixed.meta);
|
const again = healClientsMeta(fixed.clients, fixed.meta);
|
||||||
|
|||||||
Reference in New Issue
Block a user