From: Stan Grishin Date: Thu, 25 Mar 2021 05:26:22 +0000 (+0000) Subject: luci-app-vpnbypass: client-side rendering X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=refs%2Fpull%2F4943%2Fhead;p=project%2Fluci.git luci-app-vpnbypass: client-side rendering Signed-off-by: Stan Grishin --- diff --git a/applications/luci-app-vpnbypass/Makefile b/applications/luci-app-vpnbypass/Makefile index da2c2af42d..abab837c32 100644 --- a/applications/luci-app-vpnbypass/Makefile +++ b/applications/luci-app-vpnbypass/Makefile @@ -5,10 +5,11 @@ include $(TOPDIR)/rules.mk PKG_LICENSE:=GPL-3.0-or-later PKG_MAINTAINER:=Stan Grishin +PKG_VERSION:=1.3.1-9 LUCI_TITLE:=VPN Bypass Web UI LUCI_DESCRIPTION:=Provides Web UI for VPNBypass service. -LUCI_DEPENDS:=+luci-compat +luci-mod-admin-full +vpnbypass +LUCI_DEPENDS:=+luci-mod-admin-full +vpnbypass LUCI_PKGARCH:=all include ../../luci.mk diff --git a/applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js b/applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js new file mode 100644 index 0000000000..b2d5d1f775 --- /dev/null +++ b/applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js @@ -0,0 +1,62 @@ +// Copyright 2021 Stan Grishin (stangri@melmac.net) +// Many thanks to [@vsviridov](https://github.com/vsviridov) for help with transition to JS + +'use strict'; +'require form'; +'require uci'; +'require view'; +'require vpnbypass.widgets as widgets'; + +var pkg = { + get Name() { return 'vpnbypass'; }, + get URL() { return 'https://docs.openwrt.melmac.net/' + pkg.Name + '/'; } +}; + +return view.extend({ + load: function () { + return Promise.all([ + uci.load(pkg.Name), + uci.load('dhcp') + ]); + }, + + render: function (data) { + + var m, d, s, o; + + m = new form.Map(pkg.Name, _('VPN Bypass')); + + s = m.section(form.NamedSection, 'config', pkg.Name); + + o = s.option(widgets.Status, '', _('Service Status')); + + o = s.option(widgets.Buttons, '', _('Service Control')); + + o = s.option(form.DynamicList, 'localport', _('Local Ports to Bypass'), _('Local ports to trigger VPN Bypass.')); + o.datatype = 'portrange'; + o.addremove = false; + o.optional = false; + + o = s.option(form.DynamicList, 'remoteport', _('Remote Ports to Bypass'), _('Remote ports to trigger VPN Bypass.')); + o.datatype = 'portrange'; + o.addremove = false; + o.optional = false; + + o = s.option(form.DynamicList, 'localsubnet', _('Local IP Addresses to Bypass'), _('Local IP addresses or subnets with direct internet access.')); + o.datatype = 'ip4addr'; + o.addremove = false; + o.optional = false; + + o = s.option(form.DynamicList, 'remotesubnet', _('Remote IP Addresses to Bypass'), _('Remote IP addresses or subnets which will be accessed directly.')); + o.datatype = 'ip4addr'; + o.addremove = false; + o.optional = false; + + d = new form.Map('dhcp'); + s = d.section(form.TypedSection, 'dnsmasq'); + s.anonymous = true; + o = s.option(form.DynamicList, 'ipset', _('Domains to Bypass'), _('Domains to be accessed directly, see %sREADME%s for syntax.').format('', '')); + + return Promise.all([m.render(), d.render()]); + } +}); diff --git a/applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js b/applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js new file mode 100644 index 0000000000..f14dd21d74 --- /dev/null +++ b/applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js @@ -0,0 +1,192 @@ +// Thsis file wouldn't have been possible without help from [@vsviridov](https://github.com/vsviridov) + +'require ui'; +'require rpc'; +'require form'; + +var pkg = { + get Name() { return 'vpnbypass'; } +}; + +var _getInitList = rpc.declare({ + object: 'luci.' + pkg.Name, + method: 'getInitList', + params: ['name'] +}); + +var _setInitAction = rpc.declare({ + object: 'luci.' + pkg.Name, + method: 'setInitAction', + params: ['name', 'action'], + expect: { result: false } +}); + +var _getInitStatus = rpc.declare({ + object: 'luci.' + pkg.Name, + method: 'getInitStatus', + params: ['name'] +}); + +var RPC = { + listeners: [], + on: function on(event, callback) { + var pair = { event: event, callback: callback } + this.listeners.push(pair); + return function unsubscribe() { + this.listeners = this.listeners.filter(function (listener) { + return listener !== pair; + }); + }.bind(this); + }, + emit: function emit(event, data) { + this.listeners.forEach(function (listener) { + if (listener.event === event) { + listener.callback(data); + } + }); + }, + getInitList: function getInitList(name) { + _getInitList(name).then(function (result) { + this.emit('getInitList', result); + }.bind(this)); + + }, + getInitStatus: function getInitStatus(name) { + _getInitStatus(name).then(function (result) { + this.emit('getInitStatus', result); + }.bind(this)); + }, + setInitAction: function setInitAction(name, action) { + _setInitAction(name, action).then(function (result) { + this.emit('setInitAction', result); + }.bind(this)); + } +} + +var statusCBI = form.DummyValue.extend({ + renderWidget: function (section) { + var status = E('span', {}, _("Quering") + "..."); + RPC.on('getInitStatus', function (reply) { + if (reply[pkg.Name].version) { + if (reply[pkg.Name].running) { + status.innerText = _("Running (version: %s)").format(reply[pkg.Name].version); + } + else { + if (reply[pkg.Name].enabled) { + status.innerText = _("Stopped (version: %s)").format(reply[pkg.Name].version); + } + else { + status.innerText = _("Stopped (Disabled)"); + } + } + } + else { + status.innerText = _("Not installed or not found") + } + }); + return E('div', {}, [status]); + } +}); + +var buttonsCBI = form.DummyValue.extend({ + renderWidget: function (section) { + + var btn_gap = E('span', {}, '  '); + var btn_gap_long = E('span', {}, '        '); + + var btn_start = E('button', { + 'class': 'btn cbi-button cbi-button-apply', + disabled: true, + click: function (ev) { + ui.showModal(null, [ + E('p', { 'class': 'spinning' }, _('Starting %s service').format(pkg.Name)) + ]); + return RPC.setInitAction(pkg.Name, 'start'); + } + }, _('Start')); + + var btn_action = E('button', { + 'class': 'btn cbi-button cbi-button-apply', + disabled: true, + click: function (ev) { + ui.showModal(null, [ + E('p', { 'class': 'spinning' }, _('Restarting %s service').format(pkg.Name)) + ]); + return RPC.setInitAction(pkg.Name, 'restart'); + } + }, _('Restart')); + + var btn_stop = E('button', { + 'class': 'btn cbi-button cbi-button-reset', + disabled: true, + click: function (ev) { + ui.showModal(null, [ + E('p', { 'class': 'spinning' }, _('Stopping %s service').format(pkg.Name)) + ]); + return RPC.setInitAction(pkg.Name, 'stop'); + } + }, _('Stop')); + + var btn_enable = E('button', { + 'class': 'btn cbi-button cbi-button-apply', + disabled: true, + click: function (ev) { + ui.showModal(null, [ + E('p', { 'class': 'spinning' }, _('Enabling %s service').format(pkg.Name)) + ]); + return RPC.setInitAction(pkg.Name, 'enable'); + } + }, _('Enable')); + + var btn_disable = E('button', { + 'class': 'btn cbi-button cbi-button-reset', + disabled: true, + click: function (ev) { + ui.showModal(null, [ + E('p', { 'class': 'spinning' }, _('Disabling %s service').format(pkg.Name)) + ]); + return RPC.setInitAction(pkg.Name, 'disable'); + } + }, _('Disable')); + + RPC.on('getInitStatus', function (reply) { + if (reply[pkg.Name].version) { + if (reply[pkg.Name].enabled) { + btn_enable.disabled = true; + btn_disable.disabled = false; + if (reply[pkg.Name].running) { + btn_start.disabled = true; + btn_action.disabled = false; + btn_stop.disabled = false; + } + else { + btn_start.disabled = false; + btn_action.disabled = true; + btn_stop.disabled = true; + } + } + else { + btn_start.disabled = true; + btn_action.disabled = true; + btn_stop.disabled = true; + btn_enable.disabled = false; + btn_disable.disabled = true; + } + } + }); + + RPC.getInitStatus(pkg.Name); + + return E('div', {}, [btn_start, btn_gap, btn_action, btn_gap, btn_stop, btn_gap_long, btn_enable, btn_gap, btn_disable]); + } +}); + +RPC.on('setInitAction', function (reply) { + ui.hideModal(); + RPC.getInitStatus(pkg.Name); +}); + +return L.Class.extend({ + Status: statusCBI, + Buttons: buttonsCBI +}); diff --git a/applications/luci-app-vpnbypass/luasrc/controller/vpnbypass.lua b/applications/luci-app-vpnbypass/luasrc/controller/vpnbypass.lua deleted file mode 100644 index 057aee787f..0000000000 --- a/applications/luci-app-vpnbypass/luasrc/controller/vpnbypass.lua +++ /dev/null @@ -1,34 +0,0 @@ -module("luci.controller.vpnbypass", package.seeall) -function index() - if nixio.fs.access("/etc/config/vpnbypass") then - local e = entry({"admin", "vpn"}, firstchild(), _("VPN"), 60) - e.dependent = false - e.acl_depends = { "luci-app-vpnbypass" } - entry({"admin", "vpn", "vpnbypass"}, cbi("vpnbypass"), _("VPN Bypass")) - entry({"admin", "vpn", "vpnbypass", "action"}, call("vpnbypass_action"), nil).leaf = true - end -end - -function vpnbypass_action(name) - local packageName = "vpnbypass" - local http = require "luci.http" - local sys = require "luci.sys" - local uci = require "luci.model.uci".cursor() - local util = require "luci.util" - if name == "start" then - sys.init.start(packageName) - elseif name == "action" then - util.exec("/etc/init.d/" .. packageName .. " restart >/dev/null 2>&1") - util.exec("/etc/init.d/dnsmasq restart >/dev/null 2>&1") - elseif name == "stop" then - sys.init.stop(packageName) - elseif name == "enable" then - uci:set(packageName, "config", "enabled", "1") - uci:commit(packageName) - elseif name == "disable" then - uci:set(packageName, "config", "enabled", "0") - uci:commit(packageName) - end - http.prepare_content("text/plain") - http.write("0") -end diff --git a/applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua b/applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua deleted file mode 100644 index d0f6afc23a..0000000000 --- a/applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua +++ /dev/null @@ -1,95 +0,0 @@ -local uci = require "luci.model.uci".cursor() -local sys = require "luci.sys" -local util = require "luci.util" -local packageName = "vpnbypass" -local readmeURL = "https://docs.openwrt.melmac.net/" .. packageName .. "/" - -function getPackageVersion() - local opkgFile = "/usr/lib/opkg/status" - local line - local flag = false - for line in io.lines(opkgFile) do - if flag then - return line:match('[%d%.$-]+') or "" - elseif line:find("Package: " .. packageName:gsub("%-", "%%%-")) then - flag = true - end - end - return "" -end - -local packageVersion = getPackageVersion() -local statusText = nil -if packageVersion == "" then - statusText = translatef("%s is not installed or not found", packageName) -end - -local serviceRunning, serviceEnabled = false, false -if uci:get(packageName, "config", "enabled") == "1" then - serviceEnabled = true -end -if sys.call("iptables -t mangle -L | grep -q " .. packageName:upper()) == 0 then - serviceRunning = true -end - -if serviceRunning then - statusText = translate("Running") -else - statusText = translate("Stopped") - if not serviceEnabled then - statusText = translatef("%s (disabled)", statusText) - end -end - -m = Map("vpnbypass", translate("VPN Bypass Settings")) - -h = m:section(NamedSection, "config", packageName, translatef("Service Status [%s %s]", packageName, packageVersion)) -ss = h:option(DummyValue, "_dummy", translate("Service Status")) -ss.template = packageName .. "/status" -ss.value = statusText -if packageVersion ~= "" then - buttons = h:option(DummyValue, "_dummy") - buttons.template = packageName .. "/buttons" -end - -s = m:section(NamedSection, "config", "vpnbypass", translate("VPN Bypass Rules")) --- Local Ports -p1 = s:option(DynamicList, "localport", translate("Local Ports to Bypass"), translate("Local ports to trigger VPN Bypass")) -p1.datatype = "portrange" --- p1.placeholder = "0-65535" -p1.addremove = false -p1.optional = false - --- Remote Ports -p2 = s:option(DynamicList, "remoteport", translate("Remote Ports to Bypass"), translate("Remote ports to trigger VPN Bypass")) -p2.datatype = "portrange" --- p2.placeholder = "0-65535" -p2.addremove = false -p2.optional = false - --- Local Subnets -r1 = s:option(DynamicList, "localsubnet", translate("Local IP Addresses to Bypass"), translate("Local IP addresses or subnets with direct internet access (outside of the VPN tunnel)")) -r1.datatype = "ip4addr" --- r1.placeholder = ip.new(m.uci:get("network", "lan", "ipaddr"), m.uci:get("network", "lan", "netmask")) -r1.addremove = false -r1.optional = false - --- Remote Subnets -r2 = s:option(DynamicList, "remotesubnet", translate("Remote IP Addresses to Bypass"), translate("Remote IP addresses or subnets which will be accessed directly (outside of the VPN tunnel)")) -r2.datatype = "ip4addr" --- r2.placeholder = "0.0.0.0/0" -r2.addremove = false -r2.optional = false - --- Domains -d = Map("dhcp") -s4 = d:section(TypedSection, "dnsmasq") -s4.anonymous = true -di = s4:option(DynamicList, "ipset", translate("Domains to Bypass"), - translatef("Domains to be accessed directly (outside of the VPN tunnel), see %sREADME%s for syntax", - "", "")) -function d.on_after_commit(map) - util.exec("/etc/init.d/dnsmasq restart >/dev/null 2>&1") -end - -return m, d diff --git a/applications/luci-app-vpnbypass/luasrc/view/vpnbypass/buttons.htm b/applications/luci-app-vpnbypass/luasrc/view/vpnbypass/buttons.htm deleted file mode 100644 index 9261c050dc..0000000000 --- a/applications/luci-app-vpnbypass/luasrc/view/vpnbypass/buttons.htm +++ /dev/null @@ -1,77 +0,0 @@ -<%# Copyright 2020 Stan Grishin -%> - -<%+vpnbypass/css%> -<%+vpnbypass/js%> - -<%- - local packageName = "vpnbypass" - local serviceRunning, serviceEnabled = false, false; - if luci.sys.call("iptables -t mangle -L | grep -q " .. packageName:upper()) == 0 then - serviceRunning = true - end - if luci.model.uci.cursor():get(packageName, "config", "enabled") == "1" then - serviceEnabled = true - end - - if serviceEnabled then - btn_start_status = true - btn_action_status = true - btn_stop_status = true - btn_enable_status = false - btn_disable_status = true - else - btn_start_status = false - btn_action_status = false - btn_stop_status = false - btn_enable_status = true - btn_disable_status = false - end - if serviceRunning then - btn_start_status = false - btn_action_status = true - btn_stop_status = true - else - btn_action_status = false - btn_stop_status = false - end --%> - -
-
- - - - - - -   -   -   -   - - - - -
-
- -<%-if not btn_start_status then%> - -<%-end%> -<%-if not btn_action_status then%> - -<%-end%> -<%-if not btn_stop_status then%> - -<%-end%> -<%-if not btn_enable_status then%> - -<%-end%> -<%-if not btn_disable_status then%> - -<%-end%> \ No newline at end of file diff --git a/applications/luci-app-vpnbypass/luasrc/view/vpnbypass/css.htm b/applications/luci-app-vpnbypass/luasrc/view/vpnbypass/css.htm deleted file mode 100644 index 6fb3d51d3b..0000000000 --- a/applications/luci-app-vpnbypass/luasrc/view/vpnbypass/css.htm +++ /dev/null @@ -1,9 +0,0 @@ - diff --git a/applications/luci-app-vpnbypass/luasrc/view/vpnbypass/js.htm b/applications/luci-app-vpnbypass/luasrc/view/vpnbypass/js.htm deleted file mode 100644 index e8c076f50e..0000000000 --- a/applications/luci-app-vpnbypass/luasrc/view/vpnbypass/js.htm +++ /dev/null @@ -1,59 +0,0 @@ - diff --git a/applications/luci-app-vpnbypass/luasrc/view/vpnbypass/status-textarea.htm b/applications/luci-app-vpnbypass/luasrc/view/vpnbypass/status-textarea.htm deleted file mode 100644 index 4ab2e11291..0000000000 --- a/applications/luci-app-vpnbypass/luasrc/view/vpnbypass/status-textarea.htm +++ /dev/null @@ -1,13 +0,0 @@ -<%# -Copyright 2017-2019 Stan Grishin (stangri@melmac.net) -This is free software, licensed under the Apache License, Version 2.0 --%> - -<%+cbi/valueheader%> - - - -<%+cbi/valuefooter%> diff --git a/applications/luci-app-vpnbypass/luasrc/view/vpnbypass/status.htm b/applications/luci-app-vpnbypass/luasrc/view/vpnbypass/status.htm deleted file mode 100644 index c453428405..0000000000 --- a/applications/luci-app-vpnbypass/luasrc/view/vpnbypass/status.htm +++ /dev/null @@ -1,10 +0,0 @@ -<%# -Copyright 2017-2018 Dirk Brenken (dev@brenken.org) -This is free software, licensed under the Apache License, Version 2.0 --%> - -<%+cbi/valueheader%> - - - -<%+cbi/valuefooter%> diff --git a/applications/luci-app-vpnbypass/po/templates/vpnbypass.pot b/applications/luci-app-vpnbypass/po/templates/vpnbypass.pot index abbe198229..443ba8b9c0 100644 --- a/applications/luci-app-vpnbypass/po/templates/vpnbypass.pot +++ b/applications/luci-app-vpnbypass/po/templates/vpnbypass.pot @@ -1,116 +1,119 @@ msgid "" msgstr "Content-Type: text/plain; charset=UTF-8" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:40 -msgid "%s (disabled)" -msgstr "" - -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:24 -msgid "%s is not installed or not found" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js:150 +msgid "Disable" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/view/vpnbypass/buttons.htm:57 -msgid "Disable" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js:146 +msgid "Disabling %s service" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:88 +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js:58 msgid "Domains to Bypass" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:89 -msgid "" -"Domains to be accessed directly (outside of the VPN tunnel), see %sREADME%s " -"for syntax" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js:58 +msgid "Domains to be accessed directly, see %sREADME%s for syntax." msgstr "" -#: applications/luci-app-vpnbypass/luasrc/view/vpnbypass/buttons.htm:54 +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js:139 msgid "Enable" msgstr "" -#: applications/luci-app-vpnbypass/root/usr/share/rpcd/acl.d/luci-app-vpnbypass.json:3 -msgid "Grant UCI and file access for luci-app-vpnbypass" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js:135 +msgid "Enabling %s service" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/view/vpnbypass/js.htm:51 -msgid "Loading" +#: applications/luci-app-vpnbypass/root/usr/share/rpcd/acl.d/luci-app-vpnbypass.json:3 +msgid "Grant UCI and file access for luci-app-vpnbypass" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:71 +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js:45 msgid "Local IP Addresses to Bypass" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:71 -msgid "" -"Local IP addresses or subnets with direct internet access (outside of the " -"VPN tunnel)" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js:45 +msgid "Local IP addresses or subnets with direct internet access." msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:57 +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js:35 msgid "Local Ports to Bypass" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:57 -msgid "Local ports to trigger VPN Bypass" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js:35 +msgid "Local ports to trigger VPN Bypass." +msgstr "" + +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js:84 +msgid "Not installed or not found" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:78 +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js:68 +msgid "Quering" +msgstr "" + +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js:50 msgid "Remote IP Addresses to Bypass" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:78 -msgid "" -"Remote IP addresses or subnets which will be accessed directly (outside of " -"the VPN tunnel)" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js:50 +msgid "Remote IP addresses or subnets which will be accessed directly." msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:64 +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js:40 msgid "Remote Ports to Bypass" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:64 -msgid "Remote ports to trigger VPN Bypass" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js:40 +msgid "Remote ports to trigger VPN Bypass." msgstr "" -#: applications/luci-app-vpnbypass/luasrc/view/vpnbypass/buttons.htm:44 +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js:117 msgid "Restart" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:36 -msgid "Running" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js:113 +msgid "Restarting %s service" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:47 -msgid "Service Status" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js:72 +msgid "Running (version: %s)" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:46 -msgid "Service Status [%s %s]" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js:33 +msgid "Service Control" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/view/vpnbypass/buttons.htm:41 +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js:31 +msgid "Service Status" +msgstr "" + +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js:106 msgid "Start" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/view/vpnbypass/buttons.htm:47 -msgid "Stop" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js:102 +msgid "Starting %s service" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:38 -msgid "Stopped" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js:128 +msgid "Stop" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/controller/vpnbypass.lua:4 -msgid "VPN" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js:79 +msgid "Stopped (Disabled)" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/controller/vpnbypass.lua:7 -msgid "VPN Bypass" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js:76 +msgid "Stopped (version: %s)" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:55 -msgid "VPN Bypass Rules" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/vpnbypass/widgets.js:124 +msgid "Stopping %s service" msgstr "" -#: applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua:44 -msgid "VPN Bypass Settings" +#: applications/luci-app-vpnbypass/htdocs/luci-static/resources/view/vpnbypass/overview.js:27 +#: applications/luci-app-vpnbypass/root/usr/share/luci/menu.d/vpnbypass.json:3 +msgid "VPN Bypass" msgstr "" diff --git a/applications/luci-app-vpnbypass/root/etc/uci-defaults/40_luci-vpnbypass b/applications/luci-app-vpnbypass/root/etc/uci-defaults/40_luci-vpnbypass index 6df7810334..8e457adce8 100644 --- a/applications/luci-app-vpnbypass/root/etc/uci-defaults/40_luci-vpnbypass +++ b/applications/luci-app-vpnbypass/root/etc/uci-defaults/40_luci-vpnbypass @@ -1,4 +1,5 @@ #!/bin/sh + +/etc/init.d/rpcd reload rm -rf /var/luci-modulecache/; rm -f /var/luci-indexcache; exit 0 - diff --git a/applications/luci-app-vpnbypass/root/usr/libexec/rpcd/luci.vpnbypass b/applications/luci-app-vpnbypass/root/usr/libexec/rpcd/luci.vpnbypass new file mode 100755 index 0000000000..e5eb7c2ca2 --- /dev/null +++ b/applications/luci-app-vpnbypass/root/usr/libexec/rpcd/luci.vpnbypass @@ -0,0 +1,105 @@ +#!/bin/sh +# Copyright 2021 Stan Grishin (stangri@melmac.net) +# shellcheck disable=SC1091,SC2039 + +# TechRef: https://openwrt.org/docs/techref/rpcd + +. /lib/functions.sh +. /usr/share/libubox/jshn.sh + +pkgName="vpnbypass" + +is_enabled() { uci -q get "${1}.config.enabled"; } +is_running() { iptables -t mangle -L | grep -q VPNBYPASS && echo '1' || echo '0'; } +get_version() { grep -A2 -w "Package: $1$" /usr/lib/opkg/status | sed -n 's/Version: //p'; } +print_json_bool() { json_init; json_add_boolean "$1" "$2"; json_dump; json_cleanup; } +print_json_string() { json_init; json_add_string "$1" "$2"; json_dump; json_cleanup; } +logger() { /usr/bin/logger -t "$pkgName" "$@"; } + +get_init_list() { + local name="$1" + json_init + json_add_object "$name" + json_add_boolean 'enabled' "$(is_enabled "$name")" + json_add_boolean 'running' "$(is_running "$name")" + json_close_object + json_dump + json_cleanup +} + +set_init_action() { + local name="$1" action="$2" cmd + if [ ! -f "/etc/init.d/$name" ]; then + print_json_string 'error' 'Init script not found!' + return + fi + case $action in + enable) + cmd="uci -q set ${name}.config.enabled=1 && uci commit $name";; + disable) + cmd="uci -q set ${name}.config.enabled=0 && uci commit $name";; + start|stop|reload|restart) + cmd="/etc/init.d/${name} ${action}";; + esac + if [ -n "$cmd" ] && eval "${cmd}" 1>/dev/null 2>&1; then + print_json_bool "result" '1' + else + print_json_bool "result" '0' + fi +} + +get_init_status() { + local name="$1" + json_init + json_add_object "$name" + json_add_boolean 'enabled' "$(is_enabled "$name")" + json_add_boolean 'running' "$(is_running "$name")" + json_add_string 'version' "$(get_version "$name")" + json_close_object + json_dump + json_cleanup +} + +case "$1" in + list) + json_init + json_add_object "getInitList" + json_add_string 'name' 'name' + json_close_object + json_add_object "setInitAction" + json_add_string 'name' 'name' + json_add_string 'action' 'action' + json_close_object + json_add_object "getInitStatus" + json_add_string 'name' 'name' + json_close_object + json_dump + json_cleanup + ;; + call) + case "$2" in + getInitList) + read -r input + json_load "$input" + json_get_var name 'name' + json_cleanup + get_init_list "$name" + ;; + getInitStatus) + read -r input + json_load "$input" + json_get_var name 'name' + json_cleanup + get_init_status "$name" + ;; + setInitAction) + read -r input + json_load "$input" + json_get_var name 'name' + json_get_var action 'action' + json_cleanup + set_init_action "$name" "$action" + ;; + esac + ;; +esac diff --git a/applications/luci-app-vpnbypass/root/usr/share/luci/menu.d/vpnbypass.json b/applications/luci-app-vpnbypass/root/usr/share/luci/menu.d/vpnbypass.json new file mode 100644 index 0000000000..0a56f9023d --- /dev/null +++ b/applications/luci-app-vpnbypass/root/usr/share/luci/menu.d/vpnbypass.json @@ -0,0 +1,15 @@ +{ + "admin/vpn/vpnbypass": { + "title": "VPN Bypass", + "order": 90, + "action": { + "type": "view", + "path": "vpnbypass/overview" + }, + "depends": { + "acl": [ + "luci-app-vpnbypass" + ] + } + } +} diff --git a/applications/luci-app-vpnbypass/root/usr/share/rpcd/acl.d/luci-app-vpnbypass.json b/applications/luci-app-vpnbypass/root/usr/share/rpcd/acl.d/luci-app-vpnbypass.json index 6dc1cb6a3f..3e3e06745c 100644 --- a/applications/luci-app-vpnbypass/root/usr/share/rpcd/acl.d/luci-app-vpnbypass.json +++ b/applications/luci-app-vpnbypass/root/usr/share/rpcd/acl.d/luci-app-vpnbypass.json @@ -2,39 +2,23 @@ "luci-app-vpnbypass": { "description": "Grant UCI and file access for luci-app-vpnbypass", "read": { - "cgi-io": [ - "exec" - ], - "file": { - "/usr/lib/opkg/status": [ - "read" - ], - "/etc/init.d/vpnbypass *": [ - "exec" - ], - "/etc/init.d/dnsmasq restart *": [ - "exec" - ], - "/usr/bin/grep *": [ - "exec" - ], - "/usr/sbin/grep *": [ - "exec" - ], - "/usr/sbin/iptables *": [ - "exec" + "ubus": { + "luci.vpnbypass": [ + "getInitList", + "getInitStatus" ] }, "uci": [ - "dhcp", - "vpnbypass" + "vpnbypass", + "dnsmasq" ] }, "write": { - "uci": [ - "dhcp", - "vpnbypass" - ] + "ubus": { + "luci.vpnbypass": [ + "setInitAction" + ] + } } } } \ No newline at end of file