mirror of
https://github.com/gSpotx2f/ruantiblock_openwrt.git
synced 2026-05-13 14:10:59 +00:00
luci-app: Code fixes, updated log
This commit is contained in:
@@ -11,7 +11,7 @@ LUCI_APP=1
|
|||||||
OWRT_VERSION="19.07"
|
OWRT_VERSION="19.07"
|
||||||
RUAB_VERSION="0.9.0-2"
|
RUAB_VERSION="0.9.0-2"
|
||||||
RUAB_MOD_LUA_VERSION="0.9.0-2"
|
RUAB_MOD_LUA_VERSION="0.9.0-2"
|
||||||
RUAB_LUCI_APP_VERSION="0.9.0-4"
|
RUAB_LUCI_APP_VERSION="0.9.0-5"
|
||||||
BASE_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_openwrt/master"
|
BASE_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_openwrt/master"
|
||||||
PKG_DIR="/tmp"
|
PKG_DIR="/tmp"
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_VERSION:=0.9.0
|
PKG_VERSION:=0.9.0
|
||||||
PKG_RELEASE:=4
|
PKG_RELEASE:=5
|
||||||
LUCI_TITLE:=LuCI support for ruantiblock
|
LUCI_TITLE:=LuCI support for ruantiblock
|
||||||
LUCI_DEPENDS:=+ruantiblock +luci-mod-admin-full
|
LUCI_DEPENDS:=+ruantiblock +luci-mod-admin-full
|
||||||
LUCI_PKGARCH:=all
|
LUCI_PKGARCH:=all
|
||||||
|
|||||||
+271
-225
@@ -1,217 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
'require ui';
|
'require ui';
|
||||||
|
|
||||||
return L.Class.extend({
|
document.head.append(E('style', {'type': 'text/css'},
|
||||||
view: L.view.extend({
|
|
||||||
viewName: null,
|
|
||||||
|
|
||||||
title: null,
|
|
||||||
|
|
||||||
logFacilities: [
|
|
||||||
'kern',
|
|
||||||
'user',
|
|
||||||
'mail',
|
|
||||||
'daemon',
|
|
||||||
'auth',
|
|
||||||
'syslog',
|
|
||||||
'lpr',
|
|
||||||
'news',
|
|
||||||
],
|
|
||||||
|
|
||||||
logLevels: {
|
|
||||||
'emerg': E('span', { 'class': 'zonebadge log-emerg' }, E('strong', _('Emergency'))),
|
|
||||||
'alert': E('span', { 'class': 'zonebadge log-alert' }, E('strong', _('Alert'))),
|
|
||||||
'crit': E('span', { 'class': 'zonebadge log-crit' }, E('strong', _('Critical'))),
|
|
||||||
'err': E('span', { 'class': 'zonebadge log-err' }, E('strong', _('Error'))),
|
|
||||||
'warn': E('span', { 'class': 'zonebadge log-warn' }, E('strong', _('Warning'))),
|
|
||||||
'notice': E('span', { 'class': 'zonebadge log-notice' }, E('strong', _('Notice'))),
|
|
||||||
'info': E('span', { 'class': 'zonebadge log-info' }, E('strong', _('Info'))),
|
|
||||||
'debug': E('span', { 'class': 'zonebadge log-debug' }, E('strong', _('Debug'))),
|
|
||||||
},
|
|
||||||
|
|
||||||
tailValue: 25,
|
|
||||||
|
|
||||||
logSortingValue: 'asc',
|
|
||||||
|
|
||||||
logLevelsStat: {},
|
|
||||||
|
|
||||||
logLevelsDropdown: null,
|
|
||||||
|
|
||||||
totalLogLines: 0,
|
|
||||||
|
|
||||||
htmlEntities: function(str) {
|
|
||||||
return String(str).replace(
|
|
||||||
/&/g, '&').replace(
|
|
||||||
/</g, '<').replace(
|
|
||||||
/>/g, '>').replace(
|
|
||||||
/"/g, '"').replace(
|
|
||||||
/'/g, ''');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {number} tail
|
|
||||||
* @returns {string}
|
|
||||||
* Returns the raw content of the log
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
getLogData: function(tail) {
|
|
||||||
throw new Error('getLogData needs to be reloaded in subclass');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {string} logdata
|
|
||||||
* @param {number} tail
|
|
||||||
* @returns {Array<number, string|null, string|null, string|null, string|null>}
|
|
||||||
* Returns an array of values: [ #, Timestamp, Level, Facility, Message ]
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
parseLogData: function(logdata, tail) {
|
|
||||||
throw new Error('parseLogData needs to be reloaded in subclass');
|
|
||||||
},
|
|
||||||
|
|
||||||
setLevelFilter: function(cArr) {
|
|
||||||
let logLevelsKeys = Object.keys(this.logLevels);
|
|
||||||
if(logLevelsKeys.length > 0) {
|
|
||||||
let selectedLevels = this.logLevelsDropdown.getValue();
|
|
||||||
if(logLevelsKeys.length === selectedLevels.length) {
|
|
||||||
return cArr;
|
|
||||||
};
|
|
||||||
return cArr.filter(s => selectedLevels.length === 0 || selectedLevels.includes(s[2]));
|
|
||||||
};
|
|
||||||
return cArr;
|
|
||||||
},
|
|
||||||
|
|
||||||
setRegexpFilter: function(cArr) {
|
|
||||||
let fPattern = document.getElementById('logFilter').value;
|
|
||||||
if(!fPattern) {
|
|
||||||
return cArr;
|
|
||||||
};
|
|
||||||
let fArr = [];
|
|
||||||
try {
|
|
||||||
let regExp = new RegExp(`(${fPattern})`, 'giu');
|
|
||||||
cArr.forEach((e, i) => {
|
|
||||||
if(e[4] !== null && regExp.test(e[4])) {
|
|
||||||
e[4] = e[4].replace(regExp, '<span class="log-highlight-item">$1</span>');
|
|
||||||
fArr.push(e);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
} catch(err) {
|
|
||||||
if(err.name === 'SyntaxError') {
|
|
||||||
ui.addNotification(null,
|
|
||||||
E('p', {}, _('Invalid regular expression') + ': ' + err.message));
|
|
||||||
return cArr;
|
|
||||||
} else {
|
|
||||||
throw err;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
return fArr;
|
|
||||||
},
|
|
||||||
|
|
||||||
makeLogArea: function(logdataArray) {
|
|
||||||
let lines = `<div class="tr"><div class="td center log-entry-empty">${_('No entries available...')}</div></div>`;
|
|
||||||
let logTable = E('div', { 'id': 'logTable', 'class': 'table' });
|
|
||||||
|
|
||||||
for(let level of Object.keys(this.logLevels)) {
|
|
||||||
this.logLevelsStat[level] = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
if(logdataArray.length > 0) {
|
|
||||||
lines = [];
|
|
||||||
logdataArray.forEach((e, i) => {
|
|
||||||
if(e[2] in this.logLevels) {
|
|
||||||
this.logLevelsStat[e[2]] = this.logLevelsStat[e[2]] + 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
lines.push(
|
|
||||||
`<div class="tr log-${e[2] || 'empty'}"><div class="td left" data-title="#">${e[0]}</div>` +
|
|
||||||
((e[1]) ? `<div class="td left" data-title="${_('Timestamp')}">${e[1]}</div>` : '') +
|
|
||||||
((e[2]) ? `<div class="td left" data-title="${_('Level')}">${e[2]}</div>` : '') +
|
|
||||||
((e[3]) ? `<div class="td left" data-title="${_('Facility')}">${e[3]}</div>` : '') +
|
|
||||||
((e[4]) ? `<div class="td left log-entry-message-cell" data-title="${_('Message')}">${e[4]}</div>` : '') +
|
|
||||||
`</div>`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
lines = lines.join('');
|
|
||||||
|
|
||||||
logTable.append(
|
|
||||||
E('div', { 'class': 'tr table-titles' }, [
|
|
||||||
E('div', { 'class': 'th left log-entry-number' }, '#'),
|
|
||||||
(logdataArray[0][1]) ? E('div', { 'class': 'th left log-entry-time' }, _('Timestamp')) : '',
|
|
||||||
(logdataArray[0][2]) ? E('div', { 'class': 'th left log-entry-log-level' }, _('Level')) : '',
|
|
||||||
(logdataArray[0][3]) ? E('div', { 'class': 'th left log-entry-facility' }, _('Facility')) : '',
|
|
||||||
(logdataArray[0][4]) ? E('div', { 'class': 'th left log-entry-message' }, _('Message')) : '',
|
|
||||||
])
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
logTable.insertAdjacentHTML('beforeend', lines);
|
|
||||||
} catch(err) {
|
|
||||||
if(err.name === 'SyntaxError') {
|
|
||||||
ui.addNotification(null,
|
|
||||||
E('p', {}, _('HTML/XML error') + ': ' + err.message), 'error');
|
|
||||||
};
|
|
||||||
throw err;
|
|
||||||
};
|
|
||||||
|
|
||||||
let levelsStatString = '';
|
|
||||||
if((Object.values(this.logLevelsStat).reduce((s,c) => s + c, 0)) > 0) {
|
|
||||||
Object.entries(this.logLevelsStat).forEach(e => {
|
|
||||||
if(e[0] in this.logLevels && e[1] > 0) {
|
|
||||||
levelsStatString += `<span class="log-entries-count-level log-${e[0]}" title="${e[0]}">${e[1]}</span>`;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return E([
|
|
||||||
E('div', { 'class': 'log-entries-count' },
|
|
||||||
`${_('Entries')}: ${logdataArray.length} / ${this.totalLogLines}${levelsStatString}`
|
|
||||||
),
|
|
||||||
logTable
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
|
|
||||||
downloadLog: function(ev) {
|
|
||||||
let formElems = Array.from(document.forms.logForm.elements);
|
|
||||||
formElems.forEach(e => e.disabled = true);
|
|
||||||
|
|
||||||
return this.getLogData(0).then(logdata => {
|
|
||||||
logdata = logdata || '';
|
|
||||||
let link = E('a', {
|
|
||||||
'download': this.viewName + '.log',
|
|
||||||
'href': URL.createObjectURL(
|
|
||||||
new Blob([ logdata ], { type: 'text/plain' })),
|
|
||||||
});
|
|
||||||
link.click();
|
|
||||||
URL.revokeObjectURL(link.href);
|
|
||||||
}).catch(() => {
|
|
||||||
ui.addNotification(null,
|
|
||||||
E('p', {}, _('Download error') + ': ' + err.message));
|
|
||||||
}).finally(() => {
|
|
||||||
formElems.forEach(e => e.disabled = false);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
load: function() {
|
|
||||||
|
|
||||||
// Restoring settings from localStorage
|
|
||||||
let tailValueLocal = localStorage.getItem(`luci-app-${this.viewName}-tailValue`);
|
|
||||||
if(tailValueLocal) {
|
|
||||||
this.tailValue = Number(tailValueLocal);
|
|
||||||
};
|
|
||||||
let logSortingLocal = localStorage.getItem(`luci-app-${this.viewName}-logSorting`);
|
|
||||||
if(logSortingLocal) {
|
|
||||||
this.logSortingValue = logSortingLocal;
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.getLogData(this.tailValue);
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function(logdata) {
|
|
||||||
|
|
||||||
document.head.append(E('style', {'type': 'text/css'},
|
|
||||||
`
|
`
|
||||||
.log-entry-empty {
|
.log-entry-empty {
|
||||||
}
|
}
|
||||||
@@ -221,6 +11,13 @@ return L.Class.extend({
|
|||||||
.log-entry-time {
|
.log-entry-time {
|
||||||
min-width: 14em !important;
|
min-width: 14em !important;
|
||||||
}
|
}
|
||||||
|
.log-entry-host {
|
||||||
|
min-width: 10em !important;
|
||||||
|
}
|
||||||
|
.log-entry-host-cell {
|
||||||
|
word-break: break-all !important;
|
||||||
|
word-wrap: break-word !important;
|
||||||
|
}
|
||||||
.log-entry-log-level {
|
.log-entry-log-level {
|
||||||
max-width: 5em !important;
|
max-width: 5em !important;
|
||||||
}
|
}
|
||||||
@@ -291,9 +88,234 @@ log-emerg td {
|
|||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
`
|
.log-host-dropdown-item {
|
||||||
));
|
}
|
||||||
|
`));
|
||||||
|
|
||||||
|
return L.Class.extend({
|
||||||
|
view: L.view.extend({
|
||||||
|
viewName: null,
|
||||||
|
|
||||||
|
title: null,
|
||||||
|
|
||||||
|
logLevels: {
|
||||||
|
'emerg': E('span', { 'class': 'zonebadge log-emerg' }, E('strong', _('Emergency'))),
|
||||||
|
'alert': E('span', { 'class': 'zonebadge log-alert' }, E('strong', _('Alert'))),
|
||||||
|
'crit': E('span', { 'class': 'zonebadge log-crit' }, E('strong', _('Critical'))),
|
||||||
|
'err': E('span', { 'class': 'zonebadge log-err' }, E('strong', _('Error'))),
|
||||||
|
'warn': E('span', { 'class': 'zonebadge log-warn' }, E('strong', _('Warning'))),
|
||||||
|
'notice': E('span', { 'class': 'zonebadge log-notice' }, E('strong', _('Notice'))),
|
||||||
|
'info': E('span', { 'class': 'zonebadge log-info' }, E('strong', _('Info'))),
|
||||||
|
'debug': E('span', { 'class': 'zonebadge log-debug' }, E('strong', _('Debug'))),
|
||||||
|
},
|
||||||
|
|
||||||
|
tailValue: 25,
|
||||||
|
|
||||||
|
logSortingValue: 'asc',
|
||||||
|
|
||||||
|
logLevelsStat: {},
|
||||||
|
|
||||||
|
logHosts: {},
|
||||||
|
|
||||||
|
logHostsDropdown: null,
|
||||||
|
|
||||||
|
logLevelsDropdown: null,
|
||||||
|
|
||||||
|
totalLogLines: 0,
|
||||||
|
|
||||||
|
htmlEntities: function(str) {
|
||||||
|
return String(str).replace(
|
||||||
|
/&/g, '&').replace(
|
||||||
|
/</g, '<').replace(
|
||||||
|
/>/g, '>').replace(
|
||||||
|
/"/g, '"').replace(
|
||||||
|
/'/g, ''');
|
||||||
|
},
|
||||||
|
|
||||||
|
makelogHostsDropdownItem: function(host) {
|
||||||
|
return E(
|
||||||
|
'span',
|
||||||
|
{ 'class': 'zonebadge log-host-dropdown-item' },
|
||||||
|
E('strong', host)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {number} tail
|
||||||
|
* @returns {string}
|
||||||
|
* Returns the raw content of the log
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
getLogData: function(tail) {
|
||||||
|
throw new Error('getLogData must be overridden by a subclass');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} logdata
|
||||||
|
* @param {number} tail
|
||||||
|
* @returns {Array<number, string|null, string|null, string|null, string|null, string|null>}
|
||||||
|
* Returns an array of values: [ #, Timestamp, Host, Level, Facility, Message ]
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
parseLogData: function(logdata, tail) {
|
||||||
|
throw new Error('parseLogData must be overridden by a subclass');
|
||||||
|
},
|
||||||
|
|
||||||
|
setHostFilter: function(cArr) {
|
||||||
|
let logHostsKeys = Object.keys(this.logHosts);
|
||||||
|
if(logHostsKeys.length > 0) {
|
||||||
|
let selectedHosts = this.logHostsDropdown.getValue();
|
||||||
|
this.logHostsDropdown.addChoices(Object.keys(this.logHosts), this.logHosts);
|
||||||
|
if(selectedHosts.length === 0 || logHostsKeys.length === selectedHosts.length) {
|
||||||
|
return cArr;
|
||||||
|
};
|
||||||
|
return cArr.filter(e => selectedHosts.includes(e[2]));
|
||||||
|
};
|
||||||
|
return cArr;
|
||||||
|
},
|
||||||
|
|
||||||
|
setLevelFilter: function(cArr) {
|
||||||
|
let logLevelsKeys = Object.keys(this.logLevels);
|
||||||
|
if(logLevelsKeys.length > 0) {
|
||||||
|
let selectedLevels = this.logLevelsDropdown.getValue();
|
||||||
|
if(selectedLevels.length === 0 || logLevelsKeys.length === selectedLevels.length) {
|
||||||
|
return cArr;
|
||||||
|
};
|
||||||
|
return cArr.filter(e => selectedLevels.includes(e[3]));
|
||||||
|
};
|
||||||
|
return cArr;
|
||||||
|
},
|
||||||
|
|
||||||
|
setRegexpFilter: function(cArr) {
|
||||||
|
let fPattern = document.getElementById('logFilter').value;
|
||||||
|
if(!fPattern) {
|
||||||
|
return cArr;
|
||||||
|
};
|
||||||
|
let fArr = [];
|
||||||
|
try {
|
||||||
|
let regExp = new RegExp(`(${fPattern})`, 'giu');
|
||||||
|
cArr.forEach((e, i) => {
|
||||||
|
if(e[5] !== null && regExp.test(e[5])) {
|
||||||
|
e[5] = e[5].replace(regExp, '<span class="log-highlight-item">$1</span>');
|
||||||
|
fArr.push(e);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} catch(err) {
|
||||||
|
if(err.name === 'SyntaxError') {
|
||||||
|
ui.addNotification(null,
|
||||||
|
E('p', {}, _('Invalid regular expression') + ': ' + err.message));
|
||||||
|
return cArr;
|
||||||
|
} else {
|
||||||
|
throw err;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
return fArr;
|
||||||
|
},
|
||||||
|
|
||||||
|
makeLogArea: function(logdataArray) {
|
||||||
|
let lines = `<div class="tr"><div class="td center log-entry-empty">${_('No entries available...')}</div></div>`;
|
||||||
|
let logTable = E('div', { 'id': 'logTable', 'class': 'table' });
|
||||||
|
|
||||||
|
for(let level of Object.keys(this.logLevels)) {
|
||||||
|
this.logLevelsStat[level] = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
if(logdataArray.length > 0) {
|
||||||
|
lines = [];
|
||||||
|
logdataArray.forEach((e, i) => {
|
||||||
|
if(e[3] in this.logLevels) {
|
||||||
|
this.logLevelsStat[e[3]] = this.logLevelsStat[e[3]] + 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
lines.push(
|
||||||
|
`<div class="tr log-${e[3] || 'empty'}"><div class="td left" data-title="#">${e[0]}</div>` +
|
||||||
|
((e[1]) ? `<div class="td left" data-title="${_('Timestamp')}">${e[1]}</div>` : '') +
|
||||||
|
((e[2]) ? `<div class="td left log-entry-host-cell" data-title="${_('Host')}">${e[2]}</div>` : '') +
|
||||||
|
((e[3]) ? `<div class="td left" data-title="${_('Level')}">${e[3]}</div>` : '') +
|
||||||
|
((e[4]) ? `<div class="td left" data-title="${_('Facility')}">${e[4]}</div>` : '') +
|
||||||
|
((e[5]) ? `<div class="td left log-entry-message-cell" data-title="${_('Message')}">${e[5]}</div>` : '') +
|
||||||
|
`</div>`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
lines = lines.join('');
|
||||||
|
|
||||||
|
logTable.append(
|
||||||
|
E('div', { 'class': 'tr table-titles' }, [
|
||||||
|
E('div', { 'class': 'th left log-entry-number' }, '#'),
|
||||||
|
(logdataArray[0][1]) ? E('div', { 'class': 'th left log-entry-time' }, _('Timestamp')) : '',
|
||||||
|
(logdataArray[0][2]) ? E('div', { 'class': 'th left log-entry-host' }, _('Host')) : '',
|
||||||
|
(logdataArray[0][3]) ? E('div', { 'class': 'th left log-entry-log-level' }, _('Level')) : '',
|
||||||
|
(logdataArray[0][4]) ? E('div', { 'class': 'th left log-entry-facility' }, _('Facility')) : '',
|
||||||
|
(logdataArray[0][5]) ? E('div', { 'class': 'th left log-entry-message' }, _('Message')) : '',
|
||||||
|
])
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
logTable.insertAdjacentHTML('beforeend', lines);
|
||||||
|
} catch(err) {
|
||||||
|
if(err.name === 'SyntaxError') {
|
||||||
|
ui.addNotification(null,
|
||||||
|
E('p', {}, _('HTML/XML error') + ': ' + err.message), 'error');
|
||||||
|
};
|
||||||
|
throw err;
|
||||||
|
};
|
||||||
|
|
||||||
|
let levelsStatString = '';
|
||||||
|
if((Object.values(this.logLevelsStat).reduce((s,c) => s + c, 0)) > 0) {
|
||||||
|
Object.entries(this.logLevelsStat).forEach(e => {
|
||||||
|
if(e[0] in this.logLevels && e[1] > 0) {
|
||||||
|
levelsStatString += `<span class="log-entries-count-level log-${e[0]}" title="${e[0]}">${e[1]}</span>`;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return E([
|
||||||
|
E('div', { 'class': 'log-entries-count' },
|
||||||
|
`${_('Entries')}: ${logdataArray.length} / ${this.totalLogLines}${levelsStatString}`
|
||||||
|
),
|
||||||
|
logTable
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
|
downloadLog: function(ev) {
|
||||||
|
let formElems = Array.from(document.forms.logForm.elements);
|
||||||
|
formElems.forEach(e => e.disabled = true);
|
||||||
|
|
||||||
|
return this.getLogData(0).then(logdata => {
|
||||||
|
logdata = logdata || '';
|
||||||
|
let link = E('a', {
|
||||||
|
'download': this.viewName + '.log',
|
||||||
|
'href': URL.createObjectURL(
|
||||||
|
new Blob([ logdata ], { type: 'text/plain' })),
|
||||||
|
});
|
||||||
|
link.click();
|
||||||
|
URL.revokeObjectURL(link.href);
|
||||||
|
}).catch(() => {
|
||||||
|
ui.addNotification(null,
|
||||||
|
E('p', {}, _('Download error') + ': ' + err.message));
|
||||||
|
}).finally(() => {
|
||||||
|
formElems.forEach(e => e.disabled = false);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
load: function() {
|
||||||
|
// Restoring settings from localStorage
|
||||||
|
let tailValueLocal = localStorage.getItem(`luci-app-${this.viewName}-tailValue`);
|
||||||
|
if(tailValueLocal) {
|
||||||
|
this.tailValue = Number(tailValueLocal);
|
||||||
|
};
|
||||||
|
let logSortingLocal = localStorage.getItem(`luci-app-${this.viewName}-logSorting`);
|
||||||
|
if(logSortingLocal) {
|
||||||
|
this.logSortingValue = logSortingLocal;
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.getLogData(this.tailValue);
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function(logdata) {
|
||||||
let logWrapper = E('div', {
|
let logWrapper = E('div', {
|
||||||
'id': 'logWrapper',
|
'id': 'logWrapper',
|
||||||
'style': 'width:100%; min-height:20em; padding: 0 0 0 45px; font-size:0.9em !important'
|
'style': 'width:100%; min-height:20em; padding: 0 0 0 45px; font-size:0.9em !important'
|
||||||
@@ -324,6 +346,31 @@ log-emerg td {
|
|||||||
'style': 'max-width:4em !important',
|
'style': 'max-width:4em !important',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let logHostsDropdownElem = '';
|
||||||
|
let logHostsKeys = Object.keys(this.logHosts);
|
||||||
|
if(logHostsKeys.length > 0) {
|
||||||
|
this.logHostsDropdown = new ui.Dropdown(
|
||||||
|
null,
|
||||||
|
this.logHosts,
|
||||||
|
{
|
||||||
|
id: 'logHostsDropdown',
|
||||||
|
multiple: true,
|
||||||
|
select_placeholder: _('All'),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
logHostsDropdownElem = E(
|
||||||
|
'div', { 'class': 'cbi-value' }, [
|
||||||
|
E('label', {
|
||||||
|
'class': 'cbi-value-title',
|
||||||
|
'for': 'logHostsDropdown',
|
||||||
|
}, _('Hosts')),
|
||||||
|
E('div', { 'class': 'cbi-value-field' },
|
||||||
|
this.logHostsDropdown.render()
|
||||||
|
),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
let logLevelsDropdownElem = '';
|
let logLevelsDropdownElem = '';
|
||||||
let logLevelsKeys = Object.keys(this.logLevels);
|
let logLevelsKeys = Object.keys(this.logLevels);
|
||||||
if(logLevelsKeys.length > 0) {
|
if(logLevelsKeys.length > 0) {
|
||||||
@@ -335,8 +382,6 @@ log-emerg td {
|
|||||||
sort: logLevelsKeys,
|
sort: logLevelsKeys,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
select_placeholder: _('All'),
|
select_placeholder: _('All'),
|
||||||
display_items: 3,
|
|
||||||
dropdown_items: -1,
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
logLevelsDropdownElem = E(
|
logLevelsDropdownElem = E(
|
||||||
@@ -405,6 +450,7 @@ log-emerg td {
|
|||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
logHostsDropdownElem,
|
||||||
logLevelsDropdownElem,
|
logLevelsDropdownElem,
|
||||||
|
|
||||||
E('div', { 'class': 'cbi-value' }, [
|
E('div', { 'class': 'cbi-value' }, [
|
||||||
@@ -427,7 +473,7 @@ log-emerg td {
|
|||||||
E('label', {
|
E('label', {
|
||||||
'class': 'cbi-value-title',
|
'class': 'cbi-value-title',
|
||||||
'for': 'logFilter',
|
'for': 'logFilter',
|
||||||
}),
|
}, _('Refresh log')),
|
||||||
E('div', { 'class': 'cbi-value-field' }, [
|
E('div', { 'class': 'cbi-value-field' }, [
|
||||||
logFormSubmitBtn,
|
logFormSubmitBtn,
|
||||||
E('form', {
|
E('form', {
|
||||||
@@ -455,18 +501,18 @@ log-emerg td {
|
|||||||
let tail = (tailInput.value && tailInput.value > 0) ? tailInput.value : 0
|
let tail = (tailInput.value && tailInput.value > 0) ? tailInput.value : 0
|
||||||
return this.getLogData(tail).then(logdata => {
|
return this.getLogData(tail).then(logdata => {
|
||||||
logdata = logdata || '';
|
logdata = logdata || '';
|
||||||
|
logWrapper.innerHTML = '';
|
||||||
let loglines = this.makeLogArea(
|
logWrapper.append(
|
||||||
this.setRegexpFilter(
|
this.makeLogArea(
|
||||||
this.setLevelFilter(
|
this.setRegexpFilter(
|
||||||
this.parseLogData(logdata, tail)
|
this.setLevelFilter(
|
||||||
|
this.setHostFilter(
|
||||||
|
this.parseLogData(logdata, tail)
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
logWrapper.innerHTML = '';
|
|
||||||
logWrapper.append(loglines);
|
|
||||||
|
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
formElems.forEach(e => e.disabled = false);
|
formElems.forEach(e => e.disabled = false);
|
||||||
logDownloadBtn.disabled = false;
|
logDownloadBtn.disabled = false;
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
'require fs';
|
'require fs';
|
||||||
'require ui';
|
'require ui';
|
||||||
'require view.log.baselog as baselog';
|
'require view.log.abstract-log as abc';
|
||||||
'require view.ruantiblock.tools as tools';
|
'require view.ruantiblock.tools as tools';
|
||||||
|
|
||||||
return baselog.view.extend({
|
return abc.view.extend({
|
||||||
viewName: 'ruantiblock',
|
viewName: 'ruantiblock',
|
||||||
|
|
||||||
title: _('Ruantiblock') + ' - ' + _('Log'),
|
title: _('Ruantiblock') + ' - ' + _('Log'),
|
||||||
@@ -22,6 +22,7 @@ return baselog.view.extend({
|
|||||||
return [
|
return [
|
||||||
lineNum, // # (Number)
|
lineNum, // # (Number)
|
||||||
strArray.slice(0, 5).join(' '), // Timestamp (String)
|
strArray.slice(0, 5).join(' '), // Timestamp (String)
|
||||||
|
null, // Host (String)
|
||||||
logLevel[1], // Level (String)
|
logLevel[1], // Level (String)
|
||||||
logLevel[0], // Facility (String)
|
logLevel[0], // Facility (String)
|
||||||
this.htmlEntities(strArray.slice(6).join(' ')), // Message (String)
|
this.htmlEntities(strArray.slice(6).join(' ')), // Message (String)
|
||||||
@@ -30,9 +31,14 @@ return baselog.view.extend({
|
|||||||
|
|
||||||
// syslog-ng
|
// syslog-ng
|
||||||
syslog_ngHandler: function(strArray, lineNum) {
|
syslog_ngHandler: function(strArray, lineNum) {
|
||||||
|
if(!(strArray[3] in this.logHosts)) {
|
||||||
|
this.logHosts[strArray[3]] = this.makelogHostsDropdownItem(strArray[3]);
|
||||||
|
};
|
||||||
|
|
||||||
return [
|
return [
|
||||||
lineNum, // # (Number)
|
lineNum, // # (Number)
|
||||||
strArray.slice(0, 3).join(' '), // Timestamp (String)
|
strArray.slice(0, 3).join(' '), // Timestamp (String)
|
||||||
|
strArray[3], // Host (String)
|
||||||
null, // Level (String)
|
null, // Level (String)
|
||||||
null, // Facility (String)
|
null, // Facility (String)
|
||||||
this.htmlEntities(strArray.slice(4).join(' ')), // Message (String)
|
this.htmlEntities(strArray.slice(4).join(' ')), // Message (String)
|
||||||
@@ -48,7 +54,7 @@ return baselog.view.extend({
|
|||||||
|
|
||||||
if(logger) {
|
if(logger) {
|
||||||
return fs.exec_direct(logger, [ '-e', tools.app_name ]).catch(err => {
|
return fs.exec_direct(logger, [ '-e', tools.app_name ]).catch(err => {
|
||||||
ui.addNotification(null, E('p', {}, _('Unable to load log data: ' + err.message)));
|
ui.addNotification(null, E('p', {}, _('Unable to load log data:') + ' ' + err.message));
|
||||||
return '';
|
return '';
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -250,8 +250,6 @@ return L.view.extend({
|
|||||||
let proxy_local_clients = (typeof(section) === 'object') ? section.proxy_local_clients : null;
|
let proxy_local_clients = (typeof(section) === 'object') ? section.proxy_local_clients : null;
|
||||||
status_token_value = (Array.isArray(status_array)) ? tools.normalize_value(status_array[4]) : null;
|
status_token_value = (Array.isArray(status_array)) ? tools.normalize_value(status_array[4]) : null;
|
||||||
|
|
||||||
document.head.append(E('style', {'type': 'text/css'}, tools.css));
|
|
||||||
|
|
||||||
let status_string = E('div', {
|
let status_string = E('div', {
|
||||||
'id': 'status',
|
'id': 'status',
|
||||||
'name': 'status',
|
'name': 'status',
|
||||||
|
|||||||
@@ -2,30 +2,8 @@
|
|||||||
'require fs';
|
'require fs';
|
||||||
'require ui';
|
'require ui';
|
||||||
|
|
||||||
return L.Class.extend({
|
document.head.append(E('style', {'type': 'text/css'},
|
||||||
app_name: 'ruantiblock',
|
`
|
||||||
exec_path: '/usr/bin/ruantiblock',
|
|
||||||
init_path: '/etc/init.d/ruantiblock',
|
|
||||||
token_file: '/var/run/ruantiblock.token',
|
|
||||||
parsers_dir: '/usr/bin',
|
|
||||||
torrc_file: '/etc/tor/torrc',
|
|
||||||
user_entries_file: '/etc/ruantiblock/user_entries',
|
|
||||||
fqdn_filter_file: '/etc/ruantiblock/fqdn_filter',
|
|
||||||
ip_filter_file: '/etc/ruantiblock/ip_filter',
|
|
||||||
crontab_file: '/etc/crontabs/root',
|
|
||||||
info_label_starting: '<span class="label-status starting">' + _('Starting') + '</span>',
|
|
||||||
info_label_running: '<span class="label-status running">' + _('Enabled') + '</span>',
|
|
||||||
info_label_updating: '<span class="label-status updating">' + _('Updating') + '</span>',
|
|
||||||
info_label_stopped: '<span class="label-status stopped">' + _('Disabled') + '</span>',
|
|
||||||
info_label_error: '<span class="label-status error">' + _('Error') + '</span>',
|
|
||||||
|
|
||||||
blacklist_sources: {
|
|
||||||
'rublacklist': 'https://rublacklist.net',
|
|
||||||
'zapret-info': 'https://github.com/zapret-info/z-i',
|
|
||||||
'antifilter': 'https://antifilter.download',
|
|
||||||
},
|
|
||||||
|
|
||||||
css: `
|
|
||||||
.label-status {
|
.label-status {
|
||||||
display: inline;
|
display: inline;
|
||||||
margin: 0px 2px 0px 0 !important;
|
margin: 0px 2px 0px 0 !important;
|
||||||
@@ -53,7 +31,31 @@ return L.Class.extend({
|
|||||||
}
|
}
|
||||||
.total-proxy {
|
.total-proxy {
|
||||||
background-color: #ffb937 !important;
|
background-color: #ffb937 !important;
|
||||||
}`,
|
}
|
||||||
|
`));
|
||||||
|
|
||||||
|
return L.Class.extend({
|
||||||
|
app_name: 'ruantiblock',
|
||||||
|
exec_path: '/usr/bin/ruantiblock',
|
||||||
|
init_path: '/etc/init.d/ruantiblock',
|
||||||
|
token_file: '/var/run/ruantiblock.token',
|
||||||
|
parsers_dir: '/usr/bin',
|
||||||
|
torrc_file: '/etc/tor/torrc',
|
||||||
|
user_entries_file: '/etc/ruantiblock/user_entries',
|
||||||
|
fqdn_filter_file: '/etc/ruantiblock/fqdn_filter',
|
||||||
|
ip_filter_file: '/etc/ruantiblock/ip_filter',
|
||||||
|
crontab_file: '/etc/crontabs/root',
|
||||||
|
info_label_starting: '<span class="label-status starting">' + _('Starting') + '</span>',
|
||||||
|
info_label_running: '<span class="label-status running">' + _('Enabled') + '</span>',
|
||||||
|
info_label_updating: '<span class="label-status updating">' + _('Updating') + '</span>',
|
||||||
|
info_label_stopped: '<span class="label-status stopped">' + _('Disabled') + '</span>',
|
||||||
|
info_label_error: '<span class="label-status error">' + _('Error') + '</span>',
|
||||||
|
|
||||||
|
blacklist_sources: {
|
||||||
|
'rublacklist': 'https://rublacklist.net',
|
||||||
|
'zapret-info': 'https://github.com/zapret-info/z-i',
|
||||||
|
'antifilter': 'https://antifilter.download',
|
||||||
|
},
|
||||||
|
|
||||||
normalize_value: function(v) {
|
normalize_value: function(v) {
|
||||||
return (v && typeof(v) === 'string') ? v.trim().replace(/\r?\n/g, '') : v;
|
return (v && typeof(v) === 'string') ? v.trim().replace(/\r?\n/g, '') : v;
|
||||||
|
|||||||
@@ -386,6 +386,12 @@ msgstr "Записи"
|
|||||||
msgid "Facility"
|
msgid "Facility"
|
||||||
msgstr "Категория"
|
msgstr "Категория"
|
||||||
|
|
||||||
|
msgid "Host"
|
||||||
|
msgstr "Хост"
|
||||||
|
|
||||||
|
msgid "Hosts"
|
||||||
|
msgstr "Хосты"
|
||||||
|
|
||||||
msgid "Info"
|
msgid "Info"
|
||||||
msgstr "Информация"
|
msgstr "Информация"
|
||||||
|
|
||||||
@@ -413,6 +419,9 @@ msgstr "Нет доступных записей..."
|
|||||||
msgid "Notice"
|
msgid "Notice"
|
||||||
msgstr "Сообщение"
|
msgstr "Сообщение"
|
||||||
|
|
||||||
|
msgid "Refresh log"
|
||||||
|
msgstr "Обновить лог"
|
||||||
|
|
||||||
msgid "Sorting entries"
|
msgid "Sorting entries"
|
||||||
msgstr "Сортировка записей"
|
msgstr "Сортировка записей"
|
||||||
|
|
||||||
|
|||||||
@@ -113,6 +113,9 @@ msgstr ""
|
|||||||
msgid "Hour"
|
msgid "Hour"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Hour"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Interval"
|
msgid "Interval"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -356,6 +359,12 @@ msgstr ""
|
|||||||
msgid "Facility"
|
msgid "Facility"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Host"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Hosts"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Info"
|
msgid "Info"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -383,6 +392,9 @@ msgstr ""
|
|||||||
msgid "Notice"
|
msgid "Notice"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Refresh log"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Sorting entries"
|
msgid "Sorting entries"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -317,8 +317,8 @@ function BlackListParser:fill_domain_tables(val)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function BlackListParser:sink()
|
function BlackListParser:sink()
|
||||||
-- Needs to be reloaded in subclass
|
-- Must be overridden by a subclass
|
||||||
error("Method BlackListParser:sink() needs to be reloaded in subclass!")
|
error("Method BlackListParser:sink() must be overridden by a subclass!")
|
||||||
end
|
end
|
||||||
|
|
||||||
function BlackListParser:optimize_ip_table()
|
function BlackListParser:optimize_ip_table()
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ class BlackListParser(Config):
|
|||||||
raise FieldValueError()
|
raise FieldValueError()
|
||||||
|
|
||||||
def parser_func(self):
|
def parser_func(self):
|
||||||
"""Needs to be reloaded in subclass"""
|
"""Must be overridden by a subclass"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def _check_sld_masks(self, sld):
|
def _check_sld_masks(self, sld):
|
||||||
|
|||||||
Reference in New Issue
Block a user