mirror of
https://github.com/openwrt/luci.git
synced 2025-12-20 01:10:26 +08:00
luci-app-travelmate: sync with travelmate 2.3.0-1
Some checks failed
LuCI repo CodeQL Analysis / Analyze JavaScript and JSON (javascript-typescript) (push) Has been cancelled
Some checks failed
LuCI repo CodeQL Analysis / Analyze JavaScript and JSON (javascript-typescript) (push) Has been cancelled
Signed-off-by: Dirk Brenken <dev@brenken.org>
This commit is contained in:
@@ -6,6 +6,8 @@ include $(TOPDIR)/rules.mk
|
||||
LUCI_TITLE:=LuCI support for Travelmate
|
||||
LUCI_DEPENDS:=+luci-base +luci-lib-uqr +travelmate
|
||||
|
||||
PKG_VERSION:=2.3.0
|
||||
PKG_RELEASE:=1
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
PKG_MAINTAINER:=Dirk Brenken <dev@brenken.org>
|
||||
|
||||
|
||||
@@ -1,33 +1,54 @@
|
||||
'use strict';
|
||||
'require fs';
|
||||
'require rpc';
|
||||
|
||||
const callLogRead = rpc.declare({
|
||||
object: 'log',
|
||||
method: 'read',
|
||||
params: ['lines', 'stream', 'oneshot'],
|
||||
expect: {}
|
||||
});
|
||||
|
||||
function Logview(logtag, name) {
|
||||
return L.view.extend({
|
||||
load: function() {
|
||||
return Promise.all([
|
||||
L.resolveDefault(fs.stat('/sbin/logread'), null),
|
||||
L.resolveDefault(fs.stat('/usr/sbin/logread'), null)
|
||||
]);
|
||||
},
|
||||
load: () => Promise.resolve(),
|
||||
|
||||
render: function(stat) {
|
||||
let logger = stat[0]?.path || stat[1]?.path || null;
|
||||
render: () => {
|
||||
L.Poll.add(() => {
|
||||
return callLogRead(1000, false, true).then(res => {
|
||||
const logEl = document.getElementById('logfile');
|
||||
if (!logEl) return;
|
||||
|
||||
if (!logger) {
|
||||
return E('div', { class: 'error' }, _('logread not found on system.'));
|
||||
}
|
||||
L.Poll.add(function() {
|
||||
return L.resolveDefault(fs.exec_direct(logger, ['-e', logtag])).then(function(res) {
|
||||
var log = document.getElementById('logfile');
|
||||
if (log) {
|
||||
log.value = res ? res.trim() : _('No %s related logs yet!').format(name);
|
||||
log.scrollTop = log.scrollHeight;
|
||||
const entries = res?.log ?? [];
|
||||
if (entries.length > 0) {
|
||||
const filtered = entries
|
||||
.filter(entry => !logtag || entry.msg.includes(logtag))
|
||||
.map(entry => {
|
||||
const d = new Date(entry.time);
|
||||
const date = d.toLocaleDateString([], {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit'
|
||||
});
|
||||
const time = d.toLocaleTimeString([], {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
hour12: false
|
||||
});
|
||||
return `[${date}-${time}] ${entry.msg}`;
|
||||
});
|
||||
logEl.value = filtered.join('\n');
|
||||
} else {
|
||||
logEl.value = _('No %s related logs yet!').format(name);
|
||||
}
|
||||
logEl.scrollTop = logEl.scrollHeight;
|
||||
});
|
||||
});
|
||||
|
||||
return E('div', { class: 'cbi-map' }, [
|
||||
E('div', { class: 'cbi-section' }, [
|
||||
E('div', { class: 'cbi-section-descr' }, _('The syslog output, pre-filtered for messages related to: %s').format(name)),
|
||||
E('div', { class: 'cbi-section-descr' },
|
||||
_('The syslog output, pre-filtered for messages related to: %s').format(name)),
|
||||
E('textarea', {
|
||||
id: 'logfile',
|
||||
style: 'min-height: 500px; max-height: 90vh; width: 100%; padding: 5px; font-family: monospace; resize: vertical;',
|
||||
@@ -37,12 +58,11 @@ function Logview(logtag, name) {
|
||||
])
|
||||
]);
|
||||
},
|
||||
|
||||
handleSaveApply: null,
|
||||
handleSave: null,
|
||||
handleReset: null
|
||||
});
|
||||
}
|
||||
|
||||
return L.Class.extend({
|
||||
Logview: Logview
|
||||
});
|
||||
return L.Class.extend({ Logview });
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
'use strict';
|
||||
'require dom';
|
||||
'require view';
|
||||
'require poll';
|
||||
'require fs';
|
||||
@@ -14,53 +15,63 @@
|
||||
*/
|
||||
function handleAction(ev) {
|
||||
let ifaceValue;
|
||||
if (ev === 'restart') {
|
||||
if (ev === 'restartInterface') {
|
||||
ifaceValue = String(uci.get('travelmate', 'global', 'trm_iface') || 'trm_wwan');
|
||||
return fs.exec('/etc/init.d/travelmate', ['stop'])
|
||||
.then(fs.exec('/sbin/ifup', [ifaceValue]))
|
||||
.then(fs.exec('/etc/init.d/travelmate', ['start']))
|
||||
}
|
||||
if (ev === 'restartTravelmate') {
|
||||
const map = document.querySelector('.cbi-map');
|
||||
return dom.callClassMethod(map, 'save')
|
||||
.then(L.bind(ui.changes.apply, ui.changes))
|
||||
.then(function () {
|
||||
return fs.exec_direct('/etc/init.d/travelmate', ['restart']);
|
||||
})
|
||||
}
|
||||
if (ev === 'setup') {
|
||||
ifaceValue = String(uci.get('travelmate', 'global', 'trm_iface') || '');
|
||||
L.ui.showModal(_('Interface Wizard'), [
|
||||
E('p', _('To use Travelmate, you have to set up an uplink interface once. This wizard creates an IPv4- and an IPv6 alias network interface with all required network- and firewall settings.')),
|
||||
E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
|
||||
E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em' }, [
|
||||
E('input', { 'class': 'cbi-input-text', 'id': 'iface', 'placeholder': 'trm_wwan', 'value': ifaceValue, 'maxlength': '15', 'spellcheck': 'false' }),
|
||||
'\xa0\xa0\xa0',
|
||||
E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em;' }, [
|
||||
E('input', { 'class': 'cbi-input-text', 'id': 'iface', 'placeholder': 'trm_wwan', 'value': ifaceValue, 'maxlength': '15', 'spellcheck': 'false', style: 'margin-right:.5em;' }),
|
||||
_('The uplink interface name')
|
||||
]),
|
||||
E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em' }, [
|
||||
E('input', { 'class': 'cbi-input-text', 'id': 'zone', 'placeholder': 'wan', 'maxlength': '15', 'spellcheck': 'false' }),
|
||||
'\xa0\xa0\xa0',
|
||||
E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em;' }, [
|
||||
E('input', { 'class': 'cbi-input-text', 'id': 'zone', 'placeholder': 'wan', 'maxlength': '15', 'spellcheck': 'false', style: 'margin-right:.5em;' }),
|
||||
_('The firewall zone name')
|
||||
]),
|
||||
E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em' }, [
|
||||
E('input', { 'class': 'cbi-input-text', 'id': 'metric', 'placeholder': '100', 'maxlength': '3', 'spellcheck': 'false' }),
|
||||
'\xa0\xa0\xa0',
|
||||
E('label', { 'class': 'cbi-input-text', 'style': 'padding-top:.5em;' }, [
|
||||
E('input', { 'class': 'cbi-input-text', 'id': 'metric', 'placeholder': '100', 'maxlength': '3', 'spellcheck': 'false', style: 'margin-right:.5em;' }),
|
||||
_('The interface metric')
|
||||
])
|
||||
]),
|
||||
E('div', { 'class': 'right' }, [
|
||||
E('button', {
|
||||
'class': 'cbi-button',
|
||||
'style': 'float:none;margin-right:.4em;',
|
||||
'click': L.hideModal
|
||||
}, _('Dismiss')),
|
||||
' ',
|
||||
E('button', {
|
||||
'class': 'cbi-button cbi-button-positive important',
|
||||
'style': 'float:none',
|
||||
'click': ui.createHandlerFn(this, function (ev) {
|
||||
let iface = document.getElementById('iface').value || 'trm_wwan',
|
||||
zone = document.getElementById('zone').value || 'wan',
|
||||
metric = document.getElementById('metric').value || '100';
|
||||
fs.exec('/etc/init.d/travelmate', ['setup', iface, zone, metric]).then(function (rc) {
|
||||
L.hideModal();
|
||||
if (rc.code == 1) {
|
||||
ui.addNotification(null, E('p', _('Setup failed, the interface already exists!')), 'error');
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
const iface = (document.getElementById('iface').value || 'trm_wwan').toLowerCase();
|
||||
const zone = (document.getElementById('zone').value || 'wan').toLowerCase();
|
||||
const metric = document.getElementById('metric').value.replace(/\D/g, '') || '100';
|
||||
fs.exec('/etc/init.d/travelmate', ['setup', iface, zone, metric])
|
||||
.then(function (rc) {
|
||||
L.hideModal();
|
||||
switch (rc.code) {
|
||||
case 1:
|
||||
ui.addNotification(null, E('p', _('The interface already exists!')), 'info');
|
||||
break;
|
||||
default:
|
||||
location.reload();
|
||||
break;
|
||||
}
|
||||
})
|
||||
})
|
||||
}, _('Save'))
|
||||
])
|
||||
@@ -70,20 +81,20 @@ function handleAction(ev) {
|
||||
|
||||
if (ev === 'qrcode') {
|
||||
return Promise.all([
|
||||
uci.load('wireless')
|
||||
]).then(function () {
|
||||
let w_sid, w_device, w_ssid, w_enc, w_key, w_hidden, result,
|
||||
w_sections = uci.sections('wireless', 'wifi-iface'),
|
||||
optionsAP = [E('option', { value: '' }, [_('-- AP Selection --')])];
|
||||
for (let i = 0; i < w_sections.length; i++) {
|
||||
if (w_sections[i].mode === 'ap' && w_sections[i].disabled !== '1') {
|
||||
w_sid = i;
|
||||
w_device = w_sections[i].device;
|
||||
w_ssid = w_sections[i].ssid;
|
||||
optionsAP.push(E('option', { value: w_sid }, w_device + ', ' + w_ssid));
|
||||
uci.load('wireless')])
|
||||
.then(function () {
|
||||
let w_sid, w_device, w_ssid, w_enc, w_key, w_hidden, result;
|
||||
const w_sections = uci.sections('wireless', 'wifi-iface');
|
||||
const optionsAP = [E('option', { value: '' }, [_('-- AP Selection --')])];
|
||||
for (let i = 0; i < w_sections.length; i++) {
|
||||
if (w_sections[i].mode === 'ap' && w_sections[i].disabled !== '1') {
|
||||
w_sid = i;
|
||||
w_device = w_sections[i].device;
|
||||
w_ssid = w_sections[i].ssid;
|
||||
optionsAP.push(E('option', { value: w_sid }, w_device + ', ' + w_ssid));
|
||||
}
|
||||
}
|
||||
}
|
||||
let selectAP = E('select', {
|
||||
let selectAP = E('select', {
|
||||
id: 'selectID',
|
||||
class: 'cbi-input-select',
|
||||
change: function (ev) {
|
||||
@@ -100,16 +111,17 @@ function handleAction(ev) {
|
||||
} else {
|
||||
w_enc = 'WPA';
|
||||
}
|
||||
let data = `WIFI:S: ${w_ssid};T: ${w_enc};P: ${w_key};H: ${w_hidden};;`;
|
||||
const data = `WIFI:S:${w_ssid};T:${w_enc};P:${w_key};H:${w_hidden};;`;
|
||||
const options = {
|
||||
pixelSize: 4,
|
||||
pixelSize: 12,
|
||||
margin: 1,
|
||||
ecLevel: 'M',
|
||||
whiteColor: 'white',
|
||||
blackColor: 'black'
|
||||
};
|
||||
let svg = uqr.renderSVG(data, options);
|
||||
const svg = uqr.renderSVG(data, options);
|
||||
result.innerHTML = svg.trim();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
result.textContent = '';
|
||||
}
|
||||
}
|
||||
@@ -117,18 +129,15 @@ function handleAction(ev) {
|
||||
L.ui.showModal(_('QR-Code Overview'), [
|
||||
E('p', _('Render the QR-Code of the selected Access Point to transfer the WLAN credentials to your mobile devices comfortably.')),
|
||||
E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
|
||||
E('label', { 'class': 'cbi-input-select', 'style': 'padding-top:.5em' }, [
|
||||
selectAP,
|
||||
])
|
||||
E('label', { 'class': 'cbi-input-select', 'style': 'padding-top:.5em' }, [selectAP,])
|
||||
]),
|
||||
'\xa0',
|
||||
E('div', {
|
||||
'id': 'qrcode'
|
||||
}),
|
||||
E('div', { 'class': 'right' }, [
|
||||
E('button', {
|
||||
'class': 'cbi-button',
|
||||
'click': L.hideModal
|
||||
'click': L.hideModal
|
||||
}, _('Dismiss'))
|
||||
])
|
||||
]);
|
||||
@@ -141,7 +150,7 @@ return view.extend({
|
||||
return Promise.all([
|
||||
uci.load('travelmate'),
|
||||
network.getWifiDevices().then(function (res) {
|
||||
let radios = [];
|
||||
const radios = [];
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
radios.push(res[i].sid);
|
||||
}
|
||||
@@ -160,18 +169,28 @@ return view.extend({
|
||||
For further information <a href="https://github.com/openwrt/packages/blob/master/net/travelmate/files/README.md" target="_blank" rel="noreferrer noopener" >check the online documentation</a>. <br /> \
|
||||
<b><em>Please note:</em></b> On first start please call the \'Interface Wizard\' once, to make the necessary network- and firewall settings.'));
|
||||
|
||||
/*
|
||||
set text content helper function
|
||||
*/
|
||||
const setText = (id, value) => {
|
||||
const el = document.getElementById(id);
|
||||
if (el) {
|
||||
el.textContent = value || '-';
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
poll runtime information
|
||||
*/
|
||||
pollData: poll.add(function () {
|
||||
return L.resolveDefault(fs.stat('/tmp/trm_runtime.json'), null).then(function (res) {
|
||||
let status = document.getElementById('status');
|
||||
const status = document.getElementById('status');
|
||||
if (res && res.size > 0) {
|
||||
L.resolveDefault(fs.read_direct('/tmp/trm_runtime.json'), null).then(function (res) {
|
||||
if (res) {
|
||||
let info = JSON.parse(res);
|
||||
if (status && info) {
|
||||
status.textContent = (info.data.travelmate_status || '-') + ' / ' + (info.data.travelmate_version || '-');
|
||||
status.textContent = `${info.data.travelmate_status || '-'} (frontend: ${info.data.frontend_ver || '-'} / backend: ${info.data.backend_ver || '-'})`;
|
||||
if (info.data.travelmate_status.startsWith('running')) {
|
||||
if (!status.classList.contains("spinning")) {
|
||||
status.classList.add("spinning");
|
||||
@@ -187,33 +206,15 @@ return view.extend({
|
||||
status.classList.remove("spinning");
|
||||
}
|
||||
}
|
||||
let station_id = document.getElementById('station_id');
|
||||
if (station_id && info) {
|
||||
station_id.textContent = info.data.station_id || '-';
|
||||
}
|
||||
let station_mac = document.getElementById('station_mac');
|
||||
if (station_mac && info) {
|
||||
station_mac.textContent = info.data.station_mac || '-';
|
||||
}
|
||||
let station_interfaces = document.getElementById('station_interfaces');
|
||||
if (station_interfaces && info) {
|
||||
station_interfaces.textContent = info.data.station_interfaces || '-';
|
||||
}
|
||||
let station_subnet = document.getElementById('station_subnet');
|
||||
if (station_subnet && info) {
|
||||
station_subnet.textContent = info.data.station_subnet || '-';
|
||||
}
|
||||
let run_flags = document.getElementById('run_flags');
|
||||
if (run_flags && info) {
|
||||
run_flags.textContent = info.data.run_flags || '-';
|
||||
}
|
||||
let ext_hooks = document.getElementById('ext_hooks');
|
||||
if (ext_hooks && info) {
|
||||
ext_hooks.textContent = info.data.ext_hooks || '-';
|
||||
}
|
||||
let run = document.getElementById('run');
|
||||
if (run && info) {
|
||||
run.textContent = info.data.last_run || '-';
|
||||
if (info) {
|
||||
setText('station_id', info.data.station_id);
|
||||
setText('station_mac', info.data.station_mac);
|
||||
setText('station_interfaces', info.data.station_interfaces);
|
||||
setText('station_subnet', info.data.station_subnet);
|
||||
setText('run_flags', info.data.run_flags);
|
||||
setText('ext_hooks', info.data.ext_hooks);
|
||||
setText('run', info.data.last_run);
|
||||
setText('sys', info.data.system);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -265,29 +266,9 @@ return view.extend({
|
||||
E('label', { 'class': 'cbi-value-title', 'style': 'margin-bottom:-5px;padding-top:0rem;' }, _('Last Run')),
|
||||
E('div', { 'class': 'cbi-value-field', 'id': 'run', 'style': 'margin-bottom:-5px;color:#37c;' }, '-')
|
||||
]),
|
||||
E('div', { class: 'right' }, [
|
||||
E('button', {
|
||||
'class': 'cbi-button cbi-button-apply',
|
||||
'style': 'float:none;margin-right:.4em;',
|
||||
'id': 'btn_suspend',
|
||||
'click': ui.createHandlerFn(this, function () {
|
||||
return handleAction('qrcode');
|
||||
})
|
||||
}, [_('AP QR-Codes...')]),
|
||||
E('button', {
|
||||
'class': 'cbi-button cbi-button-negative',
|
||||
'style': 'float:none;margin-right:.4em;',
|
||||
'click': ui.createHandlerFn(this, function () {
|
||||
return handleAction('restart');
|
||||
})
|
||||
}, [_('Restart Interface')]),
|
||||
E('button', {
|
||||
'class': 'cbi-button cbi-button-negative',
|
||||
'style': 'float:none;',
|
||||
'click': ui.createHandlerFn(this, function () {
|
||||
return handleAction('setup');
|
||||
})
|
||||
}, [_('Interface Wizard...')])
|
||||
E('div', { 'class': 'cbi-value' }, [
|
||||
E('label', { 'class': 'cbi-value-title', 'style': 'margin-bottom:-5px;padding-top:0rem;' }, _('System Info')),
|
||||
E('div', { 'class': 'cbi-value-field', 'id': 'sys', 'style': 'margin-bottom:-5px;color:#37c;' }, '-')
|
||||
])
|
||||
]);
|
||||
}, o, this);
|
||||
@@ -308,6 +289,12 @@ return view.extend({
|
||||
o = s.taboption('general', form.Flag, 'trm_enabled', _('Enabled'), _('Enable the travelmate service.'));
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.taboption('general', widgets.NetworkSelect, 'trm_iface', _('WWAN Interface'), _('Select an existing wireless WAN network interface or create a new one with the \'Interface Wizard\'.'));
|
||||
o.multiple = false;
|
||||
o.nocreate = true;
|
||||
o.optional = true;
|
||||
o.rmempty = true;
|
||||
|
||||
o = s.taboption('general', form.MultiValue, 'trm_radio', _('Radio Selection'), _('Restrict travelmate to certain radio\(s\).'));
|
||||
for (let i = 0; i < result[1].length; i++) {
|
||||
o.value(result[1][i]);
|
||||
@@ -315,7 +302,7 @@ return view.extend({
|
||||
o.placeholder = _('-- default --');
|
||||
o.optional = true;
|
||||
o.rmempty = true;
|
||||
o.write = function(section_id, value) {
|
||||
o.write = function (section_id, value) {
|
||||
uci.set('travelmate', section_id, 'trm_radio', value.join(' '));
|
||||
};
|
||||
|
||||
@@ -456,10 +443,10 @@ return view.extend({
|
||||
*/
|
||||
o = s.taboption('adv_email', form.DummyValue, '_sub');
|
||||
o.rawhtml = true;
|
||||
o.default = '<em style="color:#37c;font-weight:bold;">' + _('E-Mail notifications require the separate setup of the <em>msmtp</em> package.') + '</em>'
|
||||
+ '<hr style="width: 200px; height: 1px;" />'
|
||||
o.default = '<em style="color:#37c;font-weight:bold;">' + _('Changes on this tab needs a travelmate service restart to take effect.') + '</em>'
|
||||
+ '<hr style="width: 200px; height: 1px;" />';
|
||||
|
||||
o = s.taboption('adv_email', form.Flag, 'trm_mail', _('E-Mail Hook'), _('Sends notification E-Mails after every succesful uplink connect.'));
|
||||
o = s.taboption('adv_email', form.Flag, 'trm_mail', _('E-Mail Notification'), _('Sends notification E-Mails after every succesful uplink connect.'));
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.taboption('adv_email', form.Value, 'trm_mailreceiver', _('E-Mail Receiver Address'), _('Receiver address for travelmate notification E-Mails.'));
|
||||
@@ -482,7 +469,47 @@ return view.extend({
|
||||
o.placeholder = 'trm_notify';
|
||||
o.rmempty = true;
|
||||
|
||||
s = m.section(form.NamedSection, 'global');
|
||||
s.render = L.bind(function () {
|
||||
return E('div', { 'class': 'cbi-page-actions' }, [
|
||||
E('button', {
|
||||
'class': 'btn cbi-button cbi-button-negative important',
|
||||
'style': 'float:none;margin-right:.4em;',
|
||||
'title': 'Interface Setup',
|
||||
'click': ui.createHandlerFn(this, function () {
|
||||
return handleAction('setup');
|
||||
})
|
||||
}, [_('Interface Wizard...')]),
|
||||
E('button', {
|
||||
'class': 'btn cbi-button cbi-button-negative important',
|
||||
'style': 'float:none;margin-right:.4em;',
|
||||
'title': 'Restart Interface',
|
||||
'click': ui.createHandlerFn(this, function () {
|
||||
return handleAction('restartInterface');
|
||||
})
|
||||
}, [_('Interface Restart')]),
|
||||
E('button', {
|
||||
'class': 'btn cbi-button cbi-button-apply important',
|
||||
'style': 'float:none;margin-right:.4em;',
|
||||
'title': 'QRCode',
|
||||
'id': 'btn_suspend',
|
||||
'click': ui.createHandlerFn(this, function () {
|
||||
return handleAction('qrcode');
|
||||
})
|
||||
}, [_('AP QR-Codes...')]),
|
||||
E('button', {
|
||||
'class': 'btn cbi-button cbi-button-positive important',
|
||||
'style': 'float:none;margin-right:.4em;',
|
||||
'title': 'Save & Restart',
|
||||
'click': function () {
|
||||
return handleAction('restartTravelmate');
|
||||
}
|
||||
}, [_('Save & Restart')])
|
||||
])
|
||||
});
|
||||
return m.render();
|
||||
},
|
||||
handleSaveApply: null,
|
||||
handleSave: null,
|
||||
handleReset: null
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"depends": {
|
||||
"acl": [ "luci-app-travelmate" ],
|
||||
"fs": {
|
||||
"/usr/bin/travelmate.sh": "executable",
|
||||
"/usr/bin/travelmate-service.sh": "executable",
|
||||
"/etc/init.d/travelmate": "executable"
|
||||
},
|
||||
"uci": { "travelmate": true }
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
"/var/run/travelmate.scan": [ "read" ],
|
||||
"/var/state/travelmate.refresh": [ "read" ],
|
||||
"/tmp/trm_runtime.json": [ "read" ],
|
||||
"/sbin/logread -e trm-": [ "exec" ],
|
||||
"/usr/sbin/logread -e trm-": [ "exec" ],
|
||||
"/sbin/ifup *": [ "exec" ],
|
||||
"/etc/init.d/travelmate start" : [ "exec" ],
|
||||
"/etc/init.d/travelmate restart" : [ "exec" ],
|
||||
"/etc/init.d/travelmate stop" : [ "exec" ],
|
||||
"/etc/init.d/travelmate setup [0-9a-z_]* [0-9a-z_]* [0-9]*" : [ "exec" ],
|
||||
"/etc/init.d/travelmate scan radio[0-1]" : [ "exec" ]
|
||||
"/etc/init.d/travelmate scan radio[0-9]" : [ "exec" ]
|
||||
},
|
||||
"uci": [ "travelmate", "wireless" ]
|
||||
"uci": [ "travelmate", "wireless" ],
|
||||
"log": [ "read" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user