mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-09-11 10:54:20 +08:00
update 2026-08-13 20:57:15
This commit is contained in:
+1
-1
@@ -10,7 +10,7 @@ PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_VERSION:=039adf5080465653d166b8c7428515dfa11431d9
|
||||
PKG_SOURCE_VERSION:=9b40cd67c1c6a799f28ee9879d43f7f5b527683f
|
||||
PKG_SOURCE_URL:=https://github.com/olicesx/dae.git
|
||||
PKG_MIRROR_HASH:=skip
|
||||
|
||||
|
||||
@@ -20,19 +20,31 @@ function is_timehhmm(str) {
|
||||
}
|
||||
|
||||
if (typeof cbi_validators !== 'undefined' && cbi_validators !== null) {
|
||||
cbi_validators['base64'] = function() {
|
||||
return isBase64(this);
|
||||
}
|
||||
cbi_validators['json'] = function() {
|
||||
return is_json(this);
|
||||
}
|
||||
cbi_validators['timehhmm'] = function() {
|
||||
return is_timehhmm(this);
|
||||
}
|
||||
cbi_validators['uuid'] = function() {
|
||||
return isUUID(this);
|
||||
}
|
||||
} else {
|
||||
L.require('validation').then(function(validation) {
|
||||
validation.types['base64'] = function() {
|
||||
return this.assert(isBase64(this.value), _('Must be Base64 text!'));
|
||||
}
|
||||
validation.types['json'] = function() {
|
||||
return this.assert(is_json(this.value), _('Must be JSON text!'));
|
||||
}
|
||||
validation.types['timehhmm'] = function() {
|
||||
return this.assert(is_timehhmm(this.value), _('valid time (hh:mm)'));
|
||||
}
|
||||
validation.types['uuid'] = function() {
|
||||
return this.assert(isUUID(this.value), _('Must be UUID format!'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,6 +8,11 @@ function arraysEqual(a, b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function isBase64(str) {
|
||||
const base64Regex = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/;
|
||||
return base64Regex.test(str);
|
||||
}
|
||||
|
||||
function decodeIfBase64(str) {
|
||||
try {
|
||||
let s = str.replace(/-/g, '+').replace(/_/g, '/');
|
||||
@@ -24,6 +29,11 @@ function decodeIfBase64(str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
function isUUID(str) {
|
||||
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
||||
return uuidRegex.test(str);
|
||||
}
|
||||
|
||||
function waitForElement(selector, callback) {
|
||||
const el = document.querySelector(selector);
|
||||
if (el) return callback(el);
|
||||
|
||||
@@ -56,6 +56,7 @@ function index()
|
||||
--[[ Server ]]
|
||||
entry({"admin", "services", appname, "server"}, cbi(appname .. "/server/index"), _("Server-Side"), 99).leaf = true
|
||||
entry({"admin", "services", appname, "server_config"}, cbi(appname .. "/server/server_config")).leaf = true
|
||||
entry({"admin", "services", appname, "server_user_config"}, cbi(appname .. "/server/user_config")).leaf = true
|
||||
|
||||
--[[ API ]]
|
||||
entry({"admin", "services", appname, "server_update_config"}, call("server_update_config")).leaf = true
|
||||
|
||||
@@ -18,37 +18,39 @@ e.default = "90"
|
||||
e.datatype = "range(0,600)"
|
||||
e.rmempty = false
|
||||
|
||||
t = m:section(TypedSection, "server", translate("Servers Manager"))
|
||||
t.anonymous = true
|
||||
t.addremove = true
|
||||
t.sortable = true
|
||||
t.template = "cbi/tblsection"
|
||||
t.extedit = api.url("server_config", "%s")
|
||||
function t.create(e, t)
|
||||
|
||||
s_server = m:section(TypedSection, "server", translate("Servers Manager"))
|
||||
s_server.anonymous = true
|
||||
s_server.addremove = true
|
||||
s_server.sortable = true
|
||||
s_server.template = "cbi/tblsection"
|
||||
s_server.extedit = api.url("server_config", "%s")
|
||||
function s_server.create(self, section)
|
||||
local uid = api.gen_random_char()
|
||||
TypedSection.create(e, uid)
|
||||
luci.http.redirect(e.extedit:format(uid))
|
||||
TypedSection.create(self, uid)
|
||||
luci.http.redirect(self.extedit:format(uid))
|
||||
end
|
||||
function t.remove(e, t)
|
||||
e.map.proceed = true
|
||||
e.map:del(t)
|
||||
luci.http.redirect(api.url("server"))
|
||||
function s_server.remove(self, section)
|
||||
local o = m:get(section) or {}
|
||||
if o[".type"] == self.sectiontype then
|
||||
m:del(section)
|
||||
end
|
||||
end
|
||||
|
||||
e = t:option(Flag, "enable", translate("Enable"))
|
||||
e = s_server:option(Flag, "enable", translate("Enable"))
|
||||
e.width = "5%"
|
||||
e.rmempty = false
|
||||
|
||||
e = t:option(DummyValue, "status", translate("Status"))
|
||||
e = s_server:option(DummyValue, "status", translate("Status"))
|
||||
e.rawhtml = true
|
||||
e.cfgvalue = function(t, n)
|
||||
return string.format('<font class="_servers_status">%s</font>', translate("Collecting data..."))
|
||||
end
|
||||
|
||||
e = t:option(DummyValue, "remarks", translate("Remarks"))
|
||||
e = s_server:option(DummyValue, "remarks", translate("Remarks"))
|
||||
e.width = "15%"
|
||||
|
||||
e = t:option(DummyValue, "type", translate("Type"))
|
||||
e = s_server:option(DummyValue, "type", translate("Type"))
|
||||
e.width = "20%"
|
||||
e.rawhtml = true
|
||||
e.cfgvalue = function(t, n)
|
||||
@@ -86,24 +88,74 @@ e.cfgvalue = function(t, n)
|
||||
return str
|
||||
end
|
||||
|
||||
e = t:option(DummyValue, "port", translate("Port"))
|
||||
e = s_server:option(DummyValue, "port", translate("Port"))
|
||||
|
||||
e = t:option(Flag, "log", translate("Log"))
|
||||
e = s_server:option(Flag, "log", translate("Log"))
|
||||
e.default = "1"
|
||||
e.rmempty = false
|
||||
|
||||
local sortable = Template(appname .. "/cbi/sortable")
|
||||
sortable.api = api
|
||||
sortable.appname = m.config
|
||||
sortable.target_cfgname = t.sectiontype
|
||||
sortable.target_cfgname = s_server.sectiontype
|
||||
m:append(sortable)
|
||||
|
||||
local server_list_status = Template(appname .. "/server/server_list_status")
|
||||
server_list_status.api = api
|
||||
server_list_status.appname = m.config
|
||||
server_list_status.sectiontype = t.sectiontype
|
||||
server_list_status.sectiontype = s_server.sectiontype
|
||||
m:append(server_list_status)
|
||||
|
||||
s_user = m:section(TypedSection, "user", translate("Users Manager"))
|
||||
s_user.anonymous = true
|
||||
s_user.addremove = true
|
||||
s_user.sortable = true
|
||||
s_user.template = "cbi/tblsection"
|
||||
s_user.extedit = api.url("server_user_config", "%s")
|
||||
s_user.create = function(e, section)
|
||||
local uid = api.gen_random_char()
|
||||
TypedSection.create(e, uid)
|
||||
luci.http.redirect(e.extedit:format(uid))
|
||||
end
|
||||
s_user.remove = function(self, section)
|
||||
local o = m:get(section) or {}
|
||||
if o[".type"] == self.sectiontype then
|
||||
m.uci:foreach(m.config, "server", function(o)
|
||||
if o.user and section == o.user then
|
||||
m:set(o[".name"], "user", "")
|
||||
end
|
||||
local changed = false
|
||||
local users = o.users or {}
|
||||
for i = #users, 1, -1 do
|
||||
if section == users[i] then
|
||||
table.remove(users, i)
|
||||
changed = true
|
||||
end
|
||||
end
|
||||
if changed then
|
||||
m:set(o[".name"], "users", users)
|
||||
end
|
||||
end)
|
||||
m:del(section)
|
||||
luci.http.redirect(api.url("server"))
|
||||
end
|
||||
end
|
||||
|
||||
e = s_user:option(DummyValue, "username", translate("Username"))
|
||||
e.width = "25%"
|
||||
|
||||
e = s_user:option(DummyValue, "password", translate("Password"))
|
||||
e.width = "25%"
|
||||
|
||||
e = s_user:option(DummyValue, "uuid", "UUID")
|
||||
e.width = "25%"
|
||||
|
||||
local sortable = Template(appname .. "/cbi/sortable")
|
||||
sortable.api = api
|
||||
sortable.appname = m.config
|
||||
sortable.target_cfgname = s_user.sectiontype
|
||||
m:append(sortable)
|
||||
|
||||
m:append(Template(appname .. "/server/log"))
|
||||
|
||||
return api.return_map(m)
|
||||
|
||||
@@ -20,7 +20,12 @@ m:append(header)
|
||||
|
||||
m:append(Template(appname .. "/cbi/nodes_listvalue_com"))
|
||||
|
||||
s = m:section(NamedSection, arg[1], "user", "")
|
||||
user_list = {}
|
||||
m.uci:foreach(m.config, "user", function(s)
|
||||
user_list[#user_list + 1] = s
|
||||
end)
|
||||
|
||||
s = m:section(NamedSection, arg[1], "server", "")
|
||||
s.addremove = false
|
||||
s.dynamic = false
|
||||
|
||||
|
||||
@@ -28,6 +28,12 @@ o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(DynamicList, _n("users"), translate("User"))
|
||||
for i, v in ipairs(user_list) do
|
||||
o:value(v[".name"], v.username)
|
||||
end
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(Flag, _n("realms"), translate("Realms"))
|
||||
o.default = "0"
|
||||
o.rewrite_option = o.option
|
||||
@@ -48,11 +54,6 @@ o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("realms")] = "1" })
|
||||
|
||||
o = s:option(Value, _n("auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o.rewrite_option = o.option
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(ListValue, _n("obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
|
||||
@@ -48,27 +48,18 @@ o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(Flag, _n("auth"), translate("Auth"))
|
||||
o.validate = function(self, value, t)
|
||||
if value and value == "1" then
|
||||
local user_v = s.fields[_n("username")] and s.fields[_n("username")]:formvalue(t) or ""
|
||||
local pass_v = s.fields[_n("password")] and s.fields[_n("password")]:formvalue(t) or ""
|
||||
if user_v == "" or pass_v == "" then
|
||||
return nil, translate("Username and Password must be used together!")
|
||||
end
|
||||
end
|
||||
return value
|
||||
|
||||
o = s:option(DynamicList, _n("users"), translate("User"))
|
||||
for i, v in ipairs(user_list) do
|
||||
o:value(v[".name"], v.username)
|
||||
end
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "http" })
|
||||
|
||||
o = s:option(Value, _n("username"), translate("Username"))
|
||||
o:depends({ [_n("auth")] = true })
|
||||
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
o:depends({ [_n("auth")] = true })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(ListValue, _n("d_protocol"), translate("Destination protocol"))
|
||||
o:value("tcp", "TCP")
|
||||
@@ -97,6 +88,9 @@ o.rewrite_option = "method"
|
||||
for a, t in ipairs(x_ss_method_list) do o:value(t) end
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(Value, _n("ss_password"), translate("Password"))
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(ListValue, _n("ss_network"), translate("Transport"))
|
||||
o.default = "tcp,udp"
|
||||
o:value("tcp", "TCP")
|
||||
@@ -109,14 +103,6 @@ o.default = "1"
|
||||
o.rmempty = false
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
|
||||
o = s:option(DynamicList, _n("uuid"), translate("ID") .. "/" .. translate("Password"))
|
||||
for i = 1, 3 do
|
||||
o:value(api.gen_uuid())
|
||||
end
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
|
||||
o = s:option(ListValue, _n("flow"), translate("flow"))
|
||||
o.default = ""
|
||||
o:value("", translate("Disable"))
|
||||
@@ -141,10 +127,6 @@ o = s:option(DynamicList, _n("hysteria2_realm_stun"), translate("Realm STUN"))
|
||||
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
|
||||
o:depends({ [_n("hysteria2_realms")] = "1" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
|
||||
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
|
||||
@@ -60,35 +60,27 @@ o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(Flag, _n("auth"), translate("Auth"))
|
||||
o.validate = function(self, value, t)
|
||||
if value and value == "1" then
|
||||
local user_v = s.fields[_n("username")] and s.fields[_n("username")]:formvalue(t) or ""
|
||||
local pass_v = s.fields[_n("password")] and s.fields[_n("password")]:formvalue(t) or ""
|
||||
if user_v == "" or pass_v == "" then
|
||||
return nil, translate("Username and Password must be used together!")
|
||||
end
|
||||
end
|
||||
return value
|
||||
o = s:option(DynamicList, _n("users"), translate("User"))
|
||||
for i, v in ipairs(user_list) do
|
||||
o:value(v[".name"], v.username)
|
||||
end
|
||||
o:depends({ [_n("protocol")] = "mixed" })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "http" })
|
||||
|
||||
o = s:option(Value, _n("username"), translate("Username"))
|
||||
o:depends({ [_n("auth")] = true })
|
||||
o:depends({ [_n("protocol")] = "naive" })
|
||||
o:depends({ [_n("protocol")] = "anytls" })
|
||||
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
o:depends({ [_n("auth")] = true })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "naive" })
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("protocol")] = "anytls" })
|
||||
|
||||
if singbox_tags:find("with_quic") then
|
||||
o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password"))
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Value, _n("hysteria_up_mbps"), translate("Max upload Mbps"))
|
||||
o.default = "100"
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
@@ -97,20 +89,6 @@ if singbox_tags:find("with_quic") then
|
||||
o.default = "100"
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password"))
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(ListValue, _n("hysteria_auth_type"), translate("Auth Type"))
|
||||
o:value("disable", translate("Disable"))
|
||||
o:value("string", translate("STRING"))
|
||||
o:value("base64", translate("BASE64"))
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Value, _n("hysteria_auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o:depends({ [_n("protocol")] = "hysteria", [_n("hysteria_auth_type")] = "string"})
|
||||
o:depends({ [_n("protocol")] = "hysteria", [_n("hysteria_auth_type")] = "base64"})
|
||||
|
||||
o = s:option(Value, _n("hysteria_recv_window_conn"), translate("QUIC stream receive window"))
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
@@ -174,10 +152,6 @@ if singbox_tags:find("with_quic") then
|
||||
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
|
||||
o:depends({ [_n("hysteria2_realms")] = "1" })
|
||||
|
||||
o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
|
||||
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
@@ -233,14 +207,8 @@ o.rewrite_option = "method"
|
||||
for a, t in ipairs(ss_method_list) do o:value(t) end
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(DynamicList, _n("uuid"), translate("ID") .. "/" .. translate("Password"))
|
||||
for i = 1, 3 do
|
||||
o:value(api.gen_uuid())
|
||||
end
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
o = s:option(Value, _n("ss_password"), translate("Password"))
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(ListValue, _n("flow"), translate("flow"))
|
||||
o.default = ""
|
||||
|
||||
@@ -27,22 +27,11 @@ o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Flag, _n("auth"), translate("Auth"))
|
||||
o.validate = function(self, value, t)
|
||||
if value and value == "1" then
|
||||
local user_v = s.fields[_n("username")] and s.fields[_n("username")]:formvalue(t) or ""
|
||||
local pass_v = s.fields[_n("password")] and s.fields[_n("password")]:formvalue(t) or ""
|
||||
if user_v == "" or pass_v == "" then
|
||||
return nil, translate("Username and Password must be used together!")
|
||||
end
|
||||
end
|
||||
return value
|
||||
|
||||
o = s:option(ListValue, _n("user"), translate("User"))
|
||||
for i, v in ipairs(user_list) do
|
||||
o:value(v[".name"], v.username)
|
||||
end
|
||||
|
||||
o = s:option(Value, _n("username"), translate("Username"))
|
||||
o:depends({ [_n("auth")] = true })
|
||||
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
o:depends({ [_n("auth")] = true })
|
||||
|
||||
o = s:option(Flag, _n("log"), translate("Log"))
|
||||
|
||||
@@ -32,8 +32,10 @@ o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
o = s:option(ListValue, _n("user"), translate("User"))
|
||||
for i, v in ipairs(user_list) do
|
||||
o:value(v[".name"], v.username)
|
||||
end
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(ListValue, _n("method"), translate("Encrypt Method"))
|
||||
|
||||
@@ -45,8 +45,10 @@ o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
o = s:option(ListValue, _n("user"), translate("User"))
|
||||
for i, v in ipairs(user_list) do
|
||||
o:value(v[".name"], v.username)
|
||||
end
|
||||
o:depends({ [_n("custom")] = false })
|
||||
|
||||
o = s:option(ListValue, _n("method"), translate("Encrypt Method"))
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
api = require "luci.passwall.api"
|
||||
appname = api.appname
|
||||
fs = api.fs
|
||||
|
||||
api.set_default_cbi()
|
||||
|
||||
m = Map("passwall_server", translate("User Config"))
|
||||
m.redirect = api.url("server")
|
||||
api.set_apply_on_parse(m)
|
||||
|
||||
if not arg[1] or not m:get(arg[1]) then
|
||||
luci.http.redirect(m.redirect)
|
||||
end
|
||||
|
||||
s = m:section(NamedSection, arg[1], "user", "")
|
||||
s.addremove = false
|
||||
s.dynamic = false
|
||||
|
||||
o = s:option(Value, "username", translate("Username"))
|
||||
o.datatype = "and(uciname,maxlength(24))"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "password", translate("Password"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "uuid", "UUID")
|
||||
o.datatype = "uuid"
|
||||
o.default = api.gen_uuid()
|
||||
o.rmempty = false
|
||||
|
||||
return api.return_map(m)
|
||||
@@ -369,6 +369,12 @@ function is_timehhmm(str)
|
||||
end
|
||||
datatypes.timehhmm = is_timehhmm
|
||||
|
||||
function is_uuid(str)
|
||||
local pattern = "^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$"
|
||||
return string.match(str, pattern) ~= nil
|
||||
end
|
||||
datatypes.uuid = is_uuid
|
||||
|
||||
function is_normal_node(e)
|
||||
if e and e.type and e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface" or e.protocol == "_urltest") then
|
||||
return false
|
||||
|
||||
@@ -123,8 +123,12 @@ local function start()
|
||||
if type == "Socks" then
|
||||
local auth = ""
|
||||
if server.auth and server.auth == "1" then
|
||||
local username = server.username or ""
|
||||
local password = server.password or ""
|
||||
local user = nil
|
||||
if server.user then
|
||||
user = uci:get_all("passwall_server", server.user)
|
||||
end
|
||||
local username = user and user.username or ""
|
||||
local password = user and user.password or ""
|
||||
if username ~= "" and password ~= "" then
|
||||
username = "-u " .. username
|
||||
password = "-P " .. password
|
||||
|
||||
@@ -4,6 +4,20 @@ local uci = api.uci
|
||||
local jsonc = api.jsonc
|
||||
|
||||
function gen_config_server(node)
|
||||
local users = node.users or {}
|
||||
local users = nil
|
||||
if node.users and #node.users > 0 then
|
||||
users = {}
|
||||
for i, v in ipairs(node.users) do
|
||||
local user = uci:get_all("passwall2_server", v) or {}
|
||||
if user[".type"] == "user" then
|
||||
users[user.username] = user.password
|
||||
end
|
||||
end
|
||||
if not next(users) then
|
||||
users = nil
|
||||
end
|
||||
end
|
||||
local config = {
|
||||
listen = (function()
|
||||
if node.hysteria2_realms and node.hysteria2_realm_url then
|
||||
@@ -25,10 +39,10 @@ function gen_config_server(node)
|
||||
password = node.hysteria2_obfs_password
|
||||
}
|
||||
} or nil,
|
||||
auth = {
|
||||
type = "password",
|
||||
password = node.hysteria2_auth_password
|
||||
},
|
||||
auth = users and {
|
||||
type = "userpass",
|
||||
userpass = users
|
||||
} or nil,
|
||||
bandwidth = (node.hysteria2_up_mbps or node.hysteria2_down_mbps) and {
|
||||
up = node.hysteria2_up_mbps and node.hysteria2_up_mbps .. " mbps" or nil,
|
||||
down = node.hysteria2_down_mbps and node.hysteria2_down_mbps .. " mbps" or nil
|
||||
|
||||
@@ -4,9 +4,13 @@ local uci = api.uci
|
||||
local jsonc = api.jsonc
|
||||
|
||||
function gen_config_server(node)
|
||||
local user = nil
|
||||
if node.user then
|
||||
user = uci:get_all("passwall2_server", node.user)
|
||||
end
|
||||
local config = {}
|
||||
config.server_port = tonumber(node.port)
|
||||
config.password = node.password
|
||||
config.password = user and user.password or ""
|
||||
config.timeout = tonumber(node.timeout)
|
||||
config.fast_open = (node.tcp_fast_open and node.tcp_fast_open == "1") and true or false
|
||||
config.method = node.method
|
||||
|
||||
@@ -766,39 +766,71 @@ function gen_config_server(node)
|
||||
listen_port = tonumber(node.port),
|
||||
}
|
||||
|
||||
local users = node.users or {}
|
||||
local users = nil
|
||||
if node.users and #node.users > 0 then
|
||||
users = {}
|
||||
for i, v in ipairs(node.users) do
|
||||
local user = uci:get_all("passwall2_server", v) or {}
|
||||
if user[".type"] == "user" then
|
||||
local u = {}
|
||||
if node.protocol == "mixed" or node.protocol == "socks" or node.protocol == "http" or node.protocol == "naive" then
|
||||
u.username = user.username
|
||||
u.password = user.password
|
||||
end
|
||||
if node.protocol == "shadowsocks" or node.protocol == "trojan" then
|
||||
u.name = user.username
|
||||
u.password = user.password
|
||||
end
|
||||
if node.protocol == "vmess" then
|
||||
u.name = user.username
|
||||
u.uuid = user.uuid
|
||||
u.alterId = 0
|
||||
end
|
||||
if node.protocol == "vless" then
|
||||
u.name = user.username
|
||||
u.uuid = user.uuid
|
||||
u.flow = node.flow
|
||||
end
|
||||
if node.protocol == "hysteria" then
|
||||
u.name = user.username
|
||||
u.auth_str = user.password
|
||||
end
|
||||
if node.protocol == "tuic" then
|
||||
u.name = user.username
|
||||
u.password = user.password
|
||||
u.uuid = user.uuid
|
||||
end
|
||||
if node.protocol == "hysteria2" then
|
||||
u.name = user.username
|
||||
u.password = user.password
|
||||
end
|
||||
users[#users + 1] = u
|
||||
end
|
||||
end
|
||||
if #users == 0 then
|
||||
users = nil
|
||||
end
|
||||
end
|
||||
|
||||
local protocol_table = nil
|
||||
|
||||
if node.protocol == "mixed" then
|
||||
protocol_table = {
|
||||
users = (node.auth == "1") and {
|
||||
{
|
||||
username = node.username,
|
||||
password = node.password
|
||||
}
|
||||
} or nil,
|
||||
users = users,
|
||||
set_system_proxy = false
|
||||
}
|
||||
end
|
||||
|
||||
if node.protocol == "socks" then
|
||||
protocol_table = {
|
||||
users = (node.auth == "1") and {
|
||||
{
|
||||
username = node.username,
|
||||
password = node.password
|
||||
}
|
||||
} or nil
|
||||
users = users
|
||||
}
|
||||
end
|
||||
|
||||
if node.protocol == "http" then
|
||||
protocol_table = {
|
||||
users = (node.auth == "1") and {
|
||||
{
|
||||
username = node.username,
|
||||
password = node.password
|
||||
}
|
||||
} or nil,
|
||||
users = users,
|
||||
tls = (node.tls == "1") and tls or nil,
|
||||
}
|
||||
end
|
||||
@@ -806,21 +838,14 @@ function gen_config_server(node)
|
||||
if node.protocol == "shadowsocks" then
|
||||
protocol_table = {
|
||||
method = node.method,
|
||||
password = node.password,
|
||||
password = node.ss_password,
|
||||
users = users,
|
||||
multiplex = mux,
|
||||
}
|
||||
end
|
||||
|
||||
if node.protocol == "vmess" then
|
||||
if node.uuid then
|
||||
local users = {}
|
||||
for i = 1, #node.uuid do
|
||||
users[i] = {
|
||||
name = node.uuid[i],
|
||||
uuid = node.uuid[i],
|
||||
alterId = 0,
|
||||
}
|
||||
end
|
||||
if users then
|
||||
protocol_table = {
|
||||
users = users,
|
||||
tls = (node.tls == "1") and tls or nil,
|
||||
@@ -831,15 +856,7 @@ function gen_config_server(node)
|
||||
end
|
||||
|
||||
if node.protocol == "vless" then
|
||||
if node.uuid then
|
||||
local users = {}
|
||||
for i = 1, #node.uuid do
|
||||
users[i] = {
|
||||
name = node.uuid[i],
|
||||
uuid = node.uuid[i],
|
||||
flow = node.flow,
|
||||
}
|
||||
end
|
||||
if users then
|
||||
protocol_table = {
|
||||
users = users,
|
||||
tls = (node.tls == "1") and tls or nil,
|
||||
@@ -850,14 +867,7 @@ function gen_config_server(node)
|
||||
end
|
||||
|
||||
if node.protocol == "trojan" then
|
||||
if node.uuid then
|
||||
local users = {}
|
||||
for i = 1, #node.uuid do
|
||||
users[i] = {
|
||||
name = node.uuid[i],
|
||||
password = node.uuid[i],
|
||||
}
|
||||
end
|
||||
if users then
|
||||
protocol_table = {
|
||||
users = users,
|
||||
tls = (node.tls == "1") and tls or nil,
|
||||
@@ -870,15 +880,12 @@ function gen_config_server(node)
|
||||
end
|
||||
|
||||
if node.protocol == "naive" then
|
||||
protocol_table = {
|
||||
users = {
|
||||
{
|
||||
username = node.username,
|
||||
password = node.password
|
||||
}
|
||||
},
|
||||
tls = tls,
|
||||
}
|
||||
if users then
|
||||
protocol_table = {
|
||||
users = users,
|
||||
tls = tls
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
if node.protocol == "hysteria" then
|
||||
@@ -888,13 +895,7 @@ function gen_config_server(node)
|
||||
up_mbps = tonumber(node.hysteria_up_mbps),
|
||||
down_mbps = tonumber(node.hysteria_down_mbps),
|
||||
obfs = node.hysteria_obfs,
|
||||
users = {
|
||||
{
|
||||
name = "user1",
|
||||
auth = (node.hysteria_auth_type == "base64") and node.hysteria_auth_password or nil,
|
||||
auth_str = (node.hysteria_auth_type == "string") and node.hysteria_auth_password or nil,
|
||||
}
|
||||
},
|
||||
users = users,
|
||||
recv_window_conn = node.hysteria_recv_window_conn and tonumber(node.hysteria_recv_window_conn) or nil, --1.14 to stream_receive_window
|
||||
recv_window_client = node.hysteria_recv_window_client and tonumber(node.hysteria_recv_window_client) or nil, --1.14 to connection_receive_window
|
||||
max_conn_client = node.hysteria_max_conn_client and tonumber(node.hysteria_max_conn_client) or nil, --1.14 to max_concurrent_streams
|
||||
@@ -904,31 +905,21 @@ function gen_config_server(node)
|
||||
end
|
||||
|
||||
if node.protocol == "tuic" then
|
||||
if node.uuid then
|
||||
local users = {}
|
||||
for i = 1, #node.uuid do
|
||||
users[i] = {
|
||||
name = node.uuid[i],
|
||||
uuid = node.uuid[i],
|
||||
password = node.password
|
||||
}
|
||||
end
|
||||
tls.alpn = (node.tuic_alpn and node.tuic_alpn ~= "default") and (function()
|
||||
local alpn = {}
|
||||
string.gsub(node.tuic_alpn, '[^,]+', function(w)
|
||||
table.insert(alpn, w)
|
||||
end)
|
||||
if #alpn > 0 then return alpn end
|
||||
return nil
|
||||
end)() or nil
|
||||
protocol_table = {
|
||||
users = users,
|
||||
congestion_control = node.tuic_congestion_control or "cubic",
|
||||
zero_rtt_handshake = (node.tuic_zero_rtt_handshake == "1") and true or false,
|
||||
heartbeat = (tonumber(node.tuic_heartbeat) or 3) .. "s",
|
||||
tls = tls
|
||||
}
|
||||
end
|
||||
tls.alpn = (node.tuic_alpn and node.tuic_alpn ~= "default") and (function()
|
||||
local alpn = {}
|
||||
string.gsub(node.tuic_alpn, '[^,]+', function(w)
|
||||
table.insert(alpn, w)
|
||||
end)
|
||||
if #alpn > 0 then return alpn end
|
||||
return nil
|
||||
end)() or nil
|
||||
protocol_table = {
|
||||
users = users,
|
||||
congestion_control = node.tuic_congestion_control or "cubic",
|
||||
zero_rtt_handshake = (node.tuic_zero_rtt_handshake == "1") and true or false,
|
||||
heartbeat = (tonumber(node.tuic_heartbeat) or 3) .. "s",
|
||||
tls = tls
|
||||
}
|
||||
end
|
||||
|
||||
if node.protocol == "hysteria2" then
|
||||
@@ -953,12 +944,7 @@ function gen_config_server(node)
|
||||
end
|
||||
return o
|
||||
end)(node.hysteria2_obfs_type),
|
||||
users = {
|
||||
{
|
||||
name = "user1",
|
||||
password = node.hysteria2_auth_password or nil,
|
||||
}
|
||||
},
|
||||
users = users,
|
||||
ignore_client_bandwidth = (node.hysteria2_ignore_client_bandwidth == "1") and true or false,
|
||||
tls = tls,
|
||||
realm = node.hysteria2_realms and (function()
|
||||
@@ -978,15 +964,12 @@ function gen_config_server(node)
|
||||
end
|
||||
|
||||
if node.protocol == "anytls" then
|
||||
protocol_table = {
|
||||
users = {
|
||||
{
|
||||
name = (node.username and node.username ~= "") and node.username or "sekai",
|
||||
password = node.password
|
||||
}
|
||||
},
|
||||
tls = tls,
|
||||
}
|
||||
if users then
|
||||
protocol_table = {
|
||||
users = users,
|
||||
tls = tls,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
if node.protocol == "direct" then
|
||||
|
||||
@@ -488,17 +488,46 @@ function gen_config_server(node)
|
||||
{ protocol = "freedom", tag = "direct", settings = { finalRules = {{ action = "allow" }}}}, { protocol = "blackhole", tag = "blocked" }
|
||||
}
|
||||
|
||||
if node.protocol == "vmess" or node.protocol == "vless" then
|
||||
if node.uuid then
|
||||
local users = {}
|
||||
for i = 1, #node.uuid do
|
||||
users[i] = {
|
||||
id = node.uuid[i],
|
||||
flow = (node.protocol == "vless"
|
||||
and (node.tls == "1" or (node.decryption and node.decryption ~= "" and node.decryption ~= "none"))
|
||||
and node.flow and node.flow ~= "") and node.flow or nil
|
||||
}
|
||||
local users = node.users or {}
|
||||
local users = nil
|
||||
if node.users and #node.users > 0 then
|
||||
users = {}
|
||||
for i, v in ipairs(node.users) do
|
||||
local user = uci:get_all("passwall2_server", v) or {}
|
||||
if user[".type"] == "user" then
|
||||
local u = {}
|
||||
if node.protocol == "socks" or node.protocol == "http" then
|
||||
u.user = user.username
|
||||
u.pass = user.password
|
||||
end
|
||||
if node.protocol == "shadowsocks" or node.protocol == "trojan" then
|
||||
u.email = user.username
|
||||
u.password = user.password
|
||||
end
|
||||
if node.protocol == "vmess" then
|
||||
u.email = user.username
|
||||
u.id = user.uuid
|
||||
u.alterId = 0
|
||||
end
|
||||
if node.protocol == "vless" then
|
||||
u.email = user.username
|
||||
u.id = user.uuid
|
||||
u.flow = node.flow
|
||||
end
|
||||
if node.protocol == "hysteria2" then
|
||||
u.email = user.username
|
||||
u.auth = user.password
|
||||
end
|
||||
users[#users + 1] = u
|
||||
end
|
||||
end
|
||||
if #users == 0 then
|
||||
users = nil
|
||||
end
|
||||
end
|
||||
|
||||
if node.protocol == "vmess" or node.protocol == "vless" then
|
||||
if users then
|
||||
settings = {
|
||||
users = users,
|
||||
decryption = (node.protocol == "vless") and ((node.decryption and node.decryption ~= "") and node.decryption or "none") or nil
|
||||
@@ -507,40 +536,25 @@ function gen_config_server(node)
|
||||
elseif node.protocol == "socks" then
|
||||
settings = {
|
||||
udp = ("1" == node.udp_forward) and true or false,
|
||||
auth = ("1" == node.auth) and "password" or "noauth",
|
||||
users = ("1" == node.auth) and {
|
||||
{
|
||||
user = node.username,
|
||||
pass = node.password
|
||||
}
|
||||
} or nil
|
||||
auth = users and "password" or "noauth",
|
||||
users = users
|
||||
}
|
||||
elseif node.protocol == "http" then
|
||||
settings = {
|
||||
allowTransparent = false,
|
||||
users = ("1" == node.auth) and {
|
||||
{
|
||||
user = node.username,
|
||||
pass = node.password
|
||||
}
|
||||
} or nil
|
||||
users = users
|
||||
}
|
||||
node.transport = "tcp"
|
||||
node.tcp_guise = "none"
|
||||
elseif node.protocol == "shadowsocks" then
|
||||
settings = {
|
||||
method = node.method,
|
||||
password = node.password,
|
||||
network = node.ss_network or "TCP,UDP"
|
||||
password = node.ss_password,
|
||||
users = users,
|
||||
network = node.ss_network or "tcp,udp"
|
||||
}
|
||||
elseif node.protocol == "trojan" then
|
||||
if node.uuid then
|
||||
local users = {}
|
||||
for i = 1, #node.uuid do
|
||||
users[i] = {
|
||||
password = node.uuid[i],
|
||||
}
|
||||
end
|
||||
if users then
|
||||
settings = {
|
||||
users = users
|
||||
}
|
||||
@@ -548,9 +562,7 @@ function gen_config_server(node)
|
||||
elseif node.protocol == "hysteria2" then
|
||||
settings = {
|
||||
version = 2,
|
||||
users = node.hysteria2_auth_password and {
|
||||
{ auth = node.hysteria2_auth_password }
|
||||
}
|
||||
users = users
|
||||
}
|
||||
elseif node.protocol == "dokodemo-door" then
|
||||
settings = {
|
||||
|
||||
@@ -1628,6 +1628,9 @@ msgstr "服务器管理"
|
||||
msgid "Users Manager"
|
||||
msgstr "用户管理"
|
||||
|
||||
msgid "User Config"
|
||||
msgstr "用户配置"
|
||||
|
||||
msgid "Logs"
|
||||
msgstr "日志"
|
||||
|
||||
@@ -2064,9 +2067,15 @@ msgstr "使用自定义配置"
|
||||
msgid "Custom Config"
|
||||
msgstr "自定义配置"
|
||||
|
||||
msgid "Must be Base64 text!"
|
||||
msgstr "必须是 Base64 内容!"
|
||||
|
||||
msgid "Must be JSON text!"
|
||||
msgstr "必须是 JSON 文本内容!"
|
||||
|
||||
msgid "Must be UUID format!"
|
||||
msgstr "必须是 UUID 格式!"
|
||||
|
||||
msgid "Geo View"
|
||||
msgstr "Geo 查询"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user