mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-07-27 10:31:38 +08:00
🔥 Sync 2026-04-18 20:14:20
This commit is contained in:
parent
5eb416f3e2
commit
4f4f9882d8
@ -5,8 +5,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ddns-go
|
||||
PKG_VERSION:=6.16.8
|
||||
PKG_RELEASE:=7
|
||||
PKG_VERSION:=6.16.9
|
||||
PKG_RELEASE:=8
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/jeessy2/ddns-go/tar.gz/v$(PKG_VERSION)?
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=gowebdav
|
||||
PKG_VERSION:=5.11.5
|
||||
PKG_RELEASE:=5
|
||||
PKG_VERSION:=5.11.6
|
||||
PKG_RELEASE:=6
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/hacdias/webdav/tar.gz/v$(PKG_VERSION)?
|
||||
|
||||
@ -16,8 +16,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-amlogic
|
||||
PKG_VERSION:=3.1.288
|
||||
PKG_RELEASE:=3
|
||||
PKG_VERSION:=3.1.289
|
||||
PKG_RELEASE:=4
|
||||
|
||||
PKG_LICENSE:=GPL-2.0 License
|
||||
PKG_MAINTAINER:=ophub <https://github.com/ophub/luci-app-amlogic>
|
||||
|
||||
@ -4,7 +4,7 @@ config amlogic 'config'
|
||||
option amlogic_firmware_repo 'https://github.com/breakingbadboy/OpenWrt'
|
||||
option amlogic_firmware_tag 'ARMv8'
|
||||
option amlogic_firmware_suffix '.img.gz'
|
||||
option amlogic_kernel_path 'https://github.com/breakingbadboy/OpenWrt'
|
||||
option amlogic_kernel_path 'https://github.com/ophub/kernel'
|
||||
option amlogic_kernel_tags ''
|
||||
option amlogic_kernel_branch ''
|
||||
option amlogic_firmware_config '1'
|
||||
|
||||
@ -133,6 +133,8 @@ else
|
||||
kernel_tag="rk3588"
|
||||
elif [[ "${kernel_uname}" =~ -rk35xx ]]; then
|
||||
kernel_tag="rk35xx"
|
||||
elif [[ "${kernel_uname}" =~ -flippy ]]; then
|
||||
kernel_tag="flippy"
|
||||
elif [[ "${kernel_uname}" =~ -h6|-zicai ]]; then
|
||||
kernel_tag="h6"
|
||||
else
|
||||
|
||||
@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
-include $(dir $(lastword $(MAKEFILE_LIST)))../version.mk
|
||||
|
||||
PKG_VERSION:=$(or $(EASYTIER_VERSION),2.6.0)
|
||||
PKG_RELEASE:=5
|
||||
PKG_RELEASE:=6
|
||||
|
||||
LUCI_TITLE:=LuCI support for EasyTier
|
||||
LUCI_DEPENDS:=+kmod-tun +easytier +luci-compat
|
||||
|
||||
@ -68,6 +68,7 @@ function index()
|
||||
entry({"admin", "vpn", "easytier", "clear_version_cache"}, call("clear_version_cache")).leaf = true
|
||||
entry({"admin", "vpn", "easytier", "get_web_config"}, call("get_web_config")).leaf = true
|
||||
entry({"admin", "vpn", "easytier", "save_web_config"}, call("save_web_config")).leaf = true
|
||||
entry({"admin", "vpn", "easytier", "reset_database"}, call("reset_database")).leaf = true
|
||||
entry({"admin", "vpn", "easytier", "check_web_status"}, call("check_web_status")).leaf = true
|
||||
entry({"admin", "vpn", "easytier", "api_status"}, call("act_status")).leaf = true
|
||||
entry({"admin", "vpn", "easytier", "api_conninfo"}, call("act_conninfo")).leaf = true
|
||||
@ -663,46 +664,178 @@ end
|
||||
|
||||
|
||||
function get_web_config()
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local config = {}
|
||||
|
||||
config.web_enabled = uci:get_first("easytier", "easytier", "web_enabled") or "0"
|
||||
config.web_db_path = uci:get_first("easytier", "easytier", "web_db_path") or "/etc/easytier/et.db"
|
||||
config.web_protocol = uci:get_first("easytier", "easytier", "web_protocol") or "udp"
|
||||
config.web_port = uci:get_first("easytier", "easytier", "web_port") or "22020"
|
||||
config.web_fw_web = uci:get_first("easytier", "easytier", "web_fw_web") or "0"
|
||||
config.web_api_port = uci:get_first("easytier", "easytier", "web_api_port") or "11211"
|
||||
config.web_html_port = uci:get_first("easytier", "easytier", "web_html_port") or "11211"
|
||||
config.web_fw_api = uci:get_first("easytier", "easytier", "web_fw_api") or "0"
|
||||
config.web_api_host = uci:get_first("easytier", "easytier", "web_api_host") or ""
|
||||
config.web_geoip_db = uci:get_first("easytier", "easytier", "web_geoip_db") or ""
|
||||
config.web_weblog = uci:get_first("easytier", "easytier", "web_weblog") or "off"
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
|
||||
local config = {
|
||||
web_enabled = uci:get_first("easytier", "easytier", "web_enabled") or "0",
|
||||
web_db_path = uci:get_first("easytier", "easytier", "web_db_path") or "/etc/easytier/et.db",
|
||||
web_protocol = uci:get_first("easytier", "easytier", "web_protocol") or "udp",
|
||||
web_port = uci:get_first("easytier", "easytier", "web_port") or "22020",
|
||||
web_fw_web = uci:get_first("easytier", "easytier", "web_fw_web") or "0",
|
||||
web_api_port = uci:get_first("easytier", "easytier", "web_api_port") or "11211",
|
||||
web_html_port = uci:get_first("easytier", "easytier", "web_html_port") or "11211",
|
||||
web_api_addr = uci:get_first("easytier", "easytier", "web_api_addr") or "0.0.0.0",
|
||||
web_html_addr = uci:get_first("easytier", "easytier", "web_html_addr") or "0.0.0.0",
|
||||
web_fw_api = uci:get_first("easytier", "easytier", "web_fw_api") or "0",
|
||||
web_api_host = uci:get_first("easytier", "easytier", "web_api_host") or "",
|
||||
web_geoip_db = uci:get_first("easytier", "easytier", "web_geoip_db") or "",
|
||||
web_disable_registration = uci:get_first("easytier", "easytier", "web_disable_registration") or "0",
|
||||
web_allow_auto_create_user = uci:get_first("easytier", "easytier", "web_allow_auto_create_user") or "0",
|
||||
web_weblog = uci:get_first("easytier", "easytier", "web_weblog") or "off",
|
||||
-- OIDC配置
|
||||
web_oidc_enabled = uci:get_first("easytier", "easytier", "web_oidc_enabled") or "0",
|
||||
web_oidc_issuer_url = uci:get_first("easytier", "easytier", "web_oidc_issuer_url") or "",
|
||||
web_oidc_client_id = uci:get_first("easytier", "easytier", "web_oidc_client_id") or "",
|
||||
web_oidc_client_secret = uci:get_first("easytier", "easytier", "web_oidc_client_secret") or "",
|
||||
web_oidc_redirect_url = uci:get_first("easytier", "easytier", "web_oidc_redirect_url") or "",
|
||||
web_oidc_username_claim = uci:get_first("easytier", "easytier", "web_oidc_username_claim") or "preferred_username",
|
||||
web_oidc_scopes = uci:get_first("easytier", "easytier", "web_oidc_scopes") or "openid profile",
|
||||
web_oidc_frontend_base_url = uci:get_first("easytier", "easytier", "web_oidc_frontend_base_url") or "",
|
||||
web_oidc_disable_pkce = uci:get_first("easytier", "easytier", "web_oidc_disable_pkce") or "0",
|
||||
-- Webhook配置
|
||||
web_webhook_enabled = uci:get_first("easytier", "easytier", "web_webhook_enabled") or "0",
|
||||
web_webhook_url = uci:get_first("easytier", "easytier", "web_webhook_url") or "",
|
||||
web_webhook_secret = uci:get_first("easytier", "easytier", "web_webhook_secret") or "",
|
||||
web_internal_auth_token = uci:get_first("easytier", "easytier", "web_internal_auth_token") or "",
|
||||
web_web_instance_id = uci:get_first("easytier", "easytier", "web_web_instance_id") or "",
|
||||
web_web_instance_api_base_url = uci:get_first("easytier", "easytier", "web_web_instance_api_base_url") or ""
|
||||
}
|
||||
|
||||
luci.http.write_json(config)
|
||||
end
|
||||
|
||||
function save_web_config()
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local http = require "luci.http"
|
||||
|
||||
uci:set("easytier", "@easytier[0]", "web_enabled", luci.http.formvalue("web_enabled") or "0")
|
||||
uci:set("easytier", "@easytier[0]", "web_db_path", luci.http.formvalue("web_db_path") or "/etc/easytier/et.db")
|
||||
uci:set("easytier", "@easytier[0]", "web_protocol", luci.http.formvalue("web_protocol") or "udp")
|
||||
uci:set("easytier", "@easytier[0]", "web_port", luci.http.formvalue("web_port") or "22020")
|
||||
uci:set("easytier", "@easytier[0]", "web_fw_web", luci.http.formvalue("web_fw_web") or "0")
|
||||
uci:set("easytier", "@easytier[0]", "web_api_port", luci.http.formvalue("web_api_port") or "11211")
|
||||
uci:set("easytier", "@easytier[0]", "web_html_port", luci.http.formvalue("web_html_port") or "11211")
|
||||
uci:set("easytier", "@easytier[0]", "web_fw_api", luci.http.formvalue("web_fw_api") or "0")
|
||||
uci:set("easytier", "@easytier[0]", "web_api_host", luci.http.formvalue("web_api_host") or "")
|
||||
uci:set("easytier", "@easytier[0]", "web_geoip_db", luci.http.formvalue("web_geoip_db") or "")
|
||||
uci:set("easytier", "@easytier[0]", "web_weblog", luci.http.formvalue("web_weblog") or "off")
|
||||
local web_enabled = http.formvalue("web_enabled") or "0"
|
||||
local web_db_path = http.formvalue("web_db_path") or "/etc/easytier/et.db"
|
||||
local web_protocol = http.formvalue("web_protocol") or "udp"
|
||||
local web_port = http.formvalue("web_port") or "22020"
|
||||
local web_fw_web = http.formvalue("web_fw_web") or "0"
|
||||
local web_api_port = http.formvalue("web_api_port") or "11211"
|
||||
local web_html_port = http.formvalue("web_html_port") or "11211"
|
||||
local web_api_addr = http.formvalue("web_api_addr") or "0.0.0.0"
|
||||
local web_html_addr = http.formvalue("web_html_addr") or "0.0.0.0"
|
||||
local web_fw_api = http.formvalue("web_fw_api") or "0"
|
||||
local web_api_host = http.formvalue("web_api_host") or ""
|
||||
local web_geoip_db = http.formvalue("web_geoip_db") or ""
|
||||
local web_disable_registration = http.formvalue("web_disable_registration") or "0"
|
||||
local web_allow_auto_create_user = http.formvalue("web_allow_auto_create_user") or "0"
|
||||
local web_weblog = http.formvalue("web_weblog") or "off"
|
||||
-- OIDC
|
||||
local web_oidc_enabled = http.formvalue("web_oidc_enabled") or "0"
|
||||
local web_oidc_issuer_url = http.formvalue("web_oidc_issuer_url") or ""
|
||||
local web_oidc_client_id = http.formvalue("web_oidc_client_id") or ""
|
||||
local web_oidc_client_secret = http.formvalue("web_oidc_client_secret") or ""
|
||||
local web_oidc_redirect_url = http.formvalue("web_oidc_redirect_url") or ""
|
||||
local web_oidc_username_claim = http.formvalue("web_oidc_username_claim") or "preferred_username"
|
||||
local web_oidc_scopes = http.formvalue("web_oidc_scopes") or "openid profile"
|
||||
local web_oidc_frontend_base_url = http.formvalue("web_oidc_frontend_base_url") or ""
|
||||
local web_oidc_disable_pkce = http.formvalue("web_oidc_disable_pkce") or "0"
|
||||
-- Webhook
|
||||
local web_webhook_enabled = http.formvalue("web_webhook_enabled") or "0"
|
||||
local web_webhook_url = http.formvalue("web_webhook_url") or ""
|
||||
local web_webhook_secret = http.formvalue("web_webhook_secret") or ""
|
||||
local web_internal_auth_token = http.formvalue("web_internal_auth_token") or ""
|
||||
local web_web_instance_id = http.formvalue("web_web_instance_id") or ""
|
||||
local web_web_instance_api_base_url = http.formvalue("web_web_instance_api_base_url") or ""
|
||||
|
||||
uci:set("easytier", "@easytier[0]", "web_enabled", web_enabled)
|
||||
uci:set("easytier", "@easytier[0]", "web_db_path", web_db_path)
|
||||
uci:set("easytier", "@easytier[0]", "web_protocol", web_protocol)
|
||||
uci:set("easytier", "@easytier[0]", "web_port", web_port)
|
||||
uci:set("easytier", "@easytier[0]", "web_fw_web", web_fw_web)
|
||||
uci:set("easytier", "@easytier[0]", "web_api_port", web_api_port)
|
||||
uci:set("easytier", "@easytier[0]", "web_html_port", web_html_port)
|
||||
uci:set("easytier", "@easytier[0]", "web_api_addr", web_api_addr)
|
||||
uci:set("easytier", "@easytier[0]", "web_html_addr", web_html_addr)
|
||||
uci:set("easytier", "@easytier[0]", "web_fw_api", web_fw_api)
|
||||
uci:set("easytier", "@easytier[0]", "web_api_host", web_api_host)
|
||||
uci:set("easytier", "@easytier[0]", "web_geoip_db", web_geoip_db)
|
||||
uci:set("easytier", "@easytier[0]", "web_disable_registration", web_disable_registration)
|
||||
uci:set("easytier", "@easytier[0]", "web_allow_auto_create_user", web_allow_auto_create_user)
|
||||
uci:set("easytier", "@easytier[0]", "web_weblog", web_weblog)
|
||||
-- OIDC
|
||||
uci:set("easytier", "@easytier[0]", "web_oidc_enabled", web_oidc_enabled)
|
||||
uci:set("easytier", "@easytier[0]", "web_oidc_issuer_url", web_oidc_issuer_url)
|
||||
uci:set("easytier", "@easytier[0]", "web_oidc_client_id", web_oidc_client_id)
|
||||
uci:set("easytier", "@easytier[0]", "web_oidc_client_secret", web_oidc_client_secret)
|
||||
uci:set("easytier", "@easytier[0]", "web_oidc_redirect_url", web_oidc_redirect_url)
|
||||
uci:set("easytier", "@easytier[0]", "web_oidc_username_claim", web_oidc_username_claim)
|
||||
uci:set("easytier", "@easytier[0]", "web_oidc_scopes", web_oidc_scopes)
|
||||
uci:set("easytier", "@easytier[0]", "web_oidc_frontend_base_url", web_oidc_frontend_base_url)
|
||||
uci:set("easytier", "@easytier[0]", "web_oidc_disable_pkce", web_oidc_disable_pkce)
|
||||
-- Webhook
|
||||
uci:set("easytier", "@easytier[0]", "web_webhook_enabled", web_webhook_enabled)
|
||||
uci:set("easytier", "@easytier[0]", "web_webhook_url", web_webhook_url)
|
||||
uci:set("easytier", "@easytier[0]", "web_webhook_secret", web_webhook_secret)
|
||||
uci:set("easytier", "@easytier[0]", "web_internal_auth_token", web_internal_auth_token)
|
||||
uci:set("easytier", "@easytier[0]", "web_web_instance_id", web_web_instance_id)
|
||||
uci:set("easytier", "@easytier[0]", "web_web_instance_api_base_url", web_web_instance_api_base_url)
|
||||
|
||||
uci:commit("easytier")
|
||||
|
||||
luci.sys.exec("/etc/init.d/easytier restart >/dev/null 2>&1 &")
|
||||
|
||||
http.prepare_content("application/json")
|
||||
http.write_json({success = true})
|
||||
end
|
||||
|
||||
function reset_database()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({success = true})
|
||||
|
||||
local json = require "luci.jsonc"
|
||||
local nixio = require "nixio"
|
||||
|
||||
-- 从请求中获取数据库路径
|
||||
local req_data = json.parse(luci.http.content())
|
||||
if not req_data or not req_data.db_path then
|
||||
luci.http.write_json({success = false, message = "Missing db_path parameter"})
|
||||
return
|
||||
end
|
||||
|
||||
local db_path = req_data.db_path
|
||||
|
||||
-- 安全检查:路径必须是绝对路径且不能是根目录或系统关键目录
|
||||
if not db_path:match("^/") or db_path == "/" or
|
||||
db_path:match("^/bin") or db_path:match("^/sbin") or
|
||||
db_path:match("^/usr/bin") or db_path:match("^/usr/sbin") or
|
||||
db_path:match("^/lib") or db_path:match("^/boot") then
|
||||
luci.http.write_json({success = false, message = "Invalid database path"})
|
||||
return
|
||||
end
|
||||
|
||||
-- 构建要删除的文件列表
|
||||
local files_to_delete = {
|
||||
db_path,
|
||||
db_path .. "-wal",
|
||||
db_path .. "-shm"
|
||||
}
|
||||
|
||||
local deleted_files = {}
|
||||
|
||||
-- 删除文件
|
||||
for _, file in ipairs(files_to_delete) do
|
||||
if nixio.fs.access(file) then
|
||||
local result = os.remove(file)
|
||||
if result then
|
||||
table.insert(deleted_files, file)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #deleted_files > 0 then
|
||||
luci.http.write_json({
|
||||
success = true,
|
||||
deleted_files = deleted_files,
|
||||
message = "Database reset successfully"
|
||||
})
|
||||
else
|
||||
luci.http.write_json({
|
||||
success = false,
|
||||
message = "No database files found or deletion failed"
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function check_web_status()
|
||||
|
||||
@ -5,7 +5,7 @@ m.description = translate("A simple, secure, decentralized VPN solution for intr
|
||||
.. "Project URL: <a href=\"https://github.com/EasyTier/EasyTier\" target=\"_blank\">github.com/EasyTier/EasyTier</a> "
|
||||
.. "<a href=\"http://easytier.cn\" target=\"_blank\">Official Documentation</a> "
|
||||
.. "<a href=\"http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=jhP2Z4UsEZ8wvfGPLrs0VwLKn_uz0Q_p&authKey=OGKSQLfg61YPCpVQuvx%2BxE7hUKBVBEVi9PljrDKbHlle6xqOXx8sOwPPTncMambK&noverify=0&group_code=949700262\" target=\"_blank\">QQ Group</a> ")
|
||||
.. "<a href=\"https://github.com/EasyTier/EasyTier/releases\" target=\"_blank\"><img alt=\"\" src=\"https://img.shields.io/github/v/tag/EasyTier/EasyTier?include_prereleases&logo=github&label=pre-releases&link=https%3A%2F%2Fgithub.com%2FEasyTier%2FEasyTier%2Freleases\" style=\"vertical-align:middle;\"></a> "
|
||||
.. "<a href=\"https://github.com/EasyTier/EasyTier/releases\" target=\"_blank\"><img alt=\"\" src=\"https://img.shields.io/github/v/tag/EasyTier/EasyTier?include_prereleases&logo=github&label=tag&link=https%3A%2F%2Fgithub.com%2FEasyTier%2FEasyTier%2Freleases\" style=\"vertical-align:middle;\"></a> "
|
||||
.. "<a href=\"https://github.com/EasyTier/EasyTier/releases\" target=\"_blank\"><img alt=\"\" src=\"https://img.shields.io/github/v/release/EasyTier/EasyTier?logo=github&link=https%3A%2F%2Fgithub.com%2FEasyTier%2FEasyTier%2Freleases\" style=\"vertical-align:middle;\"></a> "
|
||||
.. "<a href=\"https://github.com/EasyTier/luci-app-easytier/releases\" target=\"_blank\"><img alt=\"\" src=\"https://img.shields.io/github/v/release/EasyTier/luci-app-easytier?logo=openwrt&label=luci&link=https%3A%2F%2Fgithub.com%2FEasyTier%2Fluci-app-easytier%2Freleases\" style=\"vertical-align:middle;\"></a>"
|
||||
m.pageaction = false
|
||||
|
||||
@ -372,7 +372,7 @@ local translate = i18n.translate
|
||||
<label style="display:flex;align-items:center;font-size:13px;font-weight:500;color:var(--text-primary);margin-bottom:4px;">
|
||||
<span><%=translate("Fallback Version")%></span>
|
||||
<a href="https://github.com/EasyTier/EasyTier/releases" target="_blank" style="margin-left:8px;line-height:1;">
|
||||
<img alt="" src="https://img.shields.io/github/v/tag/EasyTier/EasyTier?include_prereleases&logo=github&label=pre-releases&link=https%3A%2F%2Fgithub.com%2FEasyTier%2FEasyTier%2Freleases" style="height:13px;vertical-align:middle;">
|
||||
<img alt="" src="https://img.shields.io/github/v/tag/EasyTier/EasyTier?include_prereleases&logo=github&label=tag&link=https%3A%2F%2Fgithub.com%2FEasyTier%2FEasyTier%2Freleases" style="height:13px;vertical-align:middle;">
|
||||
</a>
|
||||
<a href="https://github.com/EasyTier/EasyTier/releases" target="_blank" style="margin-left:4px;line-height:1;">
|
||||
<img alt="" src="https://img.shields.io/github/v/release/EasyTier/EasyTier?logo=github&link=https%3A%2F%2Fgithub.com%2FEasyTier%2FEasyTier%2Freleases" style="height:13px;vertical-align:middle;">
|
||||
@ -1378,7 +1378,7 @@ function cancelDownload() {
|
||||
xhr.open('POST', '<%=url("admin", "vpn", "easytier", "cancel_download")%>', true);
|
||||
xhr.onload = function() {
|
||||
closeDownloadModal();
|
||||
showAlert('info', '<%=translate("Download cancelled")%>');
|
||||
showAlert('info', '<%=translate("Cancelling download, may take up to 5 minutes to stop the current task")%>');
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
@ -388,6 +388,76 @@ input:disabled + .slider {
|
||||
color: white;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 9999;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.modal.show {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: var(--card-bg);
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
max-width: 500px;
|
||||
width: 90%;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.modal-message {
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 24px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.modal-buttons {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.modal-btn {
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.modal-btn:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.modal-btn-primary {
|
||||
background: var(--info);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.modal-btn-secondary {
|
||||
background: var(--border-color);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="web-console-container">
|
||||
@ -407,7 +477,12 @@ input:disabled + .slider {
|
||||
|
||||
<div class="form-group">
|
||||
<label for="web_db_path"><%:Database File Path%></label>
|
||||
<input type="text" class="form-control" id="web_db_path" name="web_db_path" placeholder="/etc/easytier/et.db">
|
||||
<div style="display:flex;gap:8px;align-items:flex-start;flex-wrap:wrap;">
|
||||
<input type="text" class="form-control" id="web_db_path" name="web_db_path" placeholder="/etc/easytier/et.db" style="flex:1;min-width:200px;">
|
||||
<button type="button" class="btn" onclick="showResetDbModal()" style="background:var(--error);color:white;padding:12px 16px;white-space:nowrap;">
|
||||
<%:Reset Database%>
|
||||
</button>
|
||||
</div>
|
||||
<span class="description"><%:Path to the sqlite3 database file used to store all data. (-d parameter)%></span>
|
||||
</div>
|
||||
|
||||
@ -427,7 +502,7 @@ input:disabled + .slider {
|
||||
<input type="number" class="form-control" id="web_port" name="web_port" placeholder="22020" min="1" max="65535">
|
||||
<span class="description"><%:Configure the server's listening port for easytier-core to connect. (-c parameter)%></span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<div class="checkbox-wrapper">
|
||||
<label for="web_fw_web"><%:WAN access to WEB%></label>
|
||||
@ -444,12 +519,26 @@ input:disabled + .slider {
|
||||
<input type="number" class="form-control" id="web_api_port" name="web_api_port" placeholder="11211" min="1" max="65535">
|
||||
<span class="description"><%:Listening port of the RESTful server, used as ApiHost by the web frontend. (-a parameter)%></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="web_api_addr"><%:API Listen Address%></label>
|
||||
<input type="text" class="form-control" id="web_api_addr" name="web_api_addr" placeholder="0.0.0.0">
|
||||
<span class="description"><%:Listen address for the RESTful server%>. (--api-server-addr <%:parameter%>)<br>
|
||||
<%:Example%>: 0.0.0.0 (<%:all interfaces%>), 127.0.0.1 (<%:localhost only%>), :: (<%:IPv6 all%>)</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="web_html_port"><%:Web Interface Port%></label>
|
||||
<input type="number" class="form-control" id="web_html_port" name="web_html_port" placeholder="11211" min="1" max="65535">
|
||||
<span class="description"><%:Frontend listening port for the web dashboard server. Leave empty to disable. (-l parameter)%></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="web_html_addr"><%:Web Listen Address%></label>
|
||||
<input type="text" class="form-control" id="web_html_addr" name="web_html_addr" placeholder="0.0.0.0">
|
||||
<span class="description"><%:Listen address for the web dashboard server%>. (--web-server-addr <%:parameter%>)<br>
|
||||
<%:Only effective when web port differs from API port or addresses differ%></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="checkbox-wrapper">
|
||||
@ -475,6 +564,28 @@ input:disabled + .slider {
|
||||
<span class="description"><%:GeoIP2 database file path used to locate the client%>. <%:Defaults to an embedded file (country-level information only)%>.<br>
|
||||
<%:Recommended%>: <a href="https://github.com/P3TERX/GeoLite.mmdb" target="_blank">https://github.com/P3TERX/GeoLite.mmdb</a> (--geoip-db <%:parameter%>)</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="checkbox-wrapper">
|
||||
<label for="web_disable_registration"><%:Disable User Registration%></label>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="web_disable_registration" name="web_disable_registration">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<span class="description"><%:Prevent new users from registering accounts%>. (--disable-registration <%:parameter%>)</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="checkbox-wrapper">
|
||||
<label for="web_allow_auto_create_user"><%:Allow Auto-create User%></label>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="web_allow_auto_create_user" name="web_allow_auto_create_user">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<span class="description"><%:Automatically create local user when easytier-core connects with an unknown username%>. (--allow-auto-create-user <%:parameter%>)</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="web_weblog"><%:Log Level%></label>
|
||||
@ -489,7 +600,130 @@ input:disabled + .slider {
|
||||
<span class="description"><%:Runtime log located at%> /tmp/easytierweb.log, <%:viewable in the log section%>.<br>
|
||||
<%:Log levels%>: <%:Error%> < <%:Warning%> < <%:Info%> < <%:Debug%> < <%:Trace%></span>
|
||||
</div>
|
||||
|
||||
<!-- OIDC单点登录配置 -->
|
||||
<div style="margin-top:32px;padding-top:24px;border-top:2px dashed var(--border-color);">
|
||||
<div class="form-group">
|
||||
<div class="checkbox-wrapper">
|
||||
<label for="web_oidc_enabled"><%:Enable OIDC Single Sign-On%></label>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="web_oidc_enabled" name="web_oidc_enabled" onchange="toggleOIDCFields()">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<span class="description"><%:Enable OIDC (OpenID Connect) for single sign-on authentication%></span>
|
||||
</div>
|
||||
|
||||
<div id="oidc_fields" style="display:none;">
|
||||
<div class="form-group">
|
||||
<label for="web_oidc_issuer_url"><%:OIDC Issuer URL%> *</label>
|
||||
<input type="text" class="form-control" id="web_oidc_issuer_url" name="web_oidc_issuer_url" placeholder="https://auth.example.com">
|
||||
<span class="description"><%:The OIDC issuer URL for single sign-on authentication%>. (--oidc-issuer-url <%:parameter%>)</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="web_oidc_client_id"><%:OIDC Client ID%> *</label>
|
||||
<input type="text" class="form-control" id="web_oidc_client_id" name="web_oidc_client_id" placeholder="easytier-client">
|
||||
<span class="description"><%:The OIDC client ID%>. (--oidc-client-id <%:parameter%>)</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="web_oidc_client_secret"><%:OIDC Client Secret%> *</label>
|
||||
<input type="password" class="form-control" id="web_oidc_client_secret" name="web_oidc_client_secret" placeholder="your-client-secret">
|
||||
<span class="description"><%:The OIDC client secret%>. (--oidc-client-secret <%:parameter%>)<br>
|
||||
<%:Can also be set via OIDC_CLIENT_SECRET environment variable%></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="web_oidc_redirect_url"><%:OIDC Redirect URL%> *</label>
|
||||
<input type="text" class="form-control" id="web_oidc_redirect_url" name="web_oidc_redirect_url" placeholder="http://your-domain.com:11211/api/v1/auth/oidc/callback">
|
||||
<span class="description"><%:The OIDC redirect URL (callback URL), must match exactly what is registered with your Identity Provider%>. (--oidc-redirect-url <%:parameter%>)<br>
|
||||
<%:Example%>: http://your-domain.com:11211/api/v1/auth/oidc/callback</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="web_oidc_username_claim"><%:OIDC Username Claim%></label>
|
||||
<input type="text" class="form-control" id="web_oidc_username_claim" name="web_oidc_username_claim" placeholder="preferred_username">
|
||||
<span class="description"><%:The OIDC claim to use as the local username%>. (--oidc-username-claim <%:parameter%>)<br>
|
||||
<%:Default%>: preferred_username</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="web_oidc_scopes"><%:OIDC Scopes%></label>
|
||||
<input type="text" class="form-control" id="web_oidc_scopes" name="web_oidc_scopes" placeholder="openid profile">
|
||||
<span class="description"><%:OIDC scopes to request during login%>. (--oidc-scopes <%:parameter%>)<br>
|
||||
<%:Supports comma-separated values%>. <%:Default%>: openid profile</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="web_oidc_frontend_base_url"><%:OIDC Frontend Base URL%></label>
|
||||
<input type="text" class="form-control" id="web_oidc_frontend_base_url" name="web_oidc_frontend_base_url" placeholder="http://your-domain.com:11211">
|
||||
<span class="description"><%:Frontend base URL to redirect to after successful OIDC callback%>. (--oidc-frontend-base-url <%:parameter%>)<br>
|
||||
<%:Required when frontend and API are deployed separately%></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="checkbox-wrapper">
|
||||
<label for="web_oidc_disable_pkce"><%:Disable PKCE%></label>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="web_oidc_disable_pkce" name="web_oidc_disable_pkce">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<span class="description"><%:Disable PKCE (Proof Key for Code Exchange) for OIDC authentication%>. (--oidc-disable-pkce <%:parameter%>)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Webhook高级配置 -->
|
||||
<div style="margin-top:32px;padding-top:24px;border-top:2px dashed var(--border-color);">
|
||||
<div class="form-group">
|
||||
<div class="checkbox-wrapper">
|
||||
<label for="web_webhook_enabled"><%:Enable Webhook Integration%></label>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="web_webhook_enabled" name="web_webhook_enabled" onchange="toggleWebhookFields()">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<span class="description"><%:Enable webhook for token validation and event delivery%></span>
|
||||
</div>
|
||||
|
||||
<div id="webhook_fields" style="display:none;">
|
||||
<div class="form-group">
|
||||
<label for="web_webhook_url"><%:Webhook URL%></label>
|
||||
<input type="text" class="form-control" id="web_webhook_url" name="web_webhook_url" placeholder="https://webhook.example.com/easytier">
|
||||
<span class="description"><%:Base URL of the webhook endpoint for token validation and event delivery%>. (--webhook-url <%:parameter%>)<br>
|
||||
<%:When set, incoming tokens are validated via this webhook before local fallback%></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="web_webhook_secret"><%:Webhook Secret%></label>
|
||||
<input type="password" class="form-control" id="web_webhook_secret" name="web_webhook_secret" placeholder="your-webhook-secret">
|
||||
<span class="description"><%:Shared secret used to authenticate outbound webhook calls%>. (--webhook-secret <%:parameter%>)</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="web_internal_auth_token"><%:Internal Auth Token%></label>
|
||||
<input type="password" class="form-control" id="web_internal_auth_token" name="web_internal_auth_token" placeholder="your-internal-token">
|
||||
<span class="description"><%:Token for X-Internal-Auth header%>. (--internal-auth-token <%:parameter%>)<br>
|
||||
<%:When set, API requests with this header bypass session authentication%></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="web_web_instance_id"><%:Web Instance ID%></label>
|
||||
<input type="text" class="form-control" id="web_web_instance_id" name="web_web_instance_id" placeholder="instance-1">
|
||||
<span class="description"><%:Stable identifier for this easytier-web instance when routing webhook callbacks%>. (--web-instance-id <%:parameter%>)</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="web_web_instance_api_base_url"><%:Web Instance API Base URL%></label>
|
||||
<input type="text" class="form-control" id="web_web_instance_api_base_url" name="web_web_instance_api_base_url" placeholder="http://192.168.1.1:11211">
|
||||
<span class="description"><%:Reachable base URL for this easytier-web instance's internal REST API%>. (--web-instance-api-base-url <%:parameter%>)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary" onclick="saveConfig()"><%:Save Configuration%></button>
|
||||
</div>
|
||||
@ -506,6 +740,40 @@ input:disabled + .slider {
|
||||
<!-- 提示框 -->
|
||||
<div id="alert_box" class="alert"></div>
|
||||
|
||||
<!-- 重置数据库模态窗口 -->
|
||||
<div class="modal" id="reset_db_modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-title" style="color:var(--error);">⚠️ <%:Warning%></div>
|
||||
<div class="modal-message">
|
||||
<div style="color:var(--error);font-weight:600;margin-bottom:12px;">
|
||||
<%:Are you sure you want to reset the database?%>
|
||||
</div>
|
||||
<div style="font-size:13px;line-height:1.6;color:var(--text-secondary);">
|
||||
<%:This will delete all database files and cannot be recovered%>:<br>
|
||||
<code id="reset_db_files" style="display:block;margin-top:8px;padding:8px;background:var(--hover-bg);border-radius:4px;word-break:break-all;font-size:12px;"></code>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-buttons">
|
||||
<button class="modal-btn modal-btn-secondary" onclick="closeResetDbModal()"><%:Cancel%></button>
|
||||
<button class="modal-btn" onclick="confirmResetDb()" style="background:var(--error);color:white;"><%:Delete%></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 重启服务模态窗口 -->
|
||||
<div class="modal" id="restart_web_modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-title"><%:Database Reset Successful%></div>
|
||||
<div class="modal-message">
|
||||
<pre id="restart_web_message" style="white-space:pre-wrap;word-break:break-all;font-size:13px;line-height:1.6;"></pre>
|
||||
</div>
|
||||
<div class="modal-buttons">
|
||||
<button class="modal-btn modal-btn-secondary" onclick="closeRestartModal()"><%:Later%></button>
|
||||
<button class="modal-btn modal-btn-primary" onclick="restartWebService()"><%:Restart Now%></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var originalConfig = {};
|
||||
|
||||
@ -539,12 +807,37 @@ function loadConfig() {
|
||||
document.getElementById('web_port').value = data.web_port || '22020';
|
||||
document.getElementById('web_fw_web').checked = data.web_fw_web === '1';
|
||||
document.getElementById('web_api_port').value = data.web_api_port || '11211';
|
||||
document.getElementById('web_api_addr').value = data.web_api_addr || '0.0.0.0';
|
||||
document.getElementById('web_html_port').value = data.web_html_port || '11211';
|
||||
document.getElementById('web_html_addr').value = data.web_html_addr || '0.0.0.0';
|
||||
document.getElementById('web_fw_api').checked = data.web_fw_api === '1';
|
||||
document.getElementById('web_api_host').value = data.web_api_host || '';
|
||||
document.getElementById('web_geoip_db').value = data.web_geoip_db || '';
|
||||
document.getElementById('web_disable_registration').checked = data.web_disable_registration === '1';
|
||||
document.getElementById('web_allow_auto_create_user').checked = data.web_allow_auto_create_user === '1';
|
||||
document.getElementById('web_weblog').value = data.web_weblog || 'off';
|
||||
|
||||
// OIDC配置
|
||||
document.getElementById('web_oidc_enabled').checked = data.web_oidc_enabled === '1';
|
||||
document.getElementById('web_oidc_issuer_url').value = data.web_oidc_issuer_url || '';
|
||||
document.getElementById('web_oidc_client_id').value = data.web_oidc_client_id || '';
|
||||
document.getElementById('web_oidc_client_secret').value = data.web_oidc_client_secret || '';
|
||||
document.getElementById('web_oidc_redirect_url').value = data.web_oidc_redirect_url || '';
|
||||
document.getElementById('web_oidc_username_claim').value = data.web_oidc_username_claim || 'preferred_username';
|
||||
document.getElementById('web_oidc_scopes').value = data.web_oidc_scopes || 'openid profile';
|
||||
document.getElementById('web_oidc_frontend_base_url').value = data.web_oidc_frontend_base_url || '';
|
||||
document.getElementById('web_oidc_disable_pkce').checked = data.web_oidc_disable_pkce === '1';
|
||||
toggleOIDCFields();
|
||||
|
||||
// Webhook配置
|
||||
document.getElementById('web_webhook_enabled').checked = data.web_webhook_enabled === '1';
|
||||
document.getElementById('web_webhook_url').value = data.web_webhook_url || '';
|
||||
document.getElementById('web_webhook_secret').value = data.web_webhook_secret || '';
|
||||
document.getElementById('web_internal_auth_token').value = data.web_internal_auth_token || '';
|
||||
document.getElementById('web_web_instance_id').value = data.web_web_instance_id || '';
|
||||
document.getElementById('web_web_instance_api_base_url').value = data.web_web_instance_api_base_url || '';
|
||||
toggleWebhookFields();
|
||||
|
||||
// 保存原始配置
|
||||
originalConfig = JSON.parse(JSON.stringify(data));
|
||||
|
||||
@ -562,11 +855,32 @@ function getCurrentConfig() {
|
||||
web_port: document.getElementById('web_port').value,
|
||||
web_fw_web: document.getElementById('web_fw_web').checked ? '1' : '0',
|
||||
web_api_port: document.getElementById('web_api_port').value,
|
||||
web_api_addr: document.getElementById('web_api_addr').value,
|
||||
web_html_port: document.getElementById('web_html_port').value,
|
||||
web_html_addr: document.getElementById('web_html_addr').value,
|
||||
web_fw_api: document.getElementById('web_fw_api').checked ? '1' : '0',
|
||||
web_api_host: document.getElementById('web_api_host').value,
|
||||
web_geoip_db: document.getElementById('web_geoip_db').value,
|
||||
web_weblog: document.getElementById('web_weblog').value
|
||||
web_disable_registration: document.getElementById('web_disable_registration').checked ? '1' : '0',
|
||||
web_allow_auto_create_user: document.getElementById('web_allow_auto_create_user').checked ? '1' : '0',
|
||||
web_weblog: document.getElementById('web_weblog').value,
|
||||
// OIDC
|
||||
web_oidc_enabled: document.getElementById('web_oidc_enabled').checked ? '1' : '0',
|
||||
web_oidc_issuer_url: document.getElementById('web_oidc_issuer_url').value,
|
||||
web_oidc_client_id: document.getElementById('web_oidc_client_id').value,
|
||||
web_oidc_client_secret: document.getElementById('web_oidc_client_secret').value,
|
||||
web_oidc_redirect_url: document.getElementById('web_oidc_redirect_url').value,
|
||||
web_oidc_username_claim: document.getElementById('web_oidc_username_claim').value,
|
||||
web_oidc_scopes: document.getElementById('web_oidc_scopes').value,
|
||||
web_oidc_frontend_base_url: document.getElementById('web_oidc_frontend_base_url').value,
|
||||
web_oidc_disable_pkce: document.getElementById('web_oidc_disable_pkce').checked ? '1' : '0',
|
||||
// Webhook
|
||||
web_webhook_enabled: document.getElementById('web_webhook_enabled').checked ? '1' : '0',
|
||||
web_webhook_url: document.getElementById('web_webhook_url').value,
|
||||
web_webhook_secret: document.getElementById('web_webhook_secret').value,
|
||||
web_internal_auth_token: document.getElementById('web_internal_auth_token').value,
|
||||
web_web_instance_id: document.getElementById('web_web_instance_id').value,
|
||||
web_web_instance_api_base_url: document.getElementById('web_web_instance_api_base_url').value
|
||||
};
|
||||
}
|
||||
|
||||
@ -608,6 +922,22 @@ function saveConfig() {
|
||||
xhr.send(formData);
|
||||
}
|
||||
|
||||
function toggleOIDCFields() {
|
||||
var enabled = document.getElementById('web_oidc_enabled').checked;
|
||||
var fields = document.getElementById('oidc_fields');
|
||||
if (fields) {
|
||||
fields.style.display = enabled ? 'block' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function toggleWebhookFields() {
|
||||
var enabled = document.getElementById('web_webhook_enabled').checked;
|
||||
var fields = document.getElementById('webhook_fields');
|
||||
if (fields) {
|
||||
fields.style.display = enabled ? 'block' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function checkWebStatus() {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', '<%=url("admin", "vpn", "easytier", "check_web_status")%>', true);
|
||||
@ -635,6 +965,119 @@ function checkWebStatus() {
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function showResetDbModal() {
|
||||
var dbPath = document.getElementById('web_db_path').value || '/etc/easytier/et.db';
|
||||
var files = [
|
||||
dbPath,
|
||||
dbPath + '-wal',
|
||||
dbPath + '-shm'
|
||||
];
|
||||
document.getElementById('reset_db_files').textContent = files.join('\n');
|
||||
document.getElementById('reset_db_modal').classList.add('show');
|
||||
}
|
||||
|
||||
function closeResetDbModal() {
|
||||
document.getElementById('reset_db_modal').classList.remove('show');
|
||||
}
|
||||
|
||||
function confirmResetDb() {
|
||||
var dbPath = document.getElementById('web_db_path').value || '/etc/easytier/et.db';
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', '<%=url("admin", "vpn", "easytier", "reset_database")%>', true);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.onload = function() {
|
||||
closeResetDbModal();
|
||||
if (xhr.status === 200) {
|
||||
try {
|
||||
var response = JSON.parse(xhr.responseText);
|
||||
if (response.success) {
|
||||
// 检查web服务是否运行
|
||||
checkWebStatusForRestart(response.deleted_files);
|
||||
} else {
|
||||
showAlert('error', response.message || '<%:Reset failed%>');
|
||||
}
|
||||
} catch (e) {
|
||||
showAlert('error', '<%:Reset failed%>');
|
||||
}
|
||||
} else {
|
||||
showAlert('error', '<%:Reset failed%>');
|
||||
}
|
||||
};
|
||||
xhr.onerror = function() {
|
||||
closeResetDbModal();
|
||||
showAlert('error', '<%:Network error%>');
|
||||
};
|
||||
xhr.send(JSON.stringify({db_path: dbPath}));
|
||||
}
|
||||
|
||||
function checkWebStatusForRestart(deletedFiles) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', '<%=url("admin", "vpn", "easytier", "check_web_status")%>', true);
|
||||
xhr.onload = function() {
|
||||
if (xhr.status === 200) {
|
||||
try {
|
||||
var data = JSON.parse(xhr.responseText);
|
||||
if (data.running) {
|
||||
// Web服务正在运行,弹出重启确认
|
||||
showRestartModal(deletedFiles);
|
||||
} else {
|
||||
// Web服务未运行,只显示成功提示
|
||||
var message = '<%:Database reset successfully%>\n' + deletedFiles.join('\n');
|
||||
showAlert('success', message);
|
||||
}
|
||||
} catch (e) {
|
||||
// 检查失败,只显示成功提示
|
||||
var message = '<%:Database reset successfully%>\n' + deletedFiles.join('\n');
|
||||
showAlert('success', message);
|
||||
}
|
||||
} else {
|
||||
// 检查失败,只显示成功提示
|
||||
var message = '<%:Database reset successfully%>\n' + deletedFiles.join('\n');
|
||||
showAlert('success', message);
|
||||
}
|
||||
};
|
||||
xhr.onerror = function() {
|
||||
// 检查失败,只显示成功提示
|
||||
var message = '<%:Database reset successfully%>\n' + deletedFiles.join('\n');
|
||||
showAlert('success', message);
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function showRestartModal(deletedFiles) {
|
||||
var modal = document.getElementById('restart_web_modal');
|
||||
var message = document.getElementById('restart_web_message');
|
||||
message.textContent = '<%:Database reset successfully%>\n' + deletedFiles.join('\n') + '\n\n<%:Restart service to apply changes?%>';
|
||||
modal.classList.add('show');
|
||||
}
|
||||
|
||||
function closeRestartModal() {
|
||||
document.getElementById('restart_web_modal').classList.remove('show');
|
||||
}
|
||||
|
||||
function restartWebService() {
|
||||
closeRestartModal();
|
||||
showAlert('info', '<%:Restarting service...%>');
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', '<%=url("admin", "vpn", "easytier", "restart_service")%>', true);
|
||||
xhr.onload = function() {
|
||||
if (xhr.status === 200) {
|
||||
setTimeout(function() {
|
||||
showAlert('success', '<%:Service restarted successfully%>');
|
||||
}, 2000);
|
||||
} else {
|
||||
showAlert('error', '<%:Restart failed%>');
|
||||
}
|
||||
};
|
||||
xhr.onerror = function() {
|
||||
showAlert('error', '<%:Restart failed%>');
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
loadConfig();
|
||||
checkWebStatus();
|
||||
|
||||
@ -94,14 +94,6 @@ msgstr "检测IP"
|
||||
msgid "Check for Updates"
|
||||
msgstr "检测更新"
|
||||
|
||||
#: applications/luci-app-easytier/luasrc/view/easytier/easytier_log.htm:31
|
||||
#: applications/luci-app-easytier/luasrc/view/easytier/easytierweb_log.htm:31
|
||||
msgid "Clear Logs"
|
||||
msgstr "清除日志"
|
||||
|
||||
msgid "Download Log"
|
||||
msgstr "下载日志"
|
||||
|
||||
#: applications/luci-app-easytier/luasrc/view/easytier/easytier_status.htm:35
|
||||
msgid "Collecting data..."
|
||||
msgstr "正在获取中..."
|
||||
@ -478,12 +470,6 @@ msgstr "监听端口"
|
||||
msgid "Listening Protocol"
|
||||
msgstr "监听协议"
|
||||
|
||||
#: applications/luci-app-easytier/luasrc/model/cbi/easytier.lua:710
|
||||
msgid ""
|
||||
"Listening port of the RESTful server, used as ApiHost by the web frontend. (-"
|
||||
"a parameter)"
|
||||
msgstr "restful 服务器的监听端口,作为 ApiHost 并被 web 前端使用。( -a 参数)"
|
||||
|
||||
#: applications/luci-app-easytier/luasrc/model/cbi/easytier.lua:564
|
||||
msgid "Local Startup Parameters"
|
||||
msgstr "本机启动参数"
|
||||
@ -747,10 +733,6 @@ msgid ""
|
||||
"console, for issuing configuration files"
|
||||
msgstr "连接web控制台时识别此设备的唯一标识,用于下发配置文件"
|
||||
|
||||
#: applications/luci-app-easytier/luasrc/view/easytier/other_upload.htm:4
|
||||
msgid "Upload"
|
||||
msgstr "上传"
|
||||
|
||||
#: applications/luci-app-easytier/luasrc/model/cbi/easytier.lua:20
|
||||
msgid "Upload Program"
|
||||
msgstr "上传程序"
|
||||
@ -826,10 +808,6 @@ msgstr "警告"
|
||||
msgid "Web Configuration"
|
||||
msgstr "Web配置"
|
||||
|
||||
#: applications/luci-app-easytier/luasrc/view/easytier/easytier_status.htm:25
|
||||
msgid "Web Console"
|
||||
msgstr "Web 控制台"
|
||||
|
||||
#: applications/luci-app-easytier/luasrc/model/cbi/easytier.lua:726
|
||||
msgid "Web Interface Port"
|
||||
msgstr "web界面端口"
|
||||
@ -1037,9 +1015,6 @@ msgstr "自建控制台"
|
||||
msgid "All Levels"
|
||||
msgstr "全部级别"
|
||||
|
||||
msgid "Auto Refresh"
|
||||
msgstr "自动刷新"
|
||||
|
||||
msgid "Stop Auto Refresh"
|
||||
msgstr "停止自动刷新"
|
||||
|
||||
@ -1097,9 +1072,6 @@ msgstr "Web 控制台主页"
|
||||
msgid "Service not running"
|
||||
msgstr "服务未运行"
|
||||
|
||||
msgid "Collecting data..."
|
||||
msgstr "收集数据..."
|
||||
|
||||
msgid "New"
|
||||
msgstr "发现新版本"
|
||||
|
||||
@ -1121,9 +1093,6 @@ msgstr "请稍候,操作进行中..."
|
||||
msgid "Restarting service..."
|
||||
msgstr "正在重启服务..."
|
||||
|
||||
msgid "Upload Program"
|
||||
msgstr "上传程序"
|
||||
|
||||
msgid "Upload EasyTier Binary"
|
||||
msgstr "上传 EasyTier 程序"
|
||||
|
||||
@ -1178,9 +1147,6 @@ msgstr "仅允许上传 easytier 相关程序文件或压缩包(.zip、.tar.gz
|
||||
msgid "Upload failed"
|
||||
msgstr "上传失败"
|
||||
|
||||
msgid "Network error"
|
||||
msgstr "网络错误"
|
||||
|
||||
msgid "Service restarted successfully"
|
||||
msgstr "服务重启成功"
|
||||
|
||||
@ -1193,9 +1159,6 @@ msgstr "没有需要保存的更改"
|
||||
msgid "Configuration"
|
||||
msgstr "配置"
|
||||
|
||||
msgid "Save Configuration"
|
||||
msgstr "保存并应用"
|
||||
|
||||
msgid "Configuration saved successfully"
|
||||
msgstr "配置保存成功"
|
||||
|
||||
@ -1223,9 +1186,6 @@ msgstr "包含EasyTier相关程序的压缩包"
|
||||
msgid "Drag *.tar.gz / *.zip / easytier binaries here or click to select file"
|
||||
msgstr "支持拖放 *.tar.gz / *.zip 压缩包和 easytier 二进制程序到此处,或点击选择文件"
|
||||
|
||||
msgid "Used when unable to fetch the latest version during online download"
|
||||
msgstr "在线下载时无法获取最新版本时使用的回退版本"
|
||||
|
||||
msgid "Error: Program not running! Please start the program and refresh"
|
||||
msgstr "错误:程序未运行!请先启动程序后刷新"
|
||||
|
||||
@ -1277,9 +1237,6 @@ msgstr "GeoIP 数据库路径"
|
||||
msgid "Connection Information"
|
||||
msgstr "连接信息"
|
||||
|
||||
msgid "Node Info"
|
||||
msgstr "本机信息"
|
||||
|
||||
msgid "Peer List"
|
||||
msgstr "节点列表"
|
||||
|
||||
@ -1445,9 +1402,6 @@ msgstr "值"
|
||||
msgid "Labels"
|
||||
msgstr "标签"
|
||||
|
||||
msgid "Listener"
|
||||
msgstr "监听器"
|
||||
|
||||
msgid "Client Config Start"
|
||||
msgstr "客户端配置开始"
|
||||
|
||||
@ -1688,9 +1642,6 @@ msgstr "无"
|
||||
msgid "Domain"
|
||||
msgstr "域名"
|
||||
|
||||
msgid "Failed to connect to RPC server. Please check if the RPC port is set to 15888 in the configuration."
|
||||
msgstr "无法连接到 RPC 服务器,请检查配置中的 RPC 端口是否设置为 15888"
|
||||
|
||||
msgid "Configuration File Content"
|
||||
msgstr "配置文件内容"
|
||||
|
||||
@ -1719,7 +1670,7 @@ msgid "Fallback Version"
|
||||
msgstr "备用版本"
|
||||
|
||||
msgid "Used when unable to fetch the latest version during online download"
|
||||
msgstr "用于无法获取GitHub最新版本时在线下载使用的版本"
|
||||
msgstr "用于启动脚本里无法获取GitHub最新版本时在线下载回退使用的版本"
|
||||
|
||||
msgid "Save Configuration"
|
||||
msgstr "保存并应用"
|
||||
@ -1965,6 +1916,9 @@ msgstr "取消下载"
|
||||
msgid "Download cancelled"
|
||||
msgstr "已取消下载"
|
||||
|
||||
msgid "Cancelling download, may take up to 5 minutes to stop the current task"
|
||||
msgstr "正在取消下载,当前任务可能需要最多5分钟才能停止"
|
||||
|
||||
msgid "All download attempts failed"
|
||||
msgstr "所有下载地址均下载失败,请确认github加速镜像地址有效或使用手动上传"
|
||||
|
||||
@ -1979,3 +1933,169 @@ msgstr "重试"
|
||||
|
||||
msgid "Close"
|
||||
msgstr "关闭"
|
||||
|
||||
msgid "API Listen Address"
|
||||
msgstr "API监听地址"
|
||||
|
||||
msgid "Listen address for the RESTful server"
|
||||
msgstr "RESTful服务器的监听地址"
|
||||
|
||||
msgid "all interfaces"
|
||||
msgstr "所有接口"
|
||||
|
||||
msgid "localhost only"
|
||||
msgstr "仅本地"
|
||||
|
||||
msgid "IPv6 all"
|
||||
msgstr "IPv6所有接口"
|
||||
|
||||
msgid "Web Listen Address"
|
||||
msgstr "Web监听地址"
|
||||
|
||||
msgid "Listen address for the web dashboard server"
|
||||
msgstr "Web控制台服务器的监听地址"
|
||||
|
||||
msgid "Only effective when web port differs from API port or addresses differ"
|
||||
msgstr "仅在Web端口与API端口不同或地址不同时生效"
|
||||
|
||||
msgid "Disable User Registration"
|
||||
msgstr "禁用用户注册"
|
||||
|
||||
msgid "Prevent new users from registering accounts"
|
||||
msgstr "阻止新用户注册账户"
|
||||
|
||||
msgid "Allow Auto-create User"
|
||||
msgstr "允许自动创建用户"
|
||||
|
||||
msgid "Automatically create local user when easytier-core connects with an unknown username"
|
||||
msgstr "当easytier-core使用未知用户名连接时自动创建本地用户"
|
||||
|
||||
msgid "Enable OIDC Single Sign-On"
|
||||
msgstr "启用OIDC单点登录"
|
||||
|
||||
msgid "Enable OIDC (OpenID Connect) for single sign-on authentication"
|
||||
msgstr "启用OIDC(OpenID Connect)单点登录认证"
|
||||
|
||||
msgid "OIDC Issuer URL"
|
||||
msgstr "OIDC发行者URL"
|
||||
|
||||
msgid "The OIDC issuer URL for single sign-on authentication"
|
||||
msgstr "用于单点登录认证的OIDC发行者URL"
|
||||
|
||||
msgid "OIDC Client ID"
|
||||
msgstr "OIDC客户端ID"
|
||||
|
||||
msgid "The OIDC client ID"
|
||||
msgstr "OIDC客户端ID"
|
||||
|
||||
msgid "OIDC Client Secret"
|
||||
msgstr "OIDC客户端密钥"
|
||||
|
||||
msgid "The OIDC client secret"
|
||||
msgstr "OIDC客户端密钥"
|
||||
|
||||
msgid "Can also be set via OIDC_CLIENT_SECRET environment variable"
|
||||
msgstr "也可以通过OIDC_CLIENT_SECRET环境变量设置"
|
||||
|
||||
msgid "OIDC Redirect URL"
|
||||
msgstr "OIDC重定向URL"
|
||||
|
||||
msgid "The OIDC redirect URL (callback URL), must match exactly what is registered with your Identity Provider"
|
||||
msgstr "OIDC重定向URL(回调URL),必须与身份提供商注册的完全匹配"
|
||||
|
||||
msgid "OIDC Username Claim"
|
||||
msgstr "OIDC用户名声明"
|
||||
|
||||
msgid "The OIDC claim to use as the local username"
|
||||
msgstr "用作本地用户名的OIDC声明"
|
||||
|
||||
msgid "OIDC Scopes"
|
||||
msgstr "OIDC作用域"
|
||||
|
||||
msgid "OIDC scopes to request during login"
|
||||
msgstr "登录时请求的OIDC作用域"
|
||||
|
||||
msgid "Supports comma-separated values"
|
||||
msgstr "支持逗号分隔的值"
|
||||
|
||||
msgid "OIDC Frontend Base URL"
|
||||
msgstr "OIDC前端基础URL"
|
||||
|
||||
msgid "Frontend base URL to redirect to after successful OIDC callback"
|
||||
msgstr "OIDC回调成功后重定向到的前端基础URL"
|
||||
|
||||
msgid "Required when frontend and API are deployed separately"
|
||||
msgstr "当前端和API分开部署时需要"
|
||||
|
||||
msgid "Disable PKCE"
|
||||
msgstr "禁用PKCE"
|
||||
|
||||
msgid "Disable PKCE (Proof Key for Code Exchange) for OIDC authentication"
|
||||
msgstr "禁用OIDC认证的PKCE(代码交换证明密钥)"
|
||||
|
||||
msgid "Enable Webhook Integration"
|
||||
msgstr "启用Webhook集成"
|
||||
|
||||
msgid "Enable webhook for token validation and event delivery"
|
||||
msgstr "启用webhook进行令牌验证和事件传递"
|
||||
|
||||
msgid "Webhook URL"
|
||||
msgstr "Webhook URL"
|
||||
|
||||
msgid "Base URL of the webhook endpoint for token validation and event delivery"
|
||||
msgstr "用于令牌验证和事件传递的webhook端点基础URL"
|
||||
|
||||
msgid "When set, incoming tokens are validated via this webhook before local fallback"
|
||||
msgstr "设置后,传入的令牌将通过此webhook验证,然后再进行本地回退"
|
||||
|
||||
msgid "Webhook Secret"
|
||||
msgstr "Webhook密钥"
|
||||
|
||||
msgid "Shared secret used to authenticate outbound webhook calls"
|
||||
msgstr "用于验证出站webhook调用的共享密钥"
|
||||
|
||||
msgid "Internal Auth Token"
|
||||
msgstr "内部认证令牌"
|
||||
|
||||
msgid "Token for X-Internal-Auth header"
|
||||
msgstr "X-Internal-Auth头的令牌"
|
||||
|
||||
msgid "When set, API requests with this header bypass session authentication"
|
||||
msgstr "设置后,带有此头的API请求将绕过会话认证"
|
||||
|
||||
msgid "Web Instance ID"
|
||||
msgstr "Web实例ID"
|
||||
|
||||
msgid "Stable identifier for this easytier-web instance when routing webhook callbacks"
|
||||
msgstr "路由webhook回调时此easytier-web实例的稳定标识符"
|
||||
|
||||
msgid "Web Instance API Base URL"
|
||||
msgstr "Web实例API基础URL"
|
||||
|
||||
msgid "Reachable base URL for this easytier-web instance's internal REST API"
|
||||
msgstr "此easytier-web实例内部REST API的可访问基础URL"
|
||||
|
||||
msgid "Reset Database"
|
||||
msgstr "重置数据库"
|
||||
|
||||
msgid "Are you sure you want to reset the database?"
|
||||
msgstr "确定要重置数据库吗?"
|
||||
|
||||
msgid "This will delete all database files and cannot be recovered"
|
||||
msgstr "这将删除所有数据库文件,不可恢复"
|
||||
|
||||
msgid "Database reset successfully"
|
||||
msgstr "数据库重置成功"
|
||||
|
||||
msgid "Reset failed"
|
||||
msgstr "重置失败"
|
||||
|
||||
msgid "No database files found or deletion failed"
|
||||
msgstr "未找到数据库文件或删除失败"
|
||||
|
||||
msgid "Database Reset Successful"
|
||||
msgstr "数据库重置成功"
|
||||
|
||||
msgid "Restart service to apply changes?"
|
||||
msgstr "重启服务以生效?"
|
||||
|
||||
|
||||
@ -658,11 +658,34 @@ start_web() {
|
||||
api_port="$(uci -q get easytier.@easytier[0].web_api_port)"
|
||||
html_port="$(uci -q get easytier.@easytier[0].web_html_port)"
|
||||
weblog="$(uci -q get easytier.@easytier[0].web_weblog)"
|
||||
weblog="${weblog:-off}"
|
||||
weblog="${weblog:-off}"
|
||||
api_host="$(uci -q get easytier.@easytier[0].web_api_host)"
|
||||
geoip_db="$(uci -q get easytier.@easytier[0].web_geoip_db)"
|
||||
fw_web="$(uci -q get easytier.@easytier[0].web_fw_web || echo 0)"
|
||||
fw_api="$(uci -q get easytier.@easytier[0].web_fw_api || echo 0)"
|
||||
|
||||
api_addr="$(uci -q get easytier.@easytier[0].web_api_addr)"
|
||||
html_addr="$(uci -q get easytier.@easytier[0].web_html_addr)"
|
||||
disable_registration="$(uci -q get easytier.@easytier[0].web_disable_registration || echo 0)"
|
||||
allow_auto_create_user="$(uci -q get easytier.@easytier[0].web_allow_auto_create_user || echo 0)"
|
||||
# OIDC配置
|
||||
oidc_enabled="$(uci -q get easytier.@easytier[0].web_oidc_enabled || echo 0)"
|
||||
oidc_issuer_url="$(uci -q get easytier.@easytier[0].web_oidc_issuer_url)"
|
||||
oidc_client_id="$(uci -q get easytier.@easytier[0].web_oidc_client_id)"
|
||||
oidc_client_secret="$(uci -q get easytier.@easytier[0].web_oidc_client_secret)"
|
||||
oidc_redirect_url="$(uci -q get easytier.@easytier[0].web_oidc_redirect_url)"
|
||||
oidc_username_claim="$(uci -q get easytier.@easytier[0].web_oidc_username_claim)"
|
||||
oidc_scopes="$(uci -q get easytier.@easytier[0].web_oidc_scopes)"
|
||||
oidc_frontend_base_url="$(uci -q get easytier.@easytier[0].web_oidc_frontend_base_url)"
|
||||
oidc_disable_pkce="$(uci -q get easytier.@easytier[0].web_oidc_disable_pkce || echo 0)"
|
||||
# Webhook配置
|
||||
webhook_enabled="$(uci -q get easytier.@easytier[0].web_webhook_enabled || echo 0)"
|
||||
webhook_url="$(uci -q get easytier.@easytier[0].web_webhook_url)"
|
||||
webhook_secret="$(uci -q get easytier.@easytier[0].web_webhook_secret)"
|
||||
internal_auth_token="$(uci -q get easytier.@easytier[0].web_internal_auth_token)"
|
||||
web_instance_id="$(uci -q get easytier.@easytier[0].web_web_instance_id)"
|
||||
web_instance_api_base_url="$(uci -q get easytier.@easytier[0].web_web_instance_api_base_url)"
|
||||
|
||||
procd_open_instance "easytier_web"
|
||||
get_tz
|
||||
[ -z "$SET_TZ" ] || procd_set_param env TZ="$SET_TZ"
|
||||
@ -678,6 +701,31 @@ start_web() {
|
||||
else
|
||||
web_cmd="${web_cmd} -l $html_port"
|
||||
fi
|
||||
# 基础配置参数
|
||||
[ -n "$api_addr" ] && [ "$api_addr" != "0.0.0.0" ] && web_cmd="${web_cmd} --api-server-addr $api_addr"
|
||||
[ -n "$html_addr" ] && [ "$html_addr" != "0.0.0.0" ] && web_cmd="${web_cmd} --web-server-addr $html_addr"
|
||||
[ "$disable_registration" = "1" ] && web_cmd="${web_cmd} --disable-registration"
|
||||
[ "$allow_auto_create_user" = "1" ] && web_cmd="${web_cmd} --allow-auto-create-user"
|
||||
# OIDC配置参数
|
||||
if [ "$oidc_enabled" = "1" ] ; then
|
||||
[ -z "$oidc_issuer_url" ] || web_cmd="${web_cmd} --oidc-issuer-url $oidc_issuer_url"
|
||||
[ -z "$oidc_client_id" ] || web_cmd="${web_cmd} --oidc-client-id $oidc_client_id"
|
||||
[ -z "$oidc_client_secret" ] || web_cmd="${web_cmd} --oidc-client-secret $oidc_client_secret"
|
||||
[ -z "$oidc_redirect_url" ] || web_cmd="${web_cmd} --oidc-redirect-url $oidc_redirect_url"
|
||||
[ -z "$oidc_username_claim" ] || web_cmd="${web_cmd} --oidc-username-claim $oidc_username_claim"
|
||||
[ -z "$oidc_scopes" ] || web_cmd="${web_cmd} --oidc-scopes \"$oidc_scopes\""
|
||||
[ -z "$oidc_frontend_base_url" ] || web_cmd="${web_cmd} --oidc-frontend-base-url $oidc_frontend_base_url"
|
||||
[ "$oidc_disable_pkce" = "1" ] && web_cmd="${web_cmd} --oidc-disable-pkce"
|
||||
fi
|
||||
|
||||
# Webhook配置参数
|
||||
if [ "$webhook_enabled" = "1" ] ; then
|
||||
[ -z "$webhook_url" ] || web_cmd="${web_cmd} --webhook-url $webhook_url"
|
||||
[ -z "$webhook_secret" ] || web_cmd="${web_cmd} --webhook-secret $webhook_secret"
|
||||
[ -z "$internal_auth_token" ] || web_cmd="${web_cmd} --internal-auth-token $internal_auth_token"
|
||||
[ -z "$web_instance_id" ] || web_cmd="${web_cmd} --web-instance-id $web_instance_id"
|
||||
[ -z "$web_instance_api_base_url" ] || web_cmd="${web_cmd} --web-instance-api-base-url $web_instance_api_base_url"
|
||||
fi
|
||||
if [ "$weblog" != "off" ] ; then
|
||||
web_cmd="${web_cmd} --console-log-level $weblog"
|
||||
fi
|
||||
|
||||
Loading…
Reference in New Issue
Block a user