luci-base, luci-app-firewall: port custom rules to client side view
authorJo-Philipp Wich <jo@mein.io>
Sun, 3 Nov 2019 19:34:57 +0000 (20:34 +0100)
committerJo-Philipp Wich <jo@mein.io>
Sun, 3 Nov 2019 19:34:57 +0000 (20:34 +0100)
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/custom.js [new file with mode: 0644]
applications/luci-app-firewall/luasrc/controller/firewall.lua
applications/luci-app-firewall/luasrc/model/cbi/firewall/custom.lua [deleted file]
applications/luci-app-firewall/luasrc/tools/firewall.lua [deleted file]
modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json

diff --git a/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/custom.js b/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/custom.js
new file mode 100644 (file)
index 0000000..4b4b140
--- /dev/null
@@ -0,0 +1,31 @@
+'use strict';
+'require fs';
+
+return L.view.extend({
+       load: function() {
+               return L.resolveDefault(fs.read('/etc/firewall.user'), '');
+       },
+
+       handleSave: function(ev) {
+               var value = (document.querySelector('textarea').value || '').trim().replace(/\r\n/g, '\n') + '\n';
+
+               return fs.write('/etc/firewall.user', value).then(function(rc) {
+                       document.querySelector('textarea').value = value;
+                       L.ui.addNotification(null, E('p', _('Contents have been saved.')), 'info');
+                       fs.exec('/etc/init.d/firewall', ['restart']);
+               }).catch(function(e) {
+                       L.ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message)));
+               });
+       },
+
+       render: function(fwuser) {
+               return E([
+                       E('h2', _('Firewall - Custom Rules')),
+                       E('p', {}, _('Custom rules allow you to execute arbitrary iptables commands which are not otherwise covered by the firewall framework. The commands are executed after each firewall restart, right after the default ruleset has been loaded.')),
+                       E('p', {}, E('textarea', { 'style': 'width:100%', 'rows': 10 }, [ fwuser != null ? fwuser : '' ]))
+               ]);
+       },
+
+       handleSaveApply: null,
+       handleReset: null
+});
index 58a44c6018fa0395e151416c56faf64b735d6905..5f8cb6ef31ca95fe03415b21c1f68907ba892295 100644 (file)
@@ -15,6 +15,5 @@ function index()
                view("firewall/rules"), _("Traffic Rules"), 30)
 
        entry({"admin", "network", "firewall", "custom"},
-               form("firewall/custom"),
-               _("Custom Rules"), 40).leaf = true
+               view("firewall/custom"), _("Custom Rules"), 40).leaf = true
 end
diff --git a/applications/luci-app-firewall/luasrc/model/cbi/firewall/custom.lua b/applications/luci-app-firewall/luasrc/model/cbi/firewall/custom.lua
deleted file mode 100644 (file)
index 21a1b27..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
--- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
--- Licensed to the public under the Apache License 2.0.
-
-local fs = require "nixio.fs"
-
-local f = SimpleForm("firewall",
-       translate("Firewall - Custom Rules"),
-       translate("Custom rules allow you to execute arbitrary iptables commands \
-               which are not otherwise covered by the firewall framework. \
-               The commands are executed after each firewall restart, right after \
-               the default ruleset has been loaded."))
-
-local o = f:field(Value, "_custom")
-
-o.template = "cbi/tvalue"
-o.rows = 20
-
-function o.cfgvalue(self, section)
-       return fs.readfile("/etc/firewall.user")
-end
-
-function o.write(self, section, value)
-       value = value:gsub("\r\n?", "\n")
-       fs.writefile("/etc/firewall.user", value)
-       require("luci.sys").call("/etc/init.d/firewall restart >/dev/null 2<&1")
-       require("nixio").syslog('info', 'Restarting firewall on custom /etc/firewall.user change')
-end
-
-f.submit = translate("Restart Firewall")
-
-return f
diff --git a/applications/luci-app-firewall/luasrc/tools/firewall.lua b/applications/luci-app-firewall/luasrc/tools/firewall.lua
deleted file mode 100644 (file)
index 055342b..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
--- Copyright 2011-2012 Jo-Philipp Wich <jow@openwrt.org>
--- Licensed to the public under the Apache License 2.0.
-
-module("luci.tools.firewall", package.seeall)
-
-local ut = require "luci.util"
-local ip = require "luci.ip"
-local nx = require "nixio"
-
-local translate, translatef = luci.i18n.translate, luci.i18n.translatef
-
-local function _(...)
-       return tostring(translate(...))
-end
-
-function fmt_neg(x)
-       if type(x) == "string" then
-               local v, neg = x:gsub("^ *! *", "")
-               if neg > 0 then
-                       return v, "%s " % _("not")
-               else
-                       return x, ""
-               end
-       end
-       return x, ""
-end
-
-function fmt_mac(x)
-       if x and #x > 0 then
-               local m, n
-               local l = { _("MAC"), " " }
-               for m in ut.imatch(x) do
-                       m, n = fmt_neg(m)
-                       l[#l+1] = "<var>%s%s</var>" %{ n, m }
-                       l[#l+1] = ", "
-               end
-               if #l > 1 then
-                       l[#l] = nil
-                       if #l > 3 then
-                               l[1] = _("MACs")
-                       end
-                       return table.concat(l, "")
-               end
-       end
-end
-
-function fmt_port(x, d)
-       if x and #x > 0 then
-               local p, n
-               local l = { _("port"), " " }
-               for p in ut.imatch(x) do
-                       p, n = fmt_neg(p)
-                       local a, b = p:match("(%d+)%D+(%d+)")
-                       if a and b then
-                               l[1] = _("ports")
-                               l[#l+1] = "<var>%s%d-%d</var>" %{ n, a, b }
-                       else
-                               l[#l+1] = "<var>%s%d</var>" %{ n, p }
-                       end
-                       l[#l+1] = ", "
-               end
-               if #l > 1 then
-                       l[#l] = nil
-                       if #l > 3 then
-                               l[1] = _("ports")
-                       end
-                       return table.concat(l, "")
-               end
-       end
-       return d and "<var>%s</var>" % d
-end
-
-function fmt_ip(x, d)
-       if x and #x > 0 then
-               local l = { _("IP"), " " }
-               local v, a, n
-               for v in ut.imatch(x) do
-                       v, n = fmt_neg(v)
-                       a, m = v:match("(%S+)/(%d+%.%S+)")
-                       a = a or v
-                       a = a:match(":") and ip.IPv6(a, m) or ip.IPv4(a, m)
-                       if a and (a:is6() and a:prefix() < 128 or a:prefix() < 32) then
-                               l[1] = _("IP range")
-                               l[#l+1] = "<var title='%s - %s'>%s%s</var>" %{
-                                       a:minhost():string(),
-                                       a:maxhost():string(),
-                                       n, a:string()
-                               }
-                       else
-                               l[#l+1] = "<var>%s%s</var>" %{
-                                       n,
-                                       a and a:string() or v
-                               }
-                       end
-                       l[#l+1] = ", "
-               end
-               if #l > 1 then
-                       l[#l] = nil
-                       if #l > 3 then
-                               l[1] = _("IPs")
-                       end
-                       return table.concat(l, "")
-               end
-       end
-       return d and "<var>%s</var>" % d
-end
-
-function fmt_zone(x, d)
-       if x == "*" then
-               return "<var>%s</var>" % _("any zone")
-       elseif x and #x > 0 then
-               return "<var>%s</var>" % x
-       elseif d then
-               return "<var>%s</var>" % d
-       end
-end
-
-function fmt_icmp_type(x)
-       if x and #x > 0 then
-               local t, v, n
-               local l = { _("type"), " " }
-               for v in ut.imatch(x) do
-                       v, n = fmt_neg(v)
-                       l[#l+1] = "<var>%s%s</var>" %{ n, v }
-                       l[#l+1] = ", "
-               end
-               if #l > 1 then
-                       l[#l] = nil
-                       if #l > 3 then
-                               l[1] = _("types")
-                       end
-                       return table.concat(l, "")
-               end
-       end
-end
-
-function fmt_proto(x, icmp_types)
-       if x and #x > 0 then
-               local v, n
-               local l = { }
-               local t = fmt_icmp_type(icmp_types)
-               for v in ut.imatch(x) do
-                       v, n = fmt_neg(v)
-                       if v == "tcpudp" then
-                               l[#l+1] = "TCP"
-                               l[#l+1] = ", "
-                               l[#l+1] = "UDP"
-                               l[#l+1] = ", "
-                       elseif v ~= "all" then
-                               local p = nx.getproto(v)
-                               if p then
-                                       -- ICMP
-                                       if (p.proto == 1 or p.proto == 58) and t then
-                                               l[#l+1] = translatef(
-                                                       "%s%s with %s",
-                                                       n, p.aliases[1] or p.name, t
-                                               )
-                                       else
-                                               l[#l+1] = "%s%s" %{
-                                                       n,
-                                                       p.aliases[1] or p.name
-                                               }
-                                       end
-                                       l[#l+1] = ", "
-                               end
-                       end
-               end
-               if #l > 0 then
-                       l[#l] = nil
-                       return table.concat(l, "")
-               end
-       end
-end
-
-function fmt_limit(limit, burst)
-       burst = tonumber(burst)
-       if limit and #limit > 0 then
-               local l, u = limit:match("(%d+)/(%w+)")
-               l = tonumber(l or limit)
-               u = u or "second"
-               if l then
-                       if u:match("^s") then
-                               u = _("second")
-                       elseif u:match("^m") then
-                               u = _("minute")
-                       elseif u:match("^h") then
-                               u = _("hour")
-                       elseif u:match("^d") then
-                               u = _("day")
-                       end
-                       if burst and burst > 0 then
-                               return translatef("<var>%d</var> pkts. per <var>%s</var>, \
-                                   burst <var>%d</var> pkts.", l, u, burst)
-                       else
-                               return translatef("<var>%d</var> pkts. per <var>%s</var>", l, u)
-                       end
-               end
-       end
-end
-
-function fmt_target(x, src, dest)
-       if not src or #src == 0 then
-               if x == "ACCEPT" then
-                       return _("Accept output")
-               elseif x == "REJECT" then
-                       return _("Refuse output")
-               elseif x == "NOTRACK" then
-                       return _("Do not track output")
-               else --if x == "DROP" then
-                       return _("Discard output")
-               end
-       elseif dest and #dest > 0 then
-               if x == "ACCEPT" then
-                       return _("Accept forward")
-               elseif x == "REJECT" then
-                       return _("Refuse forward")
-               elseif x == "NOTRACK" then
-                       return _("Do not track forward")
-               else --if x == "DROP" then
-                       return _("Discard forward")
-               end
-       else
-               if x == "ACCEPT" then
-                       return _("Accept input")
-               elseif x == "REJECT" then
-                       return _("Refuse input")
-               elseif x == "NOTRACK" then
-                       return _("Do not track input")
-               else --if x == "DROP" then
-                       return _("Discard input")
-               end
-       end
-end
-
-
-function opt_enabled(s, t, ...)
-       if t == luci.cbi.Button then
-               local o = s:option(t, "__enabled")
-               function o.render(self, section)
-                       if self.map:get(section, "enabled") ~= "0" then
-                               self.title      = _("Rule is enabled")
-                               self.inputtitle = _("Disable")
-                               self.inputstyle = "reset"
-                       else
-                               self.title      = _("Rule is disabled")
-                               self.inputtitle = _("Enable")
-                               self.inputstyle = "apply"
-                       end
-                       t.render(self, section)
-               end
-               function o.write(self, section, value)
-                       if self.map:get(section, "enabled") ~= "0" then
-                               self.map:set(section, "enabled", "0")
-                       else
-                               self.map:del(section, "enabled")
-                       end
-               end
-               return o
-       else
-               local o = s:option(t, "enabled", ...)
-               o.default = "1"
-               return o
-       end
-end
-
-function opt_name(s, t, ...)
-       local o = s:option(t, "name", ...)
-
-       function o.cfgvalue(self, section)
-               return self.map:get(section, "name") or
-                       self.map:get(section, "_name") or "-"
-       end
-
-       function o.write(self, section, value)
-               if value ~= "-" then
-                       self.map:set(section, "name", value)
-                       self.map:del(section, "_name")
-               else
-                       self:remove(section)
-               end
-       end
-
-       function o.remove(self, section)
-               self.map:del(section, "name")
-               self.map:del(section, "_name")
-       end
-
-       return o
-end
index a60c432bcba751eb0ed1526589b680712985db3e..321817302ed5be5ed3d02d57dbac44bb7f7c9781 100644 (file)
        "luci-app-firewall": {
                "description": "Grant access to firewall procedures",
                "read": {
+                       "file": {
+                               "/etc/firewall.user": [ "read" ]
+                       },
                        "ubus": {
                                "luci": [ "getConntrackHelpers" ]
                        },
                        "uci": [ "firewall" ]
                },
                "write": {
+                       "file": {
+                               "/etc/firewall.user": [ "write" ],
+                               "/etc/init.d/firewall": [ "exec" ]
+                       },
                        "uci": [ "firewall" ]
                }
        }