luci-mod-network: reimplement diagnostics page as client side view
authorJo-Philipp Wich <jo@mein.io>
Sun, 15 Dec 2019 21:35:21 +0000 (22:35 +0100)
committerJo-Philipp Wich <jo@mein.io>
Mon, 16 Dec 2019 17:07:18 +0000 (18:07 +0100)
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json
modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js [new file with mode: 0644]
modules/luci-mod-network/luasrc/controller/admin/network.lua
modules/luci-mod-network/luasrc/view/admin_network/diagnostics.htm [deleted file]
modules/luci-mod-network/root/usr/share/luci/menu.d/luci-mod-network.json

index 50ddc299faf71627397c7ac6fec4632800505b20..e215cf9455eb28d7006f4dd3887d388f34dbf27e 100644 (file)
                                "/proc/sys/kernel/hostname": [ "read" ],
                                "/proc/sys/net/netfilter/nf_conntrack_*": [ "read" ],
                                "/proc/mounts": [ "read" ],
-                               "/usr/lib/lua/luci/version.lua": [ "read" ]
+                               "/usr/lib/lua/luci/version.lua": [ "read" ],
+                               "/bin/ping *": [ "exec" ],
+                               "/bin/ping6 *": [ "exec" ],
+                               "/bin/traceroute *": [ "exec" ],
+                               "/bin/traceroute6 *": [ "exec" ],
+                               "/usr/bin/ping *": [ "exec" ],
+                               "/usr/bin/ping6 *": [ "exec" ],
+                               "/usr/bin/traceroute *": [ "exec" ],
+                               "/usr/bin/traceroute6 *": [ "exec" ],
+                               "/usr/bin/nslookup *": [ "exec" ]
                        },
                        "ubus": {
                                "file": [ "list", "read", "stat" ],
diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js
new file mode 100644 (file)
index 0000000..ee2a466
--- /dev/null
@@ -0,0 +1,137 @@
+'use strict';
+'require fs';
+'require ui';
+'require uci';
+
+return L.view.extend({
+       handleCommand: function(exec, args) {
+               var buttons = document.querySelectorAll('.diag-action > .cbi-button');
+
+               for (var i = 0; i < buttons.length; i++)
+                       buttons[i].setAttribute('disabled', 'true');
+
+               return fs.exec(exec, args).then(function(res) {
+                       var out = document.querySelector('.command-output');
+                           out.style.display = '';
+
+                       L.dom.content(out, [ res.stdout || '', res.stderr || '' ]);
+               }).catch(function(err) {
+                       ui.addNotification(null, E('p', [ err ]))
+               }).finally(function() {
+                       for (var i = 0; i < buttons.length; i++)
+                               buttons[i].removeAttribute('disabled');
+               });
+       },
+
+       handlePing: function(ev, cmd) {
+               var exec = cmd || 'ping',
+                   addr = ev.currentTarget.parentNode.previousSibling.value,
+                   args = (exec == 'ping') ? [ '-c', '5', '-W', '1', addr ] : [ '-c', '5', addr ];
+
+               return this.handleCommand(exec, args);
+       },
+
+       handleTraceroute: function(ev, cmd) {
+               var exec = cmd || 'traceroute',
+                   addr = ev.currentTarget.parentNode.previousSibling.value,
+                   args = (exec == 'traceroute') ? [ '-q', '1', '-w', '1', '-n', addr ] : [ '-q', '1', '-w', '2', '-n', addr ];
+
+               return this.handleCommand(exec, args);
+       },
+
+       handleNslookup: function(ev, cmd) {
+               var addr = ev.currentTarget.parentNode.previousSibling.value;
+
+               return this.handleCommand('nslookup', [ addr ]);
+       },
+
+       load: function() {
+               return Promise.all([
+                       L.resolveDefault(fs.stat('/bin/ping6'), {}),
+                       L.resolveDefault(fs.stat('/usr/bin/ping6'), {}),
+                       L.resolveDefault(fs.stat('/bin/traceroute6'), {}),
+                       L.resolveDefault(fs.stat('/usr/bin/traceroute6'), {}),
+                       uci.load('luci')
+               ]);
+       },
+
+       render: function(res) {
+               var has_ping6 = res[0].path || res[1].path,
+                   has_traceroute6 = res[2].path || res[3].path,
+                       dns_host = uci.get('luci', 'diag', 'dns') || 'openwrt.org',
+                       ping_host = uci.get('luci', 'diag', 'ping') || 'openwrt.org',
+                       route_host = uci.get('luci', 'diag', 'route') || 'openwrt.org';
+
+               return E([], [
+                       E('h2', {}, [ _('Network Utilities') ]),
+                       E('div', { 'class': 'table' }, [
+                               E('div', { 'class': 'tr' }, [
+                                       E('div', { 'class': 'td left' }, [
+                                               E('input', {
+                                                       'style': 'margin:5px 0',
+                                                       'type': 'text',
+                                                       'value': ping_host
+                                               }),
+                                               E('span', { 'class': 'diag-action' }, [
+                                                       has_ping6 ? new ui.ComboButton('ping', {
+                                                               'ping': '%s %s'.format(_('IPv4'), _('Ping')),
+                                                               'ping6': '%s %s'.format(_('IPv6'), _('Ping')),
+                                                       }, {
+                                                               'click': ui.createHandlerFn(this, 'handlePing'),
+                                                               'classes': {
+                                                                       'ping': 'cbi-button cbi-button-action',
+                                                                       'ping6': 'cbi-button cbi-button-action'
+                                                               }
+                                                       }).render() : E('button', {
+                                                               'class': 'cbi-button cbi-button-action',
+                                                               'click': ui.createHandlerFn(this, 'handlePing')
+                                                       }, [ _('Ping') ])
+                                               ])
+                                       ]),
+
+                                       E('div', { 'class': 'td left' }, [
+                                               E('input', {
+                                                       'style': 'margin:5px 0',
+                                                       'type': 'text',
+                                                       'value': route_host
+                                               }),
+                                               E('span', { 'class': 'diag-action' }, [
+                                                       has_traceroute6 ? new ui.ComboButton('traceroute', {
+                                                               'traceroute': '%s %s'.format(_('IPv4'), _('Traceroute')),
+                                                               'traceroute6': '%s %s'.format(_('IPv6'), _('Traceroute')),
+                                                       }, {
+                                                               'click': ui.createHandlerFn(this, 'handleTraceroute'),
+                                                               'classes': {
+                                                                       'traceroute': 'cbi-button cbi-button-action',
+                                                                       'traceroute6': 'cbi-button cbi-button-action'
+                                                               }
+                                                       }).render() : E('button', {
+                                                               'class': 'cbi-button cbi-button-action',
+                                                               'click': ui.createHandlerFn(this, 'handleTraceroute')
+                                                       }, [ _('Traceroute') ])
+                                               ])
+                                       ]),
+
+                                       E('div', { 'class': 'td left' }, [
+                                               E('input', {
+                                                       'style': 'margin:5px 0',
+                                                       'type': 'text',
+                                                       'value': dns_host
+                                               }),
+                                               E('span', { 'class': 'diag-action' }, [
+                                                       E('button', {
+                                                               'class': 'cbi-button cbi-button-action',
+                                                               'click': ui.createHandlerFn(this, 'handleNslookup')
+                                                       }, [ _('Nslookup') ])
+                                               ])
+                                       ])
+                               ])
+                       ]),
+                       E('pre', { 'class': 'command-output', 'style': 'display:none' })
+               ]);
+       },
+
+       handleSaveApply: null,
+       handleSave: null,
+       handleReset: null
+});
index 4e9d27e8a852e7ce949db8d1ba11a1b6a37865ed..109c59f2a7d9cb8123b7eb3c8879d292a00b5fd0 100644 (file)
@@ -66,45 +66,3 @@ function remote_addr()
        luci.http.prepare_content("application/json")
        luci.http.write_json(result)
 end
-
-function diag_command(cmd, addr)
-       if addr and addr:match("^[a-zA-Z0-9%-%.:_]+$") then
-               luci.http.prepare_content("text/plain")
-
-               local util = io.popen(cmd % luci.util.shellquote(addr))
-               if util then
-                       while true do
-                               local ln = util:read("*l")
-                               if not ln then break end
-                               luci.http.write(ln)
-                               luci.http.write("\n")
-                       end
-
-                       util:close()
-               end
-
-               return
-       end
-
-       luci.http.status(500, "Bad address")
-end
-
-function diag_ping(addr)
-       diag_command("ping -c 5 -W 1 %s 2>&1", addr)
-end
-
-function diag_traceroute(addr)
-       diag_command("traceroute -q 1 -w 1 -n %s 2>&1", addr)
-end
-
-function diag_nslookup(addr)
-       diag_command("nslookup %s 2>&1", addr)
-end
-
-function diag_ping6(addr)
-       diag_command("ping6 -c 5 %s 2>&1", addr)
-end
-
-function diag_traceroute6(addr)
-       diag_command("traceroute6 -q 1 -w 2 -n %s 2>&1", addr)
-end
diff --git a/modules/luci-mod-network/luasrc/view/admin_network/diagnostics.htm b/modules/luci-mod-network/luasrc/view/admin_network/diagnostics.htm
deleted file mode 100644 (file)
index 03dd5aa..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-<%#
- Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
- Licensed to the public under the Apache License 2.0.
--%>
-
-<%+header%>
-
-<%
-local fs   = require "nixio.fs"
-local has_ping6 = fs.access("/bin/ping6") or fs.access("/usr/bin/ping6")
-local has_traceroute6 = fs.access("/bin/traceroute6") or fs.access("/usr/bin/traceroute6")
-
-local dns_host = luci.config.diag and luci.config.diag.dns or "dev.openwrt.org"
-local ping_host = luci.config.diag and luci.config.diag.ping or "dev.openwrt.org"
-local route_host = luci.config.diag and luci.config.diag.route or "dev.openwrt.org"
-%>
-
-<script type="text/javascript">//<![CDATA[
-       var stxhr = new XHR();
-
-       function update_status(field, proto)
-       {
-               var tool = field.name;
-               var addr = field.value;
-               var protocol = proto ? "6" : "";
-
-               var legend = document.getElementById('diag-rc-legend');
-               var output = document.getElementById('diag-rc-output');
-
-               if (legend && output)
-               {
-                       output.innerHTML =
-                               '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> ' +
-                               '<%:Waiting for command to complete...%>'
-                       ;
-
-                       legend.parentNode.style.display = 'block';
-                       legend.style.display = 'inline';
-
-                       stxhr.post('<%=url('admin/network')%>/diag_' + tool + protocol + '/' + addr, { token: '<%=token%>' },
-                               function(x)
-                               {
-                                       if (x.responseText)
-                                       {
-                                               legend.style.display = 'none';
-                                               output.innerHTML = String.format('<pre>%h</pre>', x.responseText);
-                                       }
-                                       else
-                                       {
-                                               legend.style.display = 'none';
-                                               output.innerHTML = '<span class="error"><%:Bad address specified!%></span>';
-                                       }
-                               }
-                       );
-               }
-       }
-//]]></script>
-
-<form method="post" action="<%=url('admin/network/diagnostics')%>">
-       <div class="cbi-map">
-               <h2 name="content"><%:Diagnostics%></h2>
-
-               <div class="cbi-section">
-                       <legend><%:Network Utilities%></legend>
-
-                       <div class="table">
-                               <div class="tr">
-                                       <div class="td left">
-                                               <input style="margin: 5px 0" type="text" value="<%=ping_host%>" name="ping" /><br />
-                                               <% if has_ping6 then %>
-                                               <span>
-                                                       <select name="ping_proto" style="width:auto">
-                                                               <option value="" selected="selected"><%:IPv4%></option>
-                                                               <option value="6"><%:IPv6%></option>
-                                                       </select>
-                                               </span>
-                                               <input type="button" value="<%:Ping%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.ping, this.form.ping_proto.selectedIndex)" />
-                                               <% else %>
-                                               <input type="button" value="<%:Ping%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.ping)" />
-                                               <% end %>
-                                       </div>
-
-                                       <div class="td left">
-                                               <input style="margin: 5px 0" type="text" value="<%=route_host%>" name="traceroute" /><br />
-                                               <% if has_traceroute6 then %>
-                                               <span>
-                                                       <select name="traceroute_proto" style="width:auto">
-                                                               <option value="" selected="selected"><%:IPv4%></option>
-                                                               <option value="6"><%:IPv6%></option>
-                                                       </select>
-                                               </span>
-                                               <input type="button" value="<%:Traceroute%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.traceroute, this.form.traceroute_proto.selectedIndex)" />
-                                               <% else %>
-                                               <input type="button" value="<%:Traceroute%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.traceroute)" />
-                                               <% end %>
-                                               <% if not has_traceroute6 then %>
-                                                       <p>&#160;</p>
-                                                       <p><%:Install iputils-traceroute6 for IPv6 traceroute%></p>
-                                               <% end %>
-                                       </div>
-
-                                       <div class="td left">
-                                               <input style="margin: 5px 0" type="text" value="<%=dns_host%>" name="nslookup" /><br />
-                                               <input type="button" value="<%:Nslookup%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.nslookup)" />
-                                       </div>
-                               </div>
-                       </div>
-               </div>
-       </div>
-
-       <div class="cbi-section" style="display:none">
-               <strong id="diag-rc-legend"></strong>
-               <span id="diag-rc-output"></span>
-       </div>
-</form>
-
-<%+footer%>
index 990c5d35ecd9c98d795e42794759f4ae5dc86e62..670f2c1a49afe71c09396b797e24b3737eceb8e4 100644 (file)
                "title": "Diagnostics",
                "order": 60,
                "action": {
-                       "type": "template",
-                       "path": "admin_network/diagnostics"
-               }
-       },
-
-       "admin/network/diag_ping/*": {
-               "action": {
-                       "post": true,
-                       "type": "call",
-                       "module": "luci.controller.admin.network",
-                       "function": "diag_ping"
-               }
-       },
-
-       "admin/network/diag_nslookup/*": {
-               "action": {
-                       "post": true,
-                       "type": "call",
-                       "module": "luci.controller.admin.network",
-                       "function": "diag_nslookup"
-               }
-       },
-
-       "admin/network/diag_traceroute/*": {
-               "action": {
-                       "post": true,
-                       "type": "call",
-                       "module": "luci.controller.admin.network",
-                       "function": "diag_traceroute"
-               }
-       },
-
-       "admin/network/diag_ping6/*": {
-               "action": {
-                       "post": true,
-                       "type": "call",
-                       "module": "luci.controller.admin.network",
-                       "function": "diag_ping6"
-               }
-       },
-
-       "admin/network/diag_traceroute6/*": {
-               "action": {
-                       "post": true,
-                       "type": "call",
-                       "module": "luci.controller.admin.network",
-                       "function": "diag_traceroute6"
+                       "type": "view",
+                       "path": "network/diagnostics"
                }
        }
 }