diff --git a/web/html/inbounds.html b/web/html/inbounds.html
index fda4aca2..397a510c 100644
--- a/web/html/inbounds.html
+++ b/web/html/inbounds.html
@@ -845,9 +845,9 @@
},
getClientCounts(dbInbound, inbound) {
let clientCount = 0, active = [], deactive = [], depleted = [], expiring = [], online = [], comments = new Map();
- clients = inbound.clients;
- clientStats = dbInbound.clientStats
- now = new Date().getTime()
+ const clients = inbound.clients;
+ const clientStats = dbInbound.clientStats;
+ const now = new Date().getTime();
if (clients) {
clientCount = clients.length;
if (dbInbound.enable) {
@@ -862,17 +862,19 @@
deactive.push(client.email);
}
});
- clientStats.forEach(stats => {
- const exhausted = stats.total > 0 && (stats.up + stats.down) >= stats.total;
- const expired = stats.expiryTime > 0 && stats.expiryTime <= now;
- if (expired || exhausted) {
- depleted.push(stats.email);
- } else {
- const expiringSoon = (stats.expiryTime > 0 && (stats.expiryTime - now < this.expireDiff)) ||
- (stats.total > 0 && (stats.total - (stats.up + stats.down) < this.trafficDiff));
- if (expiringSoon) expiring.push(stats.email);
- }
- });
+ if (Array.isArray(clientStats)) {
+ clientStats.forEach(stats => {
+ const exhausted = stats.total > 0 && (stats.up + stats.down) >= stats.total;
+ const expired = stats.expiryTime > 0 && stats.expiryTime <= now;
+ if (expired || exhausted) {
+ depleted.push(stats.email);
+ } else {
+ const expiringSoon = (stats.expiryTime > 0 && (stats.expiryTime - now < this.expireDiff)) ||
+ (stats.total > 0 && (stats.total - (stats.up + stats.down) < this.trafficDiff));
+ if (expiringSoon) expiring.push(stats.email);
+ }
+ });
+ }
} else {
clients.forEach(client => {
deactive.push(client.email);
@@ -1060,7 +1062,8 @@
});
},
openEditInbound(dbInboundId) {
- dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ if (!dbInbound) return;
const inbound = dbInbound.toInbound();
inModal.show({
title: '{{ i18n "pages.inbounds.modifyInbound"}}',
@@ -1127,7 +1130,8 @@
await this.submit(`/panel/api/inbounds/update/${dbInbound.id}`, data, inModal);
},
openAddClient(dbInboundId) {
- dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ if (!dbInbound) return;
clientModal.show({
title: '{{ i18n "pages.client.add"}}',
okText: '{{ i18n "pages.client.submitAdd"}}',
@@ -1139,7 +1143,8 @@
});
},
openAddBulkClient(dbInboundId) {
- dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ if (!dbInbound) return;
clientsBulkModal.show({
title: '{{ i18n "pages.client.bulk"}} ' + dbInbound.remark,
okText: '{{ i18n "pages.client.bulk"}}',
@@ -1150,11 +1155,11 @@
});
},
openEditClient(dbInboundId, client) {
- dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
if (!dbInbound) return;
- clients = this.getInboundClients(dbInbound);
+ const clients = this.getInboundClients(dbInbound);
if (!clients || !Array.isArray(clients)) return;
- index = this.findIndexOfClient(dbInbound.protocol, clients, client);
+ const index = this.findIndexOfClient(dbInbound.protocol, clients, client);
if (index < 0) return;
clientModal.show({
title: '{{ i18n "pages.client.edit"}}',
@@ -1195,7 +1200,8 @@
await this.submit(`/panel/api/inbounds/updateClient/${clientId}`, data, clientModal);
},
resetTraffic(dbInboundId) {
- dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ if (!dbInbound) return;
this.$confirm({
title: '{{ i18n "pages.inbounds.resetTraffic"}}' + ' #' + dbInboundId,
content: '{{ i18n "pages.inbounds.resetTrafficContent"}}',
@@ -1211,6 +1217,8 @@
});
},
delInbound(dbInboundId) {
+ const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ if (!dbInbound) return;
this.$confirm({
title: '{{ i18n "pages.inbounds.deleteInbound"}}' + ' #' + dbInboundId,
content: '{{ i18n "pages.inbounds.deleteInboundContent"}}',
@@ -1221,8 +1229,9 @@
});
},
delClient(dbInboundId, client, confirmation = true) {
- dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
- clientId = this.getClientId(dbInbound.protocol, client);
+ const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ if (!dbInbound) return;
+ const clientId = this.getClientId(dbInbound.protocol, client);
if (confirmation) {
this.$confirm({
title: '{{ i18n "pages.inbounds.deleteClient"}}' + ' ' + client.email,
@@ -1274,9 +1283,9 @@
}
},
checkFallback(dbInbound) {
- newDbInbound = new DBInbound(dbInbound);
+ const newDbInbound = new DBInbound(dbInbound);
if (dbInbound.listen.startsWith("@")) {
- rootInbound = this.inbounds.find((i) =>
+ const rootInbound = this.inbounds.find((i) =>
i.isTcp &&
['trojan', 'vless'].includes(i.protocol) &&
i.settings.fallbacks.find(f => f.dest === dbInbound.listen)
@@ -1294,43 +1303,48 @@
return newDbInbound;
},
showQrcode(dbInboundId, client) {
- dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
- newDbInbound = this.checkFallback(dbInbound);
+ const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ if (!dbInbound) return;
+ const newDbInbound = this.checkFallback(dbInbound);
qrModal.show('{{ i18n "qrCode"}}', newDbInbound, client);
},
showInfo(dbInboundId, client) {
- dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
if (!dbInbound) return;
- index = 0;
+ let index = 0;
if (dbInbound.isMultiUser()) {
- inbound = dbInbound.toInbound();
- clients = inbound && inbound.clients ? inbound.clients : null;
+ const inbound = dbInbound.toInbound();
+ const clients = inbound && inbound.clients ? inbound.clients : null;
if (clients && Array.isArray(clients)) {
index = this.findIndexOfClient(dbInbound.protocol, clients, client);
if (index < 0) index = 0;
}
}
- newDbInbound = this.checkFallback(dbInbound);
+ const newDbInbound = this.checkFallback(dbInbound);
infoModal.show(newDbInbound, index);
},
switchEnable(dbInboundId, state) {
- dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ if (!dbInbound) return;
dbInbound.enable = state;
this.submit(`/panel/api/inbounds/update/${dbInboundId}`, dbInbound);
},
async switchEnableClient(dbInboundId, client) {
- this.loading()
- dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
- if (!dbInbound) return;
- inbound = dbInbound.toInbound();
- clients = inbound && inbound.clients ? inbound.clients : null;
- if (!clients || !Array.isArray(clients)) return;
- index = this.findIndexOfClient(dbInbound.protocol, clients, client);
- if (index < 0 || !clients[index]) return;
- clients[index].enable = !clients[index].enable;
- clientId = this.getClientId(dbInbound.protocol, clients[index]);
- await this.updateClient(clients[index], dbInboundId, clientId);
- this.loading(false);
+ this.loading();
+ try {
+ const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ if (!dbInbound) return;
+ const inbound = dbInbound.toInbound();
+ const clients = inbound && inbound.clients ? inbound.clients : null;
+ if (!clients || !Array.isArray(clients)) return;
+ const index = this.findIndexOfClient(dbInbound.protocol, clients, client);
+ if (index < 0 || !clients[index]) return;
+ clients[index].enable = !clients[index].enable;
+ const clientId = this.getClientId(dbInbound.protocol, clients[index]);
+ await this.updateClient(clients[index], dbInboundId, clientId);
+ } finally {
+ this.loading(false);
+ }
},
async submit(url, data, modal) {
const msg = await HttpUtil.postWithModal(url, data, modal);
@@ -1489,15 +1503,18 @@
return new Date(ts).toLocaleString()
},
isRemovable(dbInboundId) {
- return this.getInboundClients(this.dbInbounds.find(row => row.id === dbInboundId)).length > 1;
+ const clients = this.getInboundClients(this.dbInbounds.find(row => row.id === dbInboundId));
+ return Array.isArray(clients) && clients.length > 1;
},
inboundLinks(dbInboundId) {
- dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
- newDbInbound = this.checkFallback(dbInbound);
+ const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ if (!dbInbound) return;
+ const newDbInbound = this.checkFallback(dbInbound);
txtModal.show('{{ i18n "pages.inbounds.export"}}', newDbInbound.genInboundLinks(this.remarkModel), newDbInbound.remark);
},
exportSubs(dbInboundId) {
const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ if (!dbInbound) return;
const clients = this.getInboundClients(dbInbound);
let subLinks = []
if (clients != null) {
@@ -1548,7 +1565,8 @@
txtModal.show('{{ i18n "pages.inbounds.export"}}', copyText.join('\r\n'), 'All-Inbounds');
},
copy(dbInboundId) {
- dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
+ if (!dbInbound) return;
txtModal.show('{{ i18n "pages.inbounds.inboundData" }}', JSON.stringify(dbInbound, null, 2));
},
async startDataRefreshLoop() {
@@ -1613,9 +1631,13 @@
this.getClientEmailOptions();
// Initial data fetch
- this.getDBInbounds().then(() => {
- this.loading(false);
- });
+ this.getDBInbounds()
+ .catch((e) => {
+ console.error(e);
+ })
+ .finally(() => {
+ this.loading(false);
+ });
// Setup WebSocket for real-time updates
if (window.wsClient) {
diff --git a/web/html/index.html b/web/html/index.html
index e442a022..4eb4077e 100644
--- a/web/html/index.html
+++ b/web/html/index.html
@@ -1018,23 +1018,29 @@
},
async openLogs() {
logModal.loading = true;
- const msg = await HttpUtil.post('/panel/api/server/logs/' + logModal.rows, { level: logModal.level, syslog: logModal.syslog });
- if (!msg.success) {
- return;
+ try {
+ const msg = await HttpUtil.post('/panel/api/server/logs/' + logModal.rows, { level: logModal.level, syslog: logModal.syslog });
+ if (!msg.success) {
+ return;
+ }
+ logModal.show(msg.obj);
+ await PromiseUtil.sleep(500);
+ } finally {
+ logModal.loading = false;
}
- logModal.show(msg.obj);
- await PromiseUtil.sleep(500);
- logModal.loading = false;
},
async openXrayLogs() {
xraylogModal.loading = true;
- const msg = await HttpUtil.post('/panel/api/server/xraylogs/' + xraylogModal.rows, { filter: xraylogModal.filter, showDirect: xraylogModal.showDirect, showBlocked: xraylogModal.showBlocked, showProxy: xraylogModal.showProxy });
- if (!msg.success) {
- return;
+ try {
+ const msg = await HttpUtil.post('/panel/api/server/xraylogs/' + xraylogModal.rows, { filter: xraylogModal.filter, showDirect: xraylogModal.showDirect, showBlocked: xraylogModal.showBlocked, showProxy: xraylogModal.showProxy });
+ if (!msg.success) {
+ return;
+ }
+ xraylogModal.show(msg.obj);
+ await PromiseUtil.sleep(500);
+ } finally {
+ xraylogModal.loading = false;
}
- xraylogModal.show(msg.obj);
- await PromiseUtil.sleep(500);
- xraylogModal.loading = false;
},
downloadXrayLogs() {
if (!Array.isArray(this.xraylogModal.logs) || this.xraylogModal.logs.length === 0) {
diff --git a/web/html/login.html b/web/html/login.html
index a4ceb831..9ef14cb5 100644
--- a/web/html/login.html
+++ b/web/html/login.html
@@ -167,10 +167,20 @@
},
async mounted() {
this.lang = LanguageManager.getLanguage();
- this.twoFactorEnable = await this.getTwoFactorEnable();
- this.turnstileSiteKey = await this.getTurnstileSiteKey();
- if (this.turnstileSiteKey) {
- this.$nextTick(() => this.ensureTurnstileRendered());
+ try {
+ this.twoFactorEnable = await this.getTwoFactorEnable();
+ this.turnstileSiteKey = await this.getTurnstileSiteKey();
+ } finally {
+ this.loadingStates.fetched = true;
+ this.$nextTick(() => {
+ if (!this.animationStarted) {
+ this.animationStarted = true;
+ this.initHeadline();
+ }
+ if (this.turnstileSiteKey) {
+ this.ensureTurnstileRendered();
+ }
+ });
}
},
computed: {
@@ -248,15 +258,9 @@
const msg = await HttpUtil.post('/getTwoFactorEnable');
if (msg.success) {
this.twoFactorEnable = msg.obj;
- this.loadingStates.fetched = true;
- this.$nextTick(() => {
- if (!this.animationStarted) {
- this.animationStarted = true;
- this.initHeadline();
- }
- });
return msg.obj;
}
+ return false;
},
initHeadline() {
const animationDelay = 2000;
diff --git a/web/html/modals/client_bulk_modal.html b/web/html/modals/client_bulk_modal.html
index ac0fa011..1726771c 100644
--- a/web/html/modals/client_bulk_modal.html
+++ b/web/html/modals/client_bulk_modal.html
@@ -150,8 +150,13 @@
delayedStart: false,
reset: 0,
ok() {
- clients = [];
- method = clientsBulkModal.emailMethod;
+ const clients = [];
+ const method = clientsBulkModal.emailMethod;
+ let start;
+ let end;
+ let prefix;
+ let useNum;
+ let postfix;
if (method > 1) {
start = clientsBulkModal.firstNum;
end = clientsBulkModal.lastNum + 1;
@@ -163,7 +168,7 @@
useNum = (method > 1);
postfix = (method > 2 && clientsBulkModal.emailPostfix.length > 0) ? clientsBulkModal.emailPostfix : "";
for (let i = start; i < end; i++) {
- newClient = clientsBulkModal.newClient(clientsBulkModal.dbInbound.protocol);
+ const newClient = clientsBulkModal.newClient(clientsBulkModal.dbInbound.protocol);
if (method == 4) newClient.email = "";
newClient.email += useNum ? prefix + i.toString() + postfix : prefix + postfix;
if (clientsBulkModal.subId.length > 0) newClient.subId = clientsBulkModal.subId;
@@ -186,6 +191,9 @@
dbInbound = null,
confirm = (inbound, dbInbound) => { }
}) {
+ if (!dbInbound) {
+ return;
+ }
this.visible = true;
this.title = title;
this.okText = okText;
@@ -213,7 +221,10 @@
case Protocols.VMESS: return new Inbound.VmessSettings.VMESS();
case Protocols.VLESS: return new Inbound.VLESSSettings.VLESS();
case Protocols.TROJAN: return new Inbound.TrojanSettings.Trojan();
- case Protocols.SHADOWSOCKS: return new Inbound.ShadowsocksSettings.Shadowsocks(clientsBulkModal.inbound.settings.shadowsockses[0].method);
+ case Protocols.SHADOWSOCKS: {
+ const method = clientsBulkModal.inbound?.settings?.method || '';
+ return new Inbound.ShadowsocksSettings.Shadowsocks(method, RandomUtil.randomShadowsocksPassword(method));
+ }
default: return null;
}
},
@@ -247,4 +258,4 @@
});
-{{end}}
\ No newline at end of file
+{{end}}
diff --git a/web/html/modals/client_modal.html b/web/html/modals/client_modal.html
index 27364d96..b9a58d1e 100644
--- a/web/html/modals/client_modal.html
+++ b/web/html/modals/client_modal.html
@@ -32,6 +32,9 @@
}
},
show({ title = '', okText = '{{ i18n "sure" }}', index = null, dbInbound = null, confirm = () => { }, isEdit = false }) {
+ if (!dbInbound) {
+ return;
+ }
this.visible = true;
this.title = title;
this.okText = okText;
@@ -42,14 +45,22 @@
this.index = index === null ? this.clients.length : index;
this.delayedStart = false;
if (isEdit) {
- if (this.clients[index].expiryTime < 0) {
+ const currentClient = this.clients[index];
+ if (!currentClient) {
+ this.visible = false;
+ return;
+ }
+ if (currentClient.expiryTime < 0) {
this.delayedStart = true;
}
- this.oldClientId = this.getClientId(dbInbound.protocol, clients[index]);
+ this.oldClientId = this.getClientId(dbInbound.protocol, currentClient);
} else {
this.addClient(this.inbound, this.clients);
}
- this.clientStats = this.dbInbound.clientStats.find(row => row.email === this.clients[this.index].email);
+ const activeClient = this.clients[this.index];
+ this.clientStats = Array.isArray(this.dbInbound.clientStats)
+ ? this.dbInbound.clientStats.find(row => row.email === activeClient?.email)
+ : null;
this.confirm = confirm;
},
getClientId(protocol, client) {
@@ -64,7 +75,7 @@
case Protocols.VMESS: return clients.push(new Inbound.VmessSettings.VMESS());
case Protocols.VLESS: return clients.push(new Inbound.VLESSSettings.VLESS());
case Protocols.TROJAN: return clients.push(new Inbound.TrojanSettings.Trojan());
- case Protocols.SHADOWSOCKS: return clients.push(new Inbound.ShadowsocksSettings.Shadowsocks(clients[0].method, RandomUtil.randomShadowsocksPassword(inbound.settings.method)));
+ case Protocols.SHADOWSOCKS: return clients.push(new Inbound.ShadowsocksSettings.Shadowsocks(inbound.settings.method, RandomUtil.randomShadowsocksPassword(inbound.settings.method)));
default: return null;
}
},
diff --git a/web/html/modals/warp_modal.html b/web/html/modals/warp_modal.html
index 4bfb7ca1..8d9d7a0b 100644
--- a/web/html/modals/warp_modal.html
+++ b/web/html/modals/warp_modal.html
@@ -131,26 +131,27 @@
},
methods: {
collectConfig() {
- config = warpModal.warpConfig.config;
- peer = config.peers[0];
- if (config) {
- warpModal.warpOutbound = Outbound.fromJson({
- tag: 'warp',
- protocol: Protocols.Wireguard,
- settings: {
- mtu: 1420,
- secretKey: warpModal.warpData.private_key,
- address: this.getAddresses(config.interface.addresses),
- reserved: this.getResolved(config.client_id),
- domainStrategy: 'ForceIP',
- peers: [{
- publicKey: peer.public_key,
- endpoint: peer.endpoint.host,
- }],
- noKernelTun: false,
- }
- });
+ const config = warpModal.warpConfig?.config;
+ if (!config || !Array.isArray(config.peers) || config.peers.length === 0) {
+ return;
}
+ const peer = config.peers[0];
+ warpModal.warpOutbound = Outbound.fromJson({
+ tag: 'warp',
+ protocol: Protocols.Wireguard,
+ settings: {
+ mtu: 1420,
+ secretKey: warpModal.warpData.private_key,
+ address: this.getAddresses(config.interface.addresses),
+ reserved: this.getResolved(config.client_id),
+ domainStrategy: 'ForceIP',
+ peers: [{
+ publicKey: peer.public_key,
+ endpoint: peer.endpoint.host,
+ }],
+ noKernelTun: false,
+ }
+ });
},
getAddresses(addrs) {
let addresses = [];
@@ -243,4 +244,4 @@
});
-{{end}}
\ No newline at end of file
+{{end}}
diff --git a/web/html/modals/xray_outbound_modal.html b/web/html/modals/xray_outbound_modal.html
index 2edb5fc0..ce70bc6d 100644
--- a/web/html/modals/xray_outbound_modal.html
+++ b/web/html/modals/xray_outbound_modal.html
@@ -55,7 +55,7 @@
}
},
toggleJson(jsonTab) {
- textAreaObj = document.getElementById('outboundJson');
+ const textAreaObj = document.getElementById('outboundJson');
if(jsonTab){
if(this.cm != null) {
this.cm.toTextArea();
@@ -64,7 +64,7 @@
textAreaObj.value = JSON.stringify(this.outbound.toJson(), null, 2);
this.cm = CodeMirror.fromTextArea(textAreaObj, app.cmOptions);
this.cm.on('change',editor => {
- value = editor.getValue();
+ const value = editor.getValue();
if(this.isJsonString(value)){
this.outbound = Outbound.fromJson(JSON.parse(value));
this.check();
@@ -107,11 +107,11 @@
canEnableTls() {
return this.outModal.outbound.canEnableTls();
},
- convertLink(){
- newOutbound = Outbound.fromLink(outModal.link);
- if(newOutbound){
- this.outModal.outbound = newOutbound;
- this.outModal.toggleJson(true);
+ convertLink(){
+ const newOutbound = Outbound.fromLink(outModal.link);
+ if(newOutbound){
+ this.outModal.outbound = newOutbound;
+ this.outModal.toggleJson(true);
this.outModal.check();
this.$message.success('Link imported successfully...');
outModal.link = '';
diff --git a/web/html/settings.html b/web/html/settings.html
index 21294da7..fd86657c 100644
--- a/web/html/settings.html
+++ b/web/html/settings.html
@@ -626,8 +626,12 @@
this.entryPort = window.location.port;
this.entryProtocol = window.location.protocol;
this.entryIsIP = this._isIp(this.entryHost);
- await this.getAllSetting();
- await this.loadInboundTags();
+ try {
+ await this.getAllSetting();
+ await this.loadInboundTags();
+ } finally {
+ this.loadingStates.fetched = true;
+ }
while (true) {
await PromiseUtil.sleep(1000);
this.saveBtnDisable = this.oldAllSetting.equals(this.allSetting);
@@ -635,4 +639,4 @@
}
});
-{{ template "page/body_end" .}}
\ No newline at end of file
+{{ template "page/body_end" .}}
diff --git a/web/html/xray.html b/web/html/xray.html
index ebe31f48..5a04910b 100644
--- a/web/html/xray.html
+++ b/web/html/xray.html
@@ -398,8 +398,8 @@
this.loadingStates.fetched = true
}
- result = JSON.parse(msg.obj);
- xs = JSON.stringify(result.xraySetting, null, 2);
+ const result = JSON.parse(msg.obj);
+ const xs = JSON.stringify(result.xraySetting, null, 2);
this.oldXraySetting = xs;
this.xraySetting = xs;
this.inboundTags = result.inboundTags;
@@ -1063,9 +1063,13 @@
if (window.location.protocol !== "https:") {
this.showAlert = true;
}
- await this.getXraySetting();
- await this.getXrayResult();
- await this.getOutboundsTraffic();
+ try {
+ await this.getXraySetting();
+ await this.getXrayResult();
+ await this.getOutboundsTraffic();
+ } finally {
+ this.loadingStates.fetched = true;
+ }
if (window.wsClient) {
window.wsClient.connect();
@@ -1562,4 +1566,4 @@
},
});
-{{ template "page/body_end" .}}
\ No newline at end of file
+{{ template "page/body_end" .}}