diff options
Diffstat (limited to 'web')
| -rw-r--r-- | web/assets/js/model/dbinbound.js | 4 | ||||
| -rw-r--r-- | web/assets/js/model/inbound.js | 551 | ||||
| -rw-r--r-- | web/assets/js/model/outbound.js | 4 | ||||
| -rw-r--r-- | web/html/component/aClientTable.html | 4 | ||||
| -rw-r--r-- | web/html/form/client.html | 112 | ||||
| -rw-r--r-- | web/html/form/inbound.html | 8 | ||||
| -rw-r--r-- | web/html/form/protocol/hysteria.html | 32 | ||||
| -rw-r--r-- | web/html/form/stream/stream_hysteria.html | 75 | ||||
| -rw-r--r-- | web/html/form/stream/stream_settings.html | 8 | ||||
| -rw-r--r-- | web/html/form/tls_settings.html | 21 | ||||
| -rw-r--r-- | web/html/inbounds.html | 483 | ||||
| -rw-r--r-- | web/html/modals/client_bulk_modal.html | 104 | ||||
| -rw-r--r-- | web/html/modals/client_modal.html | 16 | ||||
| -rw-r--r-- | web/service/inbound.go | 22 | ||||
| -rw-r--r-- | web/service/xray.go | 4 |
15 files changed, 950 insertions, 498 deletions
diff --git a/web/assets/js/model/dbinbound.js b/web/assets/js/model/dbinbound.js index c347a7eb..e1802635 100644 --- a/web/assets/js/model/dbinbound.js +++ b/web/assets/js/model/dbinbound.js @@ -125,7 +125,7 @@ class DBInbound { sniffing: sniffing, clientStats: this.clientStats, }; - + this._cachedInbound = Inbound.fromJson(config); return this._cachedInbound; } @@ -147,6 +147,7 @@ class DBInbound { case Protocols.VMESS: case Protocols.VLESS: case Protocols.TROJAN: + case Protocols.HYSTERIA: return true; case Protocols.SHADOWSOCKS: return this.toInbound().isSSMultiUser; @@ -161,6 +162,7 @@ class DBInbound { case Protocols.VLESS: case Protocols.TROJAN: case Protocols.SHADOWSOCKS: + case Protocols.HYSTERIA: return true; default: return false; diff --git a/web/assets/js/model/inbound.js b/web/assets/js/model/inbound.js index b6059cf7..f74b2736 100644 --- a/web/assets/js/model/inbound.js +++ b/web/assets/js/model/inbound.js @@ -8,6 +8,7 @@ const Protocols = { HTTP: 'http', WIREGUARD: 'wireguard', TUN: 'tun', + HYSTERIA: 'hysteria', }; const SSMethods = { @@ -589,6 +590,106 @@ class xHTTPStreamSettings extends XrayCommonClass { } } +class HysteriaStreamSettings extends XrayCommonClass { + constructor( + protocol, + version = 2, + auth = '', + udpIdleTimeout = 60, + masquerade, + ) { + super(protocol); + this.version = version; + this.auth = auth; + this.udpIdleTimeout = udpIdleTimeout; + this.masquerade = masquerade; + } + + static fromJson(json = {}) { + return new HysteriaStreamSettings( + json.protocol, + json.version ?? 2, + json.auth ?? '', + json.udpIdleTimeout ?? 60, + json.masquerade ? HysteriaMasquerade.fromJson(json.masquerade) : undefined, + ); + } + + toJson() { + return { + protocol: this.protocol, + version: this.version, + auth: this.auth, + udpIdleTimeout: this.udpIdleTimeout, + masquerade: this.masqueradeSwitch ? this.masquerade.toJson() : undefined, + }; + } + + get masqueradeSwitch() { + return this.masquerade != undefined; + } + + set masqueradeSwitch(value) { + this.masquerade = value ? new HysteriaMasquerade() : undefined; + } +}; + +class HysteriaMasquerade extends XrayCommonClass { + constructor( + type = 'proxy', + dir = '', + url = '', + rewriteHost = false, + insecure = false, + content = '', + headers = [], + statusCode = 0, + ) { + super(); + this.type = type; + this.dir = dir; + this.url = url; + this.rewriteHost = rewriteHost; + this.insecure = insecure; + this.content = content; + this.headers = headers; + this.statusCode = statusCode; + } + + addHeader(name, value) { + this.headers.push({ name: name, value: value }); + } + + removeHeader(index) { + this.headers.splice(index, 1); + } + + static fromJson(json = {}) { + return new HysteriaMasquerade( + json.type, + json.dir, + json.url, + json.rewriteHost, + json.insecure, + json.content, + XrayCommonClass.toHeaders(json.headers), + json.statusCode, + ); + } + + toJson() { + return { + type: this.type, + dir: this.dir, + url: this.url, + rewriteHost: this.rewriteHost, + insecure: this.insecure, + content: this.content, + headers: XrayCommonClass.toV2Headers(this.headers, false), + statusCode: this.statusCode, + }; + } +}; class TlsStreamSettings extends XrayCommonClass { constructor( serverName = '', @@ -987,6 +1088,12 @@ class UdpMask extends XrayCommonClass { case 'header-wechat': case 'header-wireguard': return {}; + case 'header-custom': + return { client: [], server: [] }; + case 'noise': + return { reset: 0, noise: [] }; + case 'sudoku': + return { ascii: '', customTable: '', customTables: [], paddingMin: 0, paddingMax: 0 }; default: return settings; } @@ -1021,7 +1128,6 @@ class FinalMaskStreamSettings extends XrayCommonClass { return { udp: this.udp.map(udp => udp.toJson()) }; - } } @@ -1037,6 +1143,7 @@ class StreamSettings extends XrayCommonClass { grpcSettings = new GrpcStreamSettings(), httpupgradeSettings = new HTTPUpgradeStreamSettings(), xhttpSettings = new xHTTPStreamSettings(), + hysteriaSettings = new HysteriaStreamSettings(), finalmask = new FinalMaskStreamSettings(), sockopt = undefined, ) { @@ -1052,6 +1159,7 @@ class StreamSettings extends XrayCommonClass { this.grpc = grpcSettings; this.httpupgrade = httpupgradeSettings; this.xhttp = xhttpSettings; + this.hysteria = hysteriaSettings; this.finalmask = finalmask; this.sockopt = sockopt; } @@ -1116,6 +1224,7 @@ class StreamSettings extends XrayCommonClass { GrpcStreamSettings.fromJson(json.grpcSettings), HTTPUpgradeStreamSettings.fromJson(json.httpupgradeSettings), xHTTPStreamSettings.fromJson(json.xhttpSettings), + HysteriaStreamSettings.fromJson(json.hysteriaSettings), FinalMaskStreamSettings.fromJson(json.finalmask), SockoptStreamSettings.fromJson(json.sockopt), ); @@ -1135,6 +1244,7 @@ class StreamSettings extends XrayCommonClass { grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined, httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined, xhttpSettings: network === 'xhttp' ? this.xhttp.toJson() : undefined, + hysteriaSettings: network === 'hysteria' ? this.hysteria.toJson() : undefined, finalmask: this.hasFinalMask ? this.finalmask.toJson() : undefined, sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined, }; @@ -1201,6 +1311,7 @@ class Inbound extends XrayCommonClass { case Protocols.VLESS: return this.settings.vlesses; case Protocols.TROJAN: return this.settings.trojans; case Protocols.SHADOWSOCKS: return this.isSSMultiUser ? this.settings.shadowsockses : null; + case Protocols.HYSTERIA: return this.settings.hysterias; default: return null; } } @@ -1212,9 +1323,14 @@ class Inbound extends XrayCommonClass { set protocol(protocol) { this._protocol = protocol; this.settings = Inbound.Settings.getSettings(protocol); + this.stream = new StreamSettings(); if (protocol === Protocols.TROJAN) { this.tls = false; } + if (protocol === Protocols.HYSTERIA) { + this.stream.network = 'hysteria'; + this.stream.security = 'tls'; + } } get network() { @@ -1316,6 +1432,7 @@ class Inbound extends XrayCommonClass { } canEnableTls() { + if (this.protocol === Protocols.HYSTERIA) return true; if (![Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(this.protocol)) return false; return ["tcp", "ws", "http", "grpc", "httpupgrade", "xhttp"].includes(this.network); } @@ -1342,7 +1459,7 @@ class Inbound extends XrayCommonClass { } canEnableStream() { - return [Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(this.protocol); + return [Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS, Protocols.HYSTERIA].includes(this.protocol); } reset() { @@ -1689,6 +1806,26 @@ class Inbound extends XrayCommonClass { return url.toString(); } + genHysteriaLink(address = '', port = this.port, remark = '', clientAuth) { + const protocol = this.settings.version == 2 ? "hysteria2" : "hysteria"; + const link = `${protocol}://${clientAuth}@${address}:${port}`; + + const params = new Map(); + params.set("security", "tls"); + if (this.stream.tls.settings.fingerprint?.length > 0) params.set("fp", this.stream.tls.settings.fingerprint); + if (this.stream.tls.alpn?.length > 0) params.set("alpn", this.stream.tls.alpn); + if (this.stream.tls.settings.allowInsecure) params.set("insecure", "1"); + if (this.stream.tls.settings.echConfigList?.length > 0) params.set("ech", this.stream.tls.settings.echConfigList.join(',')); + if (this.stream.tls.sni?.length > 0) params.set("sni", this.stream.tls.sni); + + const url = new URL(link); + for (const [key, value] of params) { + url.searchParams.set(key, value); + } + url.hash = encodeURIComponent(remark); + return url.toString(); + } + getWireguardLink(address, port, remark, peerId) { let txt = `[Interface]\n` txt += `PrivateKey = ${this.settings.peers[peerId].privateKey}\n` @@ -1721,6 +1858,8 @@ class Inbound extends XrayCommonClass { return this.genSSLink(address, port, forceTls, remark, this.isSSMultiUser ? client.password : ''); case Protocols.TROJAN: return this.genTrojanLink(address, port, forceTls, remark, client.password); + case Protocols.HYSTERIA: + return this.genHysteriaLink(address, port, remark, client.auth.length > 0 ? client.auth : this.stream.hysteria.auth); default: return ''; } } @@ -1827,6 +1966,7 @@ Inbound.Settings = class extends XrayCommonClass { case Protocols.HTTP: return new Inbound.HttpSettings(protocol); case Protocols.WIREGUARD: return new Inbound.WireguardSettings(protocol); case Protocols.TUN: return new Inbound.TunSettings(protocol); + case Protocols.HYSTERIA: return new Inbound.HysteriaSettings(protocol); default: return null; } } @@ -1842,6 +1982,7 @@ Inbound.Settings = class extends XrayCommonClass { case Protocols.HTTP: return Inbound.HttpSettings.fromJson(json); case Protocols.WIREGUARD: return Inbound.WireguardSettings.fromJson(json); case Protocols.TUN: return Inbound.TunSettings.fromJson(json); + case Protocols.HYSTERIA: return Inbound.HysteriaSettings.fromJson(json); default: return null; } } @@ -1851,49 +1992,9 @@ Inbound.Settings = class extends XrayCommonClass { } }; -Inbound.VmessSettings = class extends Inbound.Settings { - constructor(protocol, - vmesses = [new Inbound.VmessSettings.VMESS()]) { - super(protocol); - this.vmesses = vmesses; - } - - indexOfVmessById(id) { - return this.vmesses.findIndex(VMESS => VMESS.id === id); - } - - addVmess(VMESS) { - if (this.indexOfVmessById(VMESS.id) >= 0) { - return false; - } - this.vmesses.push(VMESS); - } - - delVmess(VMESS) { - const i = this.indexOfVmessById(VMESS.id); - if (i >= 0) { - this.vmesses.splice(i, 1); - } - } - - static fromJson(json = {}) { - return new Inbound.VmessSettings( - Protocols.VMESS, - json.clients.map(client => Inbound.VmessSettings.VMESS.fromJson(client)), - ); - } - - toJson() { - return { - clients: Inbound.VmessSettings.toJsonArray(this.vmesses), - }; - } -}; - -Inbound.VmessSettings.VMESS = class extends XrayCommonClass { +/** Shared user-quota fields and UI helpers for multi-user protocol clients. */ +Inbound.ClientBase = class extends XrayCommonClass { constructor( - id = RandomUtil.randomUUID(), - security = USERS_SECURITY.AUTO, email = RandomUtil.randomLowerAndNum(8), limitIp = 0, totalGB = 0, @@ -1904,11 +2005,9 @@ Inbound.VmessSettings.VMESS = class extends XrayCommonClass { comment = '', reset = 0, created_at = undefined, - updated_at = undefined + updated_at = undefined, ) { super(); - this.id = id; - this.security = security; this.email = email; this.limitIp = limitIp; this.totalGB = totalGB; @@ -1922,10 +2021,8 @@ Inbound.VmessSettings.VMESS = class extends XrayCommonClass { this.updated_at = updated_at; } - static fromJson(json = {}) { - return new Inbound.VmessSettings.VMESS( - json.id, - json.security, + static commonArgsFromJson(json = {}) { + return [ json.email, json.limitIp, json.totalGB, @@ -1937,10 +2034,27 @@ Inbound.VmessSettings.VMESS = class extends XrayCommonClass { json.reset, json.created_at, json.updated_at, - ); + ]; } + + _clientBaseToJson() { + return { + email: this.email, + limitIp: this.limitIp, + totalGB: this.totalGB, + expiryTime: this.expiryTime, + enable: this.enable, + tgId: this.tgId, + subId: this.subId, + comment: this.comment, + reset: this.reset, + created_at: this.created_at, + updated_at: this.updated_at, + }; + } + get _expiryTime() { - if (this.expiryTime === 0 || this.expiryTime === "") { + if (this.expiryTime === 0 || this.expiryTime === '') { return null; } if (this.expiryTime < 0) { @@ -1950,12 +2064,13 @@ Inbound.VmessSettings.VMESS = class extends XrayCommonClass { } set _expiryTime(t) { - if (t == null || t === "") { + if (t == null || t === '') { this.expiryTime = 0; } else { this.expiryTime = t.valueOf(); } } + get _totalGB() { return NumberFormatter.toFixed(this.totalGB / SizeFormatter.ONE_GB, 2); } @@ -1963,7 +2078,73 @@ Inbound.VmessSettings.VMESS = class extends XrayCommonClass { set _totalGB(gb) { this.totalGB = NumberFormatter.toFixed(gb * SizeFormatter.ONE_GB, 0); } +}; +Inbound.VmessSettings = class extends Inbound.Settings { + constructor(protocol, + vmesses = [new Inbound.VmessSettings.VMESS()]) { + super(protocol); + this.vmesses = vmesses; + } + + indexOfVmessById(id) { + return this.vmesses.findIndex(VMESS => VMESS.id === id); + } + + addVmess(VMESS) { + if (this.indexOfVmessById(VMESS.id) >= 0) { + return false; + } + this.vmesses.push(VMESS); + } + + delVmess(VMESS) { + const i = this.indexOfVmessById(VMESS.id); + if (i >= 0) { + this.vmesses.splice(i, 1); + } + } + + static fromJson(json = {}) { + return new Inbound.VmessSettings( + Protocols.VMESS, + (json.clients || []).map(client => Inbound.VmessSettings.VMESS.fromJson(client)), + ); + } + + toJson() { + return { + clients: Inbound.VmessSettings.toJsonArray(this.vmesses), + }; + } +}; + +Inbound.VmessSettings.VMESS = class extends Inbound.ClientBase { + constructor( + id = RandomUtil.randomUUID(), + security = USERS_SECURITY.AUTO, + email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at, + ) { + super(email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at); + this.id = id; + this.security = security; + } + + static fromJson(json = {}) { + return new Inbound.VmessSettings.VMESS( + json.id, + json.security, + ...Inbound.ClientBase.commonArgsFromJson(json), + ); + } + + toJson() { + return { + id: this.id, + security: this.security, + ...this._clientBaseToJson(), + }; + } }; Inbound.VLESSSettings = class extends Inbound.Settings { @@ -2041,85 +2222,36 @@ Inbound.VLESSSettings = class extends Inbound.Settings { return json; } - - }; -Inbound.VLESSSettings.VLESS = class extends XrayCommonClass { +Inbound.VLESSSettings.VLESS = class extends Inbound.ClientBase { constructor( id = RandomUtil.randomUUID(), flow = '', - email = RandomUtil.randomLowerAndNum(8), - limitIp = 0, - totalGB = 0, - expiryTime = 0, - enable = true, - tgId = '', - subId = RandomUtil.randomLowerAndNum(16), - comment = '', - reset = 0, - created_at = undefined, - updated_at = undefined + email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at, ) { - super(); + super(email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at); this.id = id; this.flow = flow; - this.email = email; - this.limitIp = limitIp; - this.totalGB = totalGB; - this.expiryTime = expiryTime; - this.enable = enable; - this.tgId = tgId; - this.subId = subId; - this.comment = comment; - this.reset = reset; - this.created_at = created_at; - this.updated_at = updated_at; } static fromJson(json = {}) { return new Inbound.VLESSSettings.VLESS( json.id, json.flow, - json.email, - json.limitIp, - json.totalGB, - json.expiryTime, - json.enable, - json.tgId, - json.subId, - json.comment, - json.reset, - json.created_at, - json.updated_at, + ...Inbound.ClientBase.commonArgsFromJson(json), ); } - get _expiryTime() { - if (this.expiryTime === 0 || this.expiryTime === "") { - return null; - } - if (this.expiryTime < 0) { - return this.expiryTime / -86400000; - } - return moment(this.expiryTime); - } - - set _expiryTime(t) { - if (t == null || t === "") { - this.expiryTime = 0; - } else { - this.expiryTime = t.valueOf(); - } - } - get _totalGB() { - return NumberFormatter.toFixed(this.totalGB / SizeFormatter.ONE_GB, 2); - } - - set _totalGB(gb) { - this.totalGB = NumberFormatter.toFixed(gb * SizeFormatter.ONE_GB, 0); + toJson() { + return { + id: this.id, + flow: this.flow, + ...this._clientBaseToJson(), + }; } }; + Inbound.VLESSSettings.Fallback = class extends XrayCommonClass { constructor(name = "", alpn = '', path = '', dest = '', xver = 0) { super(); @@ -2179,7 +2311,7 @@ Inbound.TrojanSettings = class extends Inbound.Settings { static fromJson(json = {}) { return new Inbound.TrojanSettings( Protocols.TROJAN, - json.clients.map(client => Inbound.TrojanSettings.Trojan.fromJson(client)), + (json.clients || []).map(client => Inbound.TrojanSettings.Trojan.fromJson(client)), Inbound.TrojanSettings.Fallback.fromJson(json.fallbacks),); } @@ -2191,95 +2323,28 @@ Inbound.TrojanSettings = class extends Inbound.Settings { } }; -Inbound.TrojanSettings.Trojan = class extends XrayCommonClass { +Inbound.TrojanSettings.Trojan = class extends Inbound.ClientBase { constructor( password = RandomUtil.randomSeq(10), - email = RandomUtil.randomLowerAndNum(8), - limitIp = 0, - totalGB = 0, - expiryTime = 0, - enable = true, - tgId = '', - subId = RandomUtil.randomLowerAndNum(16), - comment = '', - reset = 0, - created_at = undefined, - updated_at = undefined + email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at, ) { - super(); + super(email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at); this.password = password; - this.email = email; - this.limitIp = limitIp; - this.totalGB = totalGB; - this.expiryTime = expiryTime; - this.enable = enable; - this.tgId = tgId; - this.subId = subId; - this.comment = comment; - this.reset = reset; - this.created_at = created_at; - this.updated_at = updated_at; } toJson() { return { password: this.password, - email: this.email, - limitIp: this.limitIp, - totalGB: this.totalGB, - expiryTime: this.expiryTime, - enable: this.enable, - tgId: this.tgId, - subId: this.subId, - comment: this.comment, - reset: this.reset, - created_at: this.created_at, - updated_at: this.updated_at, + ...this._clientBaseToJson(), }; } static fromJson(json = {}) { return new Inbound.TrojanSettings.Trojan( json.password, - json.email, - json.limitIp, - json.totalGB, - json.expiryTime, - json.enable, - json.tgId, - json.subId, - json.comment, - json.reset, - json.created_at, - json.updated_at, + ...Inbound.ClientBase.commonArgsFromJson(json), ); } - - get _expiryTime() { - if (this.expiryTime === 0 || this.expiryTime === "") { - return null; - } - if (this.expiryTime < 0) { - return this.expiryTime / -86400000; - } - return moment(this.expiryTime); - } - - set _expiryTime(t) { - if (t == null || t === "") { - this.expiryTime = 0; - } else { - this.expiryTime = t.valueOf(); - } - } - get _totalGB() { - return NumberFormatter.toFixed(this.totalGB / SizeFormatter.ONE_GB, 2); - } - - set _totalGB(gb) { - this.totalGB = NumberFormatter.toFixed(gb * SizeFormatter.ONE_GB, 0); - } - }; Inbound.TrojanSettings.Fallback = class extends XrayCommonClass { @@ -2343,7 +2408,7 @@ Inbound.ShadowsocksSettings = class extends Inbound.Settings { json.method, json.password, json.network, - json.clients.map(client => Inbound.ShadowsocksSettings.Shadowsocks.fromJson(client)), + (json.clients || []).map(client => Inbound.ShadowsocksSettings.Shadowsocks.fromJson(client)), json.ivCheck, ); } @@ -2359,53 +2424,22 @@ Inbound.ShadowsocksSettings = class extends Inbound.Settings { } }; -Inbound.ShadowsocksSettings.Shadowsocks = class extends XrayCommonClass { +Inbound.ShadowsocksSettings.Shadowsocks = class extends Inbound.ClientBase { constructor( method = '', password = RandomUtil.randomShadowsocksPassword(), - email = RandomUtil.randomLowerAndNum(8), - limitIp = 0, - totalGB = 0, - expiryTime = 0, - enable = true, - tgId = '', - subId = RandomUtil.randomLowerAndNum(16), - comment = '', - reset = 0, - created_at = undefined, - updated_at = undefined + email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at, ) { - super(); + super(email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at); this.method = method; this.password = password; - this.email = email; - this.limitIp = limitIp; - this.totalGB = totalGB; - this.expiryTime = expiryTime; - this.enable = enable; - this.tgId = tgId; - this.subId = subId; - this.comment = comment; - this.reset = reset; - this.created_at = created_at; - this.updated_at = updated_at; } toJson() { return { method: this.method, password: this.password, - email: this.email, - limitIp: this.limitIp, - totalGB: this.totalGB, - expiryTime: this.expiryTime, - enable: this.enable, - tgId: this.tgId, - subId: this.subId, - comment: this.comment, - reset: this.reset, - created_at: this.created_at, - updated_at: this.updated_at, + ...this._clientBaseToJson(), }; } @@ -2413,45 +2447,56 @@ Inbound.ShadowsocksSettings.Shadowsocks = class extends XrayCommonClass { return new Inbound.ShadowsocksSettings.Shadowsocks( json.method, json.password, - json.email, - json.limitIp, - json.totalGB, - json.expiryTime, - json.enable, - json.tgId, - json.subId, - json.comment, - json.reset, - json.created_at, - json.updated_at, + ...Inbound.ClientBase.commonArgsFromJson(json), ); } +}; - get _expiryTime() { - if (this.expiryTime === 0 || this.expiryTime === "") { - return null; - } - if (this.expiryTime < 0) { - return this.expiryTime / -86400000; - } - return moment(this.expiryTime); +Inbound.HysteriaSettings = class extends Inbound.Settings { + constructor(protocol, version = 2, hysterias = [new Inbound.HysteriaSettings.Hysteria()]) { + super(protocol); + this.version = version; + this.hysterias = hysterias; } - set _expiryTime(t) { - if (t == null || t === "") { - this.expiryTime = 0; - } else { - this.expiryTime = t.valueOf(); - } + static fromJson(json = {}) { + return new Inbound.HysteriaSettings( + Protocols.HYSTERIA, + json.version ?? 2, + (json.clients || []).map(client => Inbound.HysteriaSettings.Hysteria.fromJson(client)), + ); } - get _totalGB() { - return NumberFormatter.toFixed(this.totalGB / SizeFormatter.ONE_GB, 2); + + toJson() { + return { + version: this.version, + clients: Inbound.HysteriaSettings.toJsonArray(this.hysterias), + }; } +}; - set _totalGB(gb) { - this.totalGB = NumberFormatter.toFixed(gb * SizeFormatter.ONE_GB, 0); +Inbound.HysteriaSettings.Hysteria = class extends Inbound.ClientBase { + constructor( + auth = RandomUtil.randomSeq(10), + email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at, + ) { + super(email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at); + this.auth = auth; + } + + toJson() { + return { + auth: this.auth, + ...this._clientBaseToJson(), + }; } + static fromJson(json = {}) { + return new Inbound.HysteriaSettings.Hysteria( + json.auth, + ...Inbound.ClientBase.commonArgsFromJson(json), + ); + } }; Inbound.TunnelSettings = class extends Inbound.Settings { @@ -2707,4 +2752,4 @@ Inbound.TunSettings = class extends Inbound.Settings { userLevel: this.userLevel || 0, }; } -}; +};
\ No newline at end of file diff --git a/web/assets/js/model/outbound.js b/web/assets/js/model/outbound.js index 56606231..b8ec4c12 100644 --- a/web/assets/js/model/outbound.js +++ b/web/assets/js/model/outbound.js @@ -782,8 +782,8 @@ class Outbound extends CommonClass { } canEnableTls() { - if (![Protocols.VMess, Protocols.VLESS, Protocols.Trojan, Protocols.Shadowsocks, Protocols.Hysteria].includes(this.protocol)) return false; - if (this.protocol === Protocols.Hysteria) return this.stream.network === 'hysteria'; + if (this.protocol === Protocols.Hysteria) return true; + if (![Protocols.VMess, Protocols.VLESS, Protocols.Trojan, Protocols.Shadowsocks].includes(this.protocol)) return false; return ["tcp", "ws", "http", "grpc", "httpupgrade", "xhttp"].includes(this.stream.network); } diff --git a/web/html/component/aClientTable.html b/web/html/component/aClientTable.html index d9a9b5f5..0e32d45c 100644 --- a/web/html/component/aClientTable.html +++ b/web/html/component/aClientTable.html @@ -30,7 +30,7 @@ </a-tooltip> </template> <template slot="enable" slot-scope="text, client, index"> - <a-switch v-model="client.enable" @change="switchEnableClient(record.id,client)"></a-switch> + <a-switch v-model="client.enable" @change="switchEnableClient(record.id, client, $event)"></a-switch> </template> <template slot="online" slot-scope="text, client, index"> <a-popover :overlay-class-name="themeSwitcher.currentTheme"> @@ -165,7 +165,7 @@ <span :style="{ color: '#FF4D4F' }"> {{ i18n "delete"}}</span> </a-menu-item> <a-menu-item> - <a-switch v-model="client.enable" size="small" @change="switchEnableClient(record.id,client)"></a-switch> + <a-switch v-model="client.enable" size="small" @change="switchEnableClient(record.id, client, $event)"></a-switch> {{ i18n "enable"}} </a-menu-item> </a-menu> diff --git a/web/html/form/client.html b/web/html/form/client.html index 908f28d2..da19fe8f 100644 --- a/web/html/form/client.html +++ b/web/html/form/client.html @@ -1,5 +1,6 @@ {{define "form/client"}} -<a-form layout="horizontal" v-if="client" :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }"> +<a-form layout="horizontal" v-if="client" :colon="false" + :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }"> <a-form-item label='{{ i18n "pages.inbounds.enable" }}'> <a-switch v-model="client.enable"></a-switch> </a-form-item> @@ -10,38 +11,62 @@ <span>{{ i18n "pages.inbounds.emailDesc" }}</span> </template> {{ i18n "pages.inbounds.email" }} - <a-icon type="sync" @click="client.email = RandomUtil.randomLowerAndNum(9)"></a-icon> + <a-icon type="sync" + @click="client.email = RandomUtil.randomLowerAndNum(9)"></a-icon> </a-tooltip> </template> <a-input v-model.trim="client.email"></a-input> </a-form-item> - <a-form-item v-if="inbound.protocol === Protocols.TROJAN || inbound.protocol === Protocols.SHADOWSOCKS"> + <a-form-item + v-if="inbound.protocol === Protocols.TROJAN || inbound.protocol === Protocols.SHADOWSOCKS"> <template slot="label"> <a-tooltip> <template slot="title"> <span>{{ i18n "reset" }}</span> </template> {{ i18n "password" }} - <a-i
|
