update 2026-08-13 04:37:02

This commit is contained in:
action committed 2026-08-13 04:37:02 +08:00
1 parent 78221232e9
commit 00ef606a42
1986 files changed
+1523528 -443

No files matched your search

@@ -1,7 +1,5 @@
local api = require "luci.passwall2.api"
local appname = api.appname
local datatypes = api.datatypes
local sys = api.sys
api.set_default_cbi()
@@ -30,6 +28,29 @@ o:value("https://connectivitycheck.platform.hicloud.com/generate_204", "HiCloud
o:value("https://wifi.vivo.com.cn/generate_204", "VIVO (CN)")
o.default = o.keylist[3]
m:append(Template(appname .. "/node_list/node_list"))
if true then
local o = Template(appname .. "/node_list/node_list")
o.map = m
o.api = api
m:append(o)
if luci.http.formvalue("cbi.submit") == "1" then
local group_order = {}
group_order = luci.http.formvaluetable("group.order")
if group_order then
for k, v in pairs(group_order) do
if v and v~= "" then
local new_order = {}
string.gsub(v, "[^" .. " " .. "]+", function(w)
new_order[#new_order + 1] = w
end)
for idx, name in ipairs(new_order) do
m.uci:reorder(appname, name, idx - 1)
end
end
end
end
end
end
return api.return_map(m)
@@ -88,6 +88,27 @@ end
s:append(Template(appname .. "/rule/rule_version"))
m:append(Template(appname .. "/rule/shunt_rule_list"))
if true then
local o = Template(appname .. "/rule/shunt_rule_list")
o.api = api
m:append(o)
if luci.http.formvalue("cbi.submit") == "1" then
local group_order = luci.http.formvaluetable("group.order")
if group_order then
for k, v in pairs(group_order) do
if v and v~= "" then
local new_order = {}
string.gsub(v, "[^" .. " " .. "]+", function(w)
new_order[#new_order + 1] = w
end)
for idx, name in ipairs(new_order) do
m.uci:reorder(appname, name, idx - 1)
end
end
end
end
end
end
return api.return_map(m)
@@ -13,38 +13,38 @@ t.addremove = false
e = t:option(Flag, "enable", translate("Enable"))
e.rmempty = false
local cfgname = "user"
t = m:section(TypedSection, cfgname, translate("Users Manager"))
t.anonymous = true
t.addremove = true
t.sortable = true
t.template = "cbi/tblsection"
t.extedit = api.url("server_user", "%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="_users_status">%s</font>', translate("Collecting data..."))
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)
@@ -82,20 +82,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 = cfgname
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 = 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"))
m:append(Template(appname .. "/server/users_list_status"))
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
@@ -26,6 +26,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
@@ -46,11 +52,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,17 @@ 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 +87,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 +102,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 +126,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 = ""
@@ -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.passwall2.api"
appname = api.appname
fs = api.fs
api.set_default_cbi()
m = Map("passwall2_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)