mirror of
https://github.com/andrey271192/amnezia_web-PRO.git
synced 2026-09-20 14:42:00 +00:00
fix: load clients for selected profile
This commit is contained in:
@@ -34,6 +34,8 @@
|
|||||||
|
|
||||||
Если проверка на сервере показывает два разных контейнера, например `amnezia-awg2` и `amnezia-awg`, с разными портами и разным числом клиентов — это не дубль, а два инстанса. Начиная с **v1.2.33** карточки используют реальное имя профиля (`label`), чтобы `AmneziaWG 2.0` и `AmneziaWG` не выглядели одинаково.
|
Если проверка на сервере показывает два разных контейнера, например `amnezia-awg2` и `amnezia-awg`, с разными портами и разным числом клиентов — это не дубль, а два инстанса. Начиная с **v1.2.33** карточки используют реальное имя профиля (`label`), чтобы `AmneziaWG 2.0` и `AmneziaWG` не выглядели одинаково.
|
||||||
|
|
||||||
|
Если переключатель **«Инстанс»** показывает правильный контейнер, но таблица **«Пользователи»** остаётся от другого инстанса, обновите до **v1.2.34**. Клиентские запросы (`/api/clients` и операции над пользователями) теперь всегда передают явный `profileId`, а не полагаются только на cookie выбранного профиля.
|
||||||
|
|
||||||
## Лендинг не поднимается (порт 80 занят)
|
## Лендинг не поднимается (порт 80 занят)
|
||||||
|
|
||||||
При ошибке bind `:80` используйте при установке **`SKIP_LANDING=1`** или **`LANDING_PORT=8081`** — админка на `HOST_PORT` (например 8080) от этого не зависит.
|
При ошибке bind `:80` используйте при установке **`SKIP_LANDING=1`** или **`LANDING_PORT=8081`** — админка на `HOST_PORT` (например 8080) от этого не зависит.
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "amnezia-admin",
|
"name": "amnezia-admin",
|
||||||
"version": "1.2.33",
|
"version": "1.2.34",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "amnezia-admin",
|
"name": "amnezia-admin",
|
||||||
"version": "1.2.33",
|
"version": "1.2.34",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.21.2"
|
"express": "^4.21.2"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "amnezia-admin",
|
"name": "amnezia-admin",
|
||||||
"version": "1.2.33",
|
"version": "1.2.34",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "amnezia_web-PRO — веб-панель AmneziaWG: несколько инстансов, WARP, каскад/Endpoint, экспорт .conf (Docker)",
|
"description": "amnezia_web-PRO — веб-панель AmneziaWG: несколько инстансов, WARP, каскад/Endpoint, экспорт .conf (Docker)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -434,18 +434,18 @@ dtOk.addEventListener("click", async () => {
|
|||||||
setStatus("Выполняю…", false);
|
setStatus("Выполняю…", false);
|
||||||
await api("/api/clients/disable", {
|
await api("/api/clients/disable", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify({ clientId: dtClient.clientId, disconnectedAt: iso }),
|
body: JSON.stringify(withCurrentProfile({ clientId: dtClient.clientId, disconnectedAt: iso })),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const scheduleTunnel = Boolean(dtScheduleTunnel.checked && dtClient.activeInConf);
|
const scheduleTunnel = Boolean(dtScheduleTunnel.checked && dtClient.activeInConf);
|
||||||
setStatus(scheduleTunnel ? "Сохраняю расписание отключения…" : "Сохраняю дату…", false);
|
setStatus(scheduleTunnel ? "Сохраняю расписание отключения…" : "Сохраняю дату…", false);
|
||||||
await api("/api/clients/disconnect-date", {
|
await api("/api/clients/disconnect-date", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify({
|
body: JSON.stringify(withCurrentProfile({
|
||||||
clientId: dtClient.clientId,
|
clientId: dtClient.clientId,
|
||||||
disconnectedAt: iso,
|
disconnectedAt: iso,
|
||||||
scheduleTunnelDisconnect: scheduleTunnel,
|
scheduleTunnelDisconnect: scheduleTunnel,
|
||||||
}),
|
})),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
dtDialog.close();
|
dtDialog.close();
|
||||||
@@ -1247,6 +1247,16 @@ function currentProfileQuerySuffix() {
|
|||||||
return pid ? `&profileId=${encodeURIComponent(pid)}` : "";
|
return pid ? `&profileId=${encodeURIComponent(pid)}` : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function currentProfileQueryString() {
|
||||||
|
const pid = currentProfileIdValue();
|
||||||
|
return pid ? `?profileId=${encodeURIComponent(pid)}` : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function withCurrentProfile(body = {}) {
|
||||||
|
const pid = currentProfileIdValue();
|
||||||
|
return pid ? { ...body, profileId: pid } : body;
|
||||||
|
}
|
||||||
|
|
||||||
/** Прямая GET-ссылка на скачивание (работает в браузере с активной сессией панели). */
|
/** Прямая GET-ссылка на скачивание (работает в браузере с активной сессией панели). */
|
||||||
function clientExportGetUrl(clientId) {
|
function clientExportGetUrl(clientId) {
|
||||||
const q = `clientId=${encodeURIComponent(clientId)}${currentProfileQuerySuffix()}`;
|
const q = `clientId=${encodeURIComponent(clientId)}${currentProfileQuerySuffix()}`;
|
||||||
@@ -1576,7 +1586,7 @@ async function renameClient(c) {
|
|||||||
setStatus("Сохраняю имя…", false);
|
setStatus("Сохраняю имя…", false);
|
||||||
await api("/api/clients/rename", {
|
await api("/api/clients/rename", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify({ clientId: c.clientId, name: trimmed }),
|
body: JSON.stringify(withCurrentProfile({ clientId: c.clientId, name: trimmed })),
|
||||||
});
|
});
|
||||||
setStatus("Готово.", false);
|
setStatus("Готово.", false);
|
||||||
await loadClients();
|
await loadClients();
|
||||||
@@ -1588,7 +1598,7 @@ async function renameClient(c) {
|
|||||||
async function mutate(path, clientId) {
|
async function mutate(path, clientId) {
|
||||||
try {
|
try {
|
||||||
setStatus("Выполняю…", false);
|
setStatus("Выполняю…", false);
|
||||||
await api(path, { method: "POST", body: JSON.stringify({ clientId }) });
|
await api(path, { method: "POST", body: JSON.stringify(withCurrentProfile({ clientId })) });
|
||||||
setStatus("Готово.", false);
|
setStatus("Готово.", false);
|
||||||
await loadClients();
|
await loadClients();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -1607,7 +1617,7 @@ async function confirmDelete(name, clientId) {
|
|||||||
async function loadClients() {
|
async function loadClients() {
|
||||||
try {
|
try {
|
||||||
setStatus("Загрузка…", false);
|
setStatus("Загрузка…", false);
|
||||||
const data = await api("/api/clients");
|
const data = await api(`/api/clients${currentProfileQueryString()}`);
|
||||||
applyEditionPayload(data);
|
applyEditionPayload(data);
|
||||||
applyUiHiddenFromPayload(data);
|
applyUiHiddenFromPayload(data);
|
||||||
const pref = data.profileLabel ? `${data.profileLabel} · ` : "";
|
const pref = data.profileLabel ? `${data.profileLabel} · ` : "";
|
||||||
|
|||||||
12
server.js
12
server.js
@@ -2229,7 +2229,7 @@ app.post("/api/protocol", requireAuth, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.get("/api/clients", requireAuth, async (req, res) => {
|
app.get("/api/clients", requireAuth, async (req, res) => {
|
||||||
const rt = runtimeForRequest(req);
|
const rt = runtimeFromExportRequest(req);
|
||||||
try {
|
try {
|
||||||
let wgShow = "";
|
let wgShow = "";
|
||||||
try {
|
try {
|
||||||
@@ -2701,7 +2701,7 @@ app.post("/api/warp/routing", requireAuth, requireProTier, async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/clients/disable", requireAuth, requireProTier, async (req, res) => {
|
app.post("/api/clients/disable", requireAuth, requireProTier, async (req, res) => {
|
||||||
const rt = runtimeForRequest(req);
|
const rt = runtimeFromExportRequest(req);
|
||||||
const clientId = req.body?.clientId;
|
const clientId = req.body?.clientId;
|
||||||
if (!clientId) return res.status(400).json({ error: "clientId required" });
|
if (!clientId) return res.status(400).json({ error: "clientId required" });
|
||||||
let ts;
|
let ts;
|
||||||
@@ -2724,7 +2724,7 @@ app.post("/api/clients/disable", requireAuth, requireProTier, async (req, res) =
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/clients/enable", requireAuth, requireProTier, async (req, res) => {
|
app.post("/api/clients/enable", requireAuth, requireProTier, async (req, res) => {
|
||||||
const rt = runtimeForRequest(req);
|
const rt = runtimeFromExportRequest(req);
|
||||||
const clientId = req.body?.clientId;
|
const clientId = req.body?.clientId;
|
||||||
if (!clientId) return res.status(400).json({ error: "clientId required" });
|
if (!clientId) return res.status(400).json({ error: "clientId required" });
|
||||||
try {
|
try {
|
||||||
@@ -2774,7 +2774,7 @@ AllowedIPs = ${ips}`;
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/clients/disconnect-date", requireAuth, requireProTier, async (req, res) => {
|
app.post("/api/clients/disconnect-date", requireAuth, requireProTier, async (req, res) => {
|
||||||
const rt = runtimeForRequest(req);
|
const rt = runtimeFromExportRequest(req);
|
||||||
const clientId = req.body?.clientId;
|
const clientId = req.body?.clientId;
|
||||||
if (!clientId) return res.status(400).json({ error: "clientId required" });
|
if (!clientId) return res.status(400).json({ error: "clientId required" });
|
||||||
let iso;
|
let iso;
|
||||||
@@ -2814,7 +2814,7 @@ app.post("/api/clients/disconnect-date", requireAuth, requireProTier, async (req
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/clients/rename", requireAuth, requireProTier, async (req, res) => {
|
app.post("/api/clients/rename", requireAuth, requireProTier, async (req, res) => {
|
||||||
const rt = runtimeForRequest(req);
|
const rt = runtimeFromExportRequest(req);
|
||||||
const clientId = req.body?.clientId;
|
const clientId = req.body?.clientId;
|
||||||
const rawName = req.body?.name ?? req.body?.clientName;
|
const rawName = req.body?.name ?? req.body?.clientName;
|
||||||
if (!clientId) return res.status(400).json({ error: "clientId required" });
|
if (!clientId) return res.status(400).json({ error: "clientId required" });
|
||||||
@@ -2841,7 +2841,7 @@ app.post("/api/clients/rename", requireAuth, requireProTier, async (req, res) =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/clients/delete", requireAuth, requireProTier, async (req, res) => {
|
app.post("/api/clients/delete", requireAuth, requireProTier, async (req, res) => {
|
||||||
const rt = runtimeForRequest(req);
|
const rt = runtimeFromExportRequest(req);
|
||||||
const clientId = req.body?.clientId;
|
const clientId = req.body?.clientId;
|
||||||
if (!clientId) return res.status(400).json({ error: "clientId required" });
|
if (!clientId) return res.status(400).json({ error: "clientId required" });
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user