From ec5ce985fee50d4bcb02e70ae95be68cdfafc49e Mon Sep 17 00:00:00 2001 From: BERENYI Balazs Date: Wed, 16 Dec 2020 17:22:37 +0000 Subject: [PATCH] luci-app-softether: add basic softether status page Signed-off-by: BERENYI Balazs --- applications/luci-app-softether/Makefile | 12 ++ .../resources/view/softether-status.js | 117 ++++++++++++++++++ .../root/usr/libexec/vpncmd-call | 31 +++++ .../share/luci/menu.d/luci-app-softether.json | 13 ++ .../share/rpcd/acl.d/luci-app-softether.json | 12 ++ 5 files changed, 185 insertions(+) create mode 100644 applications/luci-app-softether/Makefile create mode 100644 applications/luci-app-softether/htdocs/luci-static/resources/view/softether-status.js create mode 100755 applications/luci-app-softether/root/usr/libexec/vpncmd-call create mode 100644 applications/luci-app-softether/root/usr/share/luci/menu.d/luci-app-softether.json create mode 100644 applications/luci-app-softether/root/usr/share/rpcd/acl.d/luci-app-softether.json diff --git a/applications/luci-app-softether/Makefile b/applications/luci-app-softether/Makefile new file mode 100644 index 0000000000..06a310c7e1 --- /dev/null +++ b/applications/luci-app-softether/Makefile @@ -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 index 0000000000..3c3130d96f --- /dev/null +++ b/applications/luci-app-softether/htdocs/luci-static/resources/view/softether-status.js @@ -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 index 0000000000..3d671dce4c --- /dev/null +++ b/applications/luci-app-softether/root/usr/libexec/vpncmd-call @@ -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 index 0000000000..c0ed09c20f --- /dev/null +++ b/applications/luci-app-softether/root/usr/share/luci/menu.d/luci-app-softether.json @@ -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 index 0000000000..900e4bed78 --- /dev/null +++ b/applications/luci-app-softether/root/usr/share/rpcd/acl.d/luci-app-softether.json @@ -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" ] + } + } + } +} -- 2.30.2