Merge pull request #4665 from berenyibalazs/softether
authorFlorian Eckert <fe@dev.tdt.de>
Wed, 13 Jan 2021 10:47:15 +0000 (11:47 +0100)
committerGitHub <noreply@github.com>
Wed, 13 Jan 2021 10:47:15 +0000 (11:47 +0100)
luci-app-softether: add basic softether status page

applications/luci-app-softether/Makefile [new file with mode: 0644]
applications/luci-app-softether/htdocs/luci-static/resources/view/softether-status.js [new file with mode: 0644]
applications/luci-app-softether/root/usr/libexec/vpncmd-call [new file with mode: 0755]
applications/luci-app-softether/root/usr/share/luci/menu.d/luci-app-softether.json [new file with mode: 0644]
applications/luci-app-softether/root/usr/share/rpcd/acl.d/luci-app-softether.json [new file with mode: 0644]

diff --git a/applications/luci-app-softether/Makefile b/applications/luci-app-softether/Makefile
new file mode 100644 (file)
index 0000000..06a310c
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# This is free software, licensed under the Apache License, Version 2.0 .
+#
+
+include $(TOPDIR)/rules.mk
+
+LUCI_TITLE:=Softether management application
+LUCI_DEPENDS:=+softethervpn5-client
+
+include ../../luci.mk
+
+# call BuildPackage - OpenWrt buildroot signature
diff --git a/applications/luci-app-softether/htdocs/luci-static/resources/view/softether-status.js b/applications/luci-app-softether/htdocs/luci-static/resources/view/softether-status.js
new file mode 100644 (file)
index 0000000..3c3130d
--- /dev/null
@@ -0,0 +1,117 @@
+'use strict';
+'require view';
+'require fs';
+
+return view.extend({
+       setElementShown: function(selector, shown) {
+               var loaderE = document.querySelector(selector);
+               if (loaderE) {
+                       if (loaderE.classList.contains('hidden') === shown)
+                       {
+                               if (shown) {
+                                       loaderE.classList.remove('hidden');
+                               } else {
+                                       loaderE.classList.add('hidden');
+                               }
+                       }
+               }
+       },
+       fixupResponse: function(response) {
+               return response.toString().replace(/(\n$)/, '');
+       },
+       rpcDownloadAccountLists: function() {
+               return new Promise(L.bind(function (resolve, fail) {
+                       fs.exec_direct('/usr/libexec/vpncmd-call', [ 'account-list' ])
+                               .then(L.bind(function(resp) {
+                                       var accounts = [];
+                                       var responseList = this.fixupResponse(resp).split('\n');
+                                       responseList.forEach(function(d) {
+                                               var s = d.split(',');
+                                               var tmp = {};
+                                               tmp.name = s[0];
+                                               tmp.properties = {};
+                                               tmp.properties['Status'] = s[1];
+                                               tmp.properties['Remote'] = s[2];
+                                               tmp.properties['Hub'] = s[3];
+                                               accounts.push(tmp);
+                                       })
+                                       resolve(accounts);
+                               },this));
+               },this));
+       },
+       rpcDownloadAccountStatus: function(account) {
+               return new Promise(L.bind(function (resolve, fail) {
+                       fs.exec_direct('/usr/libexec/vpncmd-call', [ 'account-status-get', account.name ])
+                               .then(L.bind(function(resp) {
+                                       var detailList = this.fixupResponse(resp).split('\n');
+                                       detailList.forEach(function(d) {
+                                               var s = d.split(',');
+                                               if (s.length === 2)
+                                                       account.properties[s[0]] = s[1];
+                                       });
+                                       resolve(account);
+                               },this));
+               },this));
+       },
+       downloadAllStatus: function(accountList) {
+               var promises = [];
+               accountList.forEach(L.bind(function(account) { promises.push(this.rpcDownloadAccountStatus(account)); },this));
+               return Promise.all(promises);
+       },
+       downloadAllAccounts: function() {
+               return new Promise(L.bind(function(resolve) {
+                       this.rpcDownloadAccountLists().then(L.bind(function(accountList) {
+                               this.downloadAllStatus(accountList).then(function(accountListWDetail) { 
+                                       resolve(accountListWDetail); 
+                               });
+                       },this));
+               },this));
+       },
+       updateAccountTable: function(listData) {
+               var tableSelector = '#accountTable';
+               var table = isElem(tableSelector) ? tableSelector : document.querySelector(tableSelector);
+               if (listData.length > 0 ) {
+                       listData.forEach(L.bind(function(account) { 
+                               table.appendChild(this.renderAccountRow(account)); 
+                       },this));
+               } else {
+                       this.setElementShown('#emptyLabel', true);
+               }
+               this.setElementShown('#loader', false);
+       },
+       renderAccountRow: function(account) {
+               var properties = [];
+               for(var key in account.properties) {
+                       if (account.properties.hasOwnProperty(key)) {
+                               properties.push(E('strong', {}, [key + ':']));
+                               properties.push(account.properties[key]);
+                               properties.push(E('br', {}, []));
+                       }
+               }
+               var row = E('div', {'class':'tr cbi-section-table-row'}, [
+                                       E('div', {'class':'td', 'style': 'width: 20%;vertical-align:top;'}, [
+                                               E('strong', {}, ['Account:']),
+                                               account.name
+                                       ]),
+                                       E('div', {'class':'td'}, properties)
+                               ]);
+               return row;
+       },
+       render: function() {
+               var view = E([], [
+                       E('h2', {}, _('SoftEther Status')),
+                       E('div', { 'class': 'cbi-section'}, [
+                               E('div', { 'class': 'cbi-section-node'}, [
+                                       E('div', { 'id': 'accountTable', 'class': 'table cbi-section-table' }, [        ])
+                               ])
+                       ]),
+                       E('div', { 'id': 'loader', 'class': 'spinning' }, _('Loading account information…')),
+                       E('div', { 'id': 'emptyLabel', 'class': 'hidden'}, _('No VPN account configured.'))
+               ]);
+               this.downloadAllAccounts().then(L.bind(function(v) { this.updateAccountTable(v); },this));
+               return view;
+       },
+       handleSave: null,
+       handleSaveApply: null,
+       handleReset: null,
+});
diff --git a/applications/luci-app-softether/root/usr/libexec/vpncmd-call b/applications/luci-app-softether/root/usr/libexec/vpncmd-call
new file mode 100755 (executable)
index 0000000..3d671dc
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+action=$1
+shift
+
+case "$action" in
+       nic-list)
+               /usr/bin/vpncmd localhost /client /csv /cmd:niclist | tail -n +4 2> /dev/null
+       ;;
+       nic-create)
+               /usr/bin/vpncmd localhost /client /cmd:niccreate $1 > /dev/null && echo "OK" || echo "NOK"
+       ;;
+       nic-delete)
+               /usr/bin/vpncmd localhost /client /csv /cmd:nicdelete $1 > /dev/null && echo "OK" || echo "NOK"
+       ;;
+       account-list)
+               /usr/bin/vpncmd localhost /client /csv /cmd:accountlist | tail -n +4 2> /dev/null
+       ;;
+       account-status-get)
+               /usr/bin/vpncmd localhost /client /csv /cmd:accountstatusget $1 | tail -n +4 2> /dev/null
+       ;;
+       *)
+               echo "Usage:" >&2
+               echo "       $0 {nic-list}"                        >&2
+               echo "       $0 {nic-create} {name}"               >&2
+               echo "       $0 {nic-delete} {name}"               >&2
+               echo "       $0 {account-list}"                    >&2
+               echo "       $0 {account-status-get {accountname}" >&2
+               exit 1
+       ;;
+esac
diff --git a/applications/luci-app-softether/root/usr/share/luci/menu.d/luci-app-softether.json b/applications/luci-app-softether/root/usr/share/luci/menu.d/luci-app-softether.json
new file mode 100644 (file)
index 0000000..c0ed09c
--- /dev/null
@@ -0,0 +1,13 @@
+{
+       "admin/status/softether": {
+               "title": "SoftEther Status",
+               "order": 95,
+               "action": {
+                       "type": "view",
+                       "path": "softether-status"
+               },
+               "depends": {
+                       "acl": [ "luci-app-softether" ]
+               }
+       }
+}
diff --git a/applications/luci-app-softether/root/usr/share/rpcd/acl.d/luci-app-softether.json b/applications/luci-app-softether/root/usr/share/rpcd/acl.d/luci-app-softether.json
new file mode 100644 (file)
index 0000000..900e4be
--- /dev/null
@@ -0,0 +1,12 @@
+{
+       "luci-app-softether": {
+               "description": "Grant access to softether management",
+               "read": {
+                       "cgi-io": [ "exec" ],
+                       "file": {
+                               "/usr/libexec/vpncmd-call account-list": [ "exec" ],
+                               "/usr/libexec/vpncmd-call account-status-get *": [ "exec" ]
+                       }
+               }
+       }
+}