luci: Add log viewer

This commit is contained in:
remittor
2025-02-09 20:42:51 +03:00
parent 41df444327
commit adab5d93c5
4 changed files with 178 additions and 0 deletions

View File

@@ -0,0 +1,155 @@
'use strict';
'require view';
'require fs';
'require form';
'require poll';
'require uci';
'require ui';
'require view.zapret.tools as tools';
return view.extend({
retrieveLog: async function() {
return Promise.all([
L.resolveDefault(fs.stat('/bin/cat'), null),
fs.exec('/usr/bin/find', [ '/tmp', '-maxdepth', '1', '-type', 'f', '-name', 'zapret+*.log' ]),
]).then(function(status_array) {
var filereader = status_array[0] ? status_array[0].path : null;
var log_data = status_array[1]; // stdout: multiline text
if (log_data.code != 0) {
ui.addNotification(null, E('p', _('Unable to get log files') + '(code = ' + log_data.code + ') : retrieveLog()'));
return null;
}
var log_list = log_data.stdout.trim().split('\n');
if (log_list.length <= 0) {
ui.addNotification(null, E('p', _('Unable to get log files') + '(not found) : retrieveLog()'));
return null;
}
var tasks = [ ];
var logdata = [ ];
for (let i = 0; i < log_list.length; i++) {
let logfn = log_list[i].trim();
if (logfn.startsWith('/tmp/')) {
//console.log('LOG: ' + logfn);
logdata.push( { filename: logfn, data: null, rows: 0 } );
tasks.push( fs.exec_direct(filereader, [ logfn ] ) );
}
}
return Promise.all(tasks).then(function(log_array) {
for (let i = 0; i < log_array.length; i++) {
if (log_array[i]) {
logdata[i].data = log_array[i];
logdata[i].rows = tools.getLineCount(log_array[i]) + 1;
}
}
return logdata;
}).catch(function(e) {
ui.addNotification(null, E('p', _('Unable to execute or read contents')
+ ': %s [ %s | %s | %s | %s ]'.format(
e.message, tools.execPath, 'retrieveLogData', 'uci.zapret'
)));
return null;
});
}).catch(function(e) {
ui.addNotification(null, E('p', _('Unable to execute or read contents')
+ ': %s [ %s | %s | %s | %s ]'.format(
e.message, tools.execPath, 'retrieveLog', 'uci.zapret'
)));
return null;
});
},
pollLog: async function() {
const elem0 = document.getElementById('dmnlog_0');
if (elem0) {
const logdata = await this.retrieveLog();
for (let log_num = 0; log_num < logdata.length; log_num++) {
let elem = document.getElementById('dmnlog_' + log_num);
if (elem) {
if (logdata[log_num].data) {
elem.value = logdata[log_num].data;
elem.rows = logdata[log_num].rows;
} else {
elem.value = '';
elem.rows = 0;
}
}
}
//console.log('POLL: updated ' + logdata.length);
}
},
load: async function() {
poll.add(this.pollLog.bind(this));
return await this.retrieveLog();
},
render: function(logdata) {
if (!logdata) {
return;
}
var h2 = E('div', {'class' : 'cbi-title-section'}, [
E('h2', {'class': 'cbi-title-field'}, [ _('Zapret') + ' - ' + _('Log Viewer') ]),
]);
var tabs = E('div', {}, E('div'));
for (let log_num = 0; log_num < logdata.length; log_num++) {
//console.log('REN: ' + logdata[log_num].filename + ' : ' + logdata[log_num].data.length);
var logfn = logdata[log_num].filename;
let filename = logfn.replace(/.*\//, '');
let fname = filename.split('.')[0];
fname = fname.replace(/^(zapret\+)/, '');
let fn = fname.split('+');
let tabNameText = fname.replace(/\+/g, ' ');
let tabname = 'tablog_' + log_num;
var scrollDownButton = null;
var scrollUpButton = null;
scrollDownButton = E('button', {
'id': 'scrollDownButton_' + log_num,
'class': 'cbi-button cbi-button-neutral'
}, _('Scroll to tail', 'scroll to bottom (the tail) of the log file')
);
scrollDownButton.addEventListener('click', function() {
scrollUpButton.focus();
});
scrollUpButton = E('button', {
'id' : 'scrollUpButton_' + log_num,
'class': 'cbi-button cbi-button-neutral'
}, _('Scroll to head', 'scroll to top (the head) of the log file')
);
scrollUpButton.addEventListener('click', function() {
scrollDownButton.focus();
});
let log_text = (logdata[log_num].data) ? logdata[log_num].data : '';
let tab = E('div', { 'data-tab': tabname, 'data-tab-title': tabNameText }, [
E('div', { 'id': 'content_dmnlog_' + log_num }, [
E('div', {'style': 'padding-bottom: 20px'}, [ scrollDownButton ]),
E('textarea', {
'id': 'dmnlog_' + log_num,
'style': 'font-size:12px',
'readonly': 'readonly',
'wrap': 'off',
'rows': logdata[log_num].rows,
}, [ log_text ]),
E('div', {'style': 'padding-bottom: 20px'}, [ scrollUpButton ]),
]),
]);
tabs.firstElementChild.appendChild(tab);
}
ui.tabs.initTabGroup(tabs.firstElementChild.childNodes);
//this.pollFn = L.bind(this.handleScanRefresh, this);
//poll.add(this.pollFn);
return E('div', { }, [ h2, tabs ]);
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});

View File

@@ -308,6 +308,17 @@ return baseclass.extend({
</table>`; </table>`;
return out; return out;
}, },
getLineCount: function(mstr) {
let count = 0;
let c = '\n'.charAt(0);
for (let i = 0; i < mstr.length; ++i) {
if (c === mstr.charAt(i)) {
++count;
}
}
return count;
},
fileEditDialog: baseclass.extend({ fileEditDialog: baseclass.extend({
__init__: function(file, title, desc, aux = null, rows = 10, callback, file_exists = false) { __init__: function(file, title, desc, aux = null, rows = 10, callback, file_exists = false) {

View File

@@ -33,5 +33,14 @@
"type": "view", "type": "view",
"path": "zapret/settings" "path": "zapret/settings"
} }
},
"admin/services/zapret/dmnlog": {
"title": "Log Viewer",
"order": 30,
"action": {
"type": "view",
"path": "zapret/dmnlog"
}
} }
} }

View File

@@ -7,11 +7,14 @@
"/opt/zapret/config": [ "read" ], "/opt/zapret/config": [ "read" ],
"/opt/zapret/ipset/*": [ "read" ], "/opt/zapret/ipset/*": [ "read" ],
"/etc/crontabs/root": [ "read" ], "/etc/crontabs/root": [ "read" ],
"/tmp/zapret*": [ "read" ],
"/etc/init.d/zapret*": [ "exec" ], "/etc/init.d/zapret*": [ "exec" ],
"/bin/ps*": [ "exec" ], "/bin/ps*": [ "exec" ],
"/bin/cat*": [ "exec" ],
"/bin/busybox*": [ "exec" ], "/bin/busybox*": [ "exec" ],
"/bin/opkg*": [ "exec" ], "/bin/opkg*": [ "exec" ],
"/usr/bin/apk*": [ "exec" ], "/usr/bin/apk*": [ "exec" ],
"/usr/bin/find*": [ "exec" ],
"/opt/zapret/restore-def-cfg.sh*": [ "exec" ], "/opt/zapret/restore-def-cfg.sh*": [ "exec" ],
"/opt/zapret/sync_config.sh*": [ "exec" ] "/opt/zapret/sync_config.sh*": [ "exec" ]
}, },