From 61a74661177418c273f6e0b15fc7f6a904a8cc6b Mon Sep 17 00:00:00 2001 From: Tobias Mueller Date: Mon, 16 Oct 2023 11:53:08 +0200 Subject: [PATCH] initial PoC for a Web interface --- srl-blue-merle/usr/libexec/blue-merle | 3 + .../usr/share/luci/menu.d/luci-app-opkg2.json | 6 +- .../share/rpcd/acl.d/luci-app-blue-merle.json | 26 +++ .../usr/share/rpcd/acl.d/luci-app-opkg2.json | 29 --- .../www/luci-static/resources/view/opkg2.js | 181 +++++------------- 5 files changed, 75 insertions(+), 170 deletions(-) create mode 100755 srl-blue-merle/usr/libexec/blue-merle create mode 100644 srl-blue-merle/usr/share/rpcd/acl.d/luci-app-blue-merle.json delete mode 100644 srl-blue-merle/usr/share/rpcd/acl.d/luci-app-opkg2.json diff --git a/srl-blue-merle/usr/libexec/blue-merle b/srl-blue-merle/usr/libexec/blue-merle new file mode 100755 index 0000000..a758ac5 --- /dev/null +++ b/srl-blue-merle/usr/libexec/blue-merle @@ -0,0 +1,3 @@ +#!/bin/sh + +echo Hello, World! diff --git a/srl-blue-merle/usr/share/luci/menu.d/luci-app-opkg2.json b/srl-blue-merle/usr/share/luci/menu.d/luci-app-opkg2.json index b4d2d79..bc5db82 100644 --- a/srl-blue-merle/usr/share/luci/menu.d/luci-app-opkg2.json +++ b/srl-blue-merle/usr/share/luci/menu.d/luci-app-opkg2.json @@ -1,13 +1,13 @@ { - "admin/system/opkg2": { - "title": "Software", + "admin/network/blue-merle": { + "title": "Blue Merle", "order": 30, "action": { "type": "view", "path": "opkg2" }, "depends": { - "acl": [ "luci-app-opkg2" ] + "acl": [ "luci-app-blue-merle" ] } } } diff --git a/srl-blue-merle/usr/share/rpcd/acl.d/luci-app-blue-merle.json b/srl-blue-merle/usr/share/rpcd/acl.d/luci-app-blue-merle.json new file mode 100644 index 0000000..8e9ff2c --- /dev/null +++ b/srl-blue-merle/usr/share/rpcd/acl.d/luci-app-blue-merle.json @@ -0,0 +1,26 @@ +{ + "luci-app-blue-merle": { + "description": "Grant access to opkg management", + "read": { + "cgi-io": [ "exec" ], + "file": { + "/usr/libexec/blue-merle": [ "exec" ], + "/usr/libexec/blue-merle shred": [ "exec" ], + "/usr/libexec/blue-merle *": [ "exec" ], + "/etc/opkg.conf": [ "read" ], + "/etc/opkg/*.conf": [ "read" ] + }, + "ubus": { + "luci": [ "getMountPoints" ] + } + }, + "write": { + "file": { + "/usr/libexec/blue-merle": [ "exec" ], + "/usr/libexec/blue-merle shred": [ "exec" ], + "/usr/libexec/blue-merle *": [ "exec" ], + "/tmp/upload.ipk": [ "write" ] + } + } + } +} diff --git a/srl-blue-merle/usr/share/rpcd/acl.d/luci-app-opkg2.json b/srl-blue-merle/usr/share/rpcd/acl.d/luci-app-opkg2.json deleted file mode 100644 index 1ed3aa0..0000000 --- a/srl-blue-merle/usr/share/rpcd/acl.d/luci-app-opkg2.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "luci-app-opkg2": { - "description": "Grant access to opkg management", - "read": { - "cgi-io": [ "exec" ], - "file": { - "/usr/libexec/opkg-list installed": [ "exec" ], - "/usr/libexec/opkg-list available": [ "exec" ], - "/usr/libexec/opkg-call list-installed": [ "exec" ], - "/usr/libexec/opkg-call list-available": [ "exec" ], - "/etc/opkg.conf": [ "read" ], - "/etc/opkg/*.conf": [ "read" ] - }, - "ubus": { - "luci": [ "getMountPoints" ] - } - }, - "write": { - "file": { - "/usr/libexec/opkg-call install *": [ "exec" ], - "/usr/libexec/opkg-call remove *": [ "exec" ], - "/usr/libexec/opkg-call update *": [ "exec" ], - "/etc/opkg.conf": [ "write" ], - "/etc/opkg/*.conf": [ "write" ], - "/tmp/upload.ipk": [ "write" ] - } - } - } -} diff --git a/srl-blue-merle/www/luci-static/resources/view/opkg2.js b/srl-blue-merle/www/luci-static/resources/view/opkg2.js index 72a444c..f167a7e 100644 --- a/srl-blue-merle/www/luci-static/resources/view/opkg2.js +++ b/srl-blue-merle/www/luci-static/resources/view/opkg2.js @@ -199,140 +199,6 @@ function parseList(s, dest) } } -function display(pattern) -{ - var src = packages[currentDisplayMode === 'updates' ? 'installed' : currentDisplayMode], - table = document.querySelector('#packages'), - pagers = document.querySelectorAll('.controls > .pager'), - i18n_filter = null; - - currentDisplayRows.length = 0; - - if (typeof(pattern) === 'string' && pattern.length > 0) - pattern = new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'ig'); - - switch (document.querySelector('input[name="filter_i18n"]:checked').value) { - case 'all': - i18n_filter = /^luci-i18n-/; - break; - - case 'lang': - i18n_filter = new RegExp('^luci-i18n-(base-.+|.+-(' + languages.join('|') + '))$'); - break; - } - - for (var name in src.pkgs) { - var pkg = src.pkgs[name], - desc = pkg.description || '', - altsize = null; - - if (!pkg.size && packages.available.pkgs[name]) - altsize = packages.available.pkgs[name].size; - - if (!desc && packages.available.pkgs[name]) - desc = packages.available.pkgs[name].description || ''; - - desc = desc.split(/\n/); - desc = desc[0].trim() + (desc.length > 1 ? '…' : ''); - - if ((pattern instanceof RegExp) && - !name.match(pattern) && !desc.match(pattern)) - continue; - - if (name.indexOf('luci-i18n-') === 0 && (!(i18n_filter instanceof RegExp) || !name.match(i18n_filter))) - continue; - - var btn, ver; - - if (currentDisplayMode === 'updates') { - var avail = packages.available.pkgs[name], - inst = packages.installed.pkgs[name]; - - if (!inst || !inst.installed) - continue; - - if (!avail || compareVersion(avail.version, pkg.version) <= 0) - continue; - - ver = '%s » %s'.format( - truncateVersion(pkg.version || '-'), - truncateVersion(avail.version || '-')); - - btn = E('div', { - 'class': 'btn cbi-button-positive', - 'data-package': name, - 'click': handleInstall - }, _('Upgrade…')); - } - else if (currentDisplayMode === 'installed') { - if (!pkg.installed) - continue; - - ver = truncateVersion(pkg.version || '-'); - btn = E('div', { - 'class': 'btn cbi-button-negative', - 'data-package': name, - 'click': handleRemove - }, _('Remove…')); - } - else { - var inst = packages.installed.pkgs[name]; - - ver = truncateVersion(pkg.version || '-'); - - if (!inst || !inst.installed) - btn = E('div', { - 'class': 'btn cbi-button-action', - 'data-package': name, - 'click': handleInstall - }, _('Install…')); - else if (inst.installed && inst.version != pkg.version) - btn = E('div', { - 'class': 'btn cbi-button-positive', - 'data-package': name, - 'click': handleInstall - }, _('Upgrade…')); - else - btn = E('div', { - 'class': 'btn cbi-button-neutral', - 'disabled': 'disabled' - }, _('Installed')); - } - - name = '%h'.format(name); - desc = '%h'.format(desc || '-'); - - if (pattern) { - name = name.replace(pattern, '$&'); - desc = desc.replace(pattern, '$&'); - } - - currentDisplayRows.push([ - name, - ver, - pkg.size ? '%1024mB'.format(pkg.size) - : (altsize ? '~%1024mB'.format(altsize) : '-'), - desc, - btn - ]); - } - - currentDisplayRows.sort(function(a, b) { - if (a[0] < b[0]) - return -1; - else if (a[0] > b[0]) - return 1; - else - return 0; - }); - - for (var i = 0; i < pagers.length; i++) { - pagers[i].parentNode.style.display = ''; - pagers[i].setAttribute('data-offset', 100); - } - - handlePage({ target: pagers[0].querySelector('.prev') }); -} function handlePage(ev) { @@ -852,9 +718,48 @@ function handleConfig(ev) { var conf = {}; - ui.showModal(_('OPKG Configuration'), [ - E('p', { 'class': 'spinning' }, _('Loading configuration data…')) - ]); + var cmd = "/usr/libexec/blue-merle"; + var dlg = ui.showModal(_('Executing blue merle'), [ + E('p', { 'class': 'spinning' }, + _('Waiting for the %h command to complete…').format(cmd)) + ]); + + var argv = []; //["shred"]; + fs.exec_direct('/usr/libexec/blue-merle', argv, 'json').then(function(res) { + + if (res.stdout) + dlg.appendChild(E('pre', [ res.stdout ])); + + if (res.stderr) { + dlg.appendChild(E('h5', _('Errors'))); + dlg.appendChild(E('pre', { 'class': 'errors' }, [ res.stderr ])); + } + + if (res.code !== 0) + dlg.appendChild(E('p', _('The opkg %h command failed with code %d.').format(cmd, (res.code & 0xff) || -1))); + + dlg.appendChild(E('div', { 'class': 'right' }, + E('div', { + 'class': 'btn', + 'click': L.bind(function(res) { + if (ui.menu && ui.menu.flushCache) + ui.menu.flushCache(); + + ui.hideModal(); + updateLists(); + + if (res.code !== 0) + rejectFn(new Error(res.stderr || 'opkg error %d'.format(res.code))); + else + resolveFn(res); + }, this, res) + }, _('Dismiss')))); + }).catch(function(err) { + ui.addNotification(null, E('p', _('Unable to execute opkg %s command: %s').format(cmd, err))); + ui.hideModal(); + }); + + fs.list('/etc/opkg').then(function(partials) { var files = [ '/etc/opkg.conf' ]; @@ -914,7 +819,7 @@ function handleConfig(ev) }, _('Save')), ])); - ui.showModal(_('OPKG Configuration'), body); + //ui.showModal(_('OPKG Configuration'), body); }); }