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 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» — дефолтное имя от приложения, оно не ценнее сохранённого. */
|
||||
export function isPlaceholderName(name) {
|
||||
@@ -58,7 +67,9 @@ export function healClientsMeta(clients, meta) {
|
||||
if (!id) return row;
|
||||
const userData = { ...(row.userData || {}) };
|
||||
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])) {
|
||||
userData[field] = saved[field];
|
||||
restored++;
|
||||
@@ -69,6 +80,7 @@ export function healClientsMeta(clients, meta) {
|
||||
if (isMeaningful(field, userData[field])) keep[field] = userData[field];
|
||||
}
|
||||
if (Object.keys(keep).length) nextMeta[id] = keep;
|
||||
else delete nextMeta[id];
|
||||
return { ...row, userData };
|
||||
});
|
||||
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";
|
||||
|
||||
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" } },
|
||||
];
|
||||
|
||||
@@ -22,9 +30,18 @@ const wiped = [
|
||||
const fixed = healClientsMeta(wiped, snap.meta);
|
||||
assert.equal(fixed.clients[0].userData.clientName, "Mama");
|
||||
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[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. Повторный прогон уже целой таблицы ничего не чинит и не переписывает снимок.
|
||||
const again = healClientsMeta(fixed.clients, fixed.meta);
|
||||
|
||||
Reference in New Issue
Block a user