luci-app-banip: handle json load errors
[project/luci.git] / applications / luci-app-banip / htdocs / luci-static / resources / view / banip / setreport.js
1 'use strict';
2 'require view';
3 'require fs';
4 'require ui';
5
6 /*
7 button handling
8 */
9 function handleAction(report, ev) {
10 if (ev === 'search') {
11 L.ui.showModal(_('IP Search'), [
12 E('p', _('Search the banIP-related Sets for a specific IP.')),
13 E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
14 E('label', { 'style': 'padding-top:.5em', 'id': 'run' }, [
15 E('input', {
16 'class': 'cbi-input-text',
17 'placeholder': '192.168.0.1',
18 'style': 'width:300px',
19 'spellcheck': 'false',
20 'id': 'search'
21 })
22 ])
23 ]),
24 E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
25 '\xa0',
26 E('h5', _('Result')),
27 E('textarea', {
28 'id': 'result',
29 'style': 'width: 100% !important; padding: 5px; font-family: monospace',
30 'readonly': 'readonly',
31 'wrap': 'off',
32 'rows': 20
33 })
34 ]),
35 E('div', { 'class': 'right' }, [
36 E('button', {
37 'class': 'btn cbi-button',
38 'click': L.hideModal
39 }, _('Cancel')),
40 ' ',
41 E('button', {
42 'class': 'btn cbi-button-action',
43 'click': ui.createHandlerFn(this, function (ev) {
44 let ip = document.getElementById('search').value.trim().toLowerCase();
45 if (ip) {
46 document.getElementById('search').value = ip;
47 document.getElementById('result').textContent = 'The search is running, please wait...';
48 return L.resolveDefault(fs.exec_direct('/etc/init.d/banip', ['search', ip])).then(function (res) {
49 let result = document.getElementById('result');
50 if (res) {
51 result.textContent = res.trim();
52 } else {
53 result.textContent = _('No Search results!');
54 }
55 document.getElementById('search').value = '';
56 })
57 }
58 document.getElementById('search').focus();
59 })
60 }, _('Search'))
61 ])
62 ]);
63 document.getElementById('search').focus();
64 }
65 if (ev === 'survey') {
66 let content, selectOption;
67
68 if (report[1]) {
69 try {
70 content = JSON.parse(report[1]);
71 } catch (e) {
72 content = "";
73 ui.addNotification(null, E('p', _('Unable to parse the ruleset file: %s').format(e.message)), 'error');
74 }
75 } else {
76 content = "";
77 }
78 selectOption = [E('option', { value: '' }, [_('-- Set Selection --')])];
79 for (let i = 0; i < Object.keys(content.nftables).length; i++) {
80 if (content.nftables[i].set && content.nftables[i].set.name !== undefined && content.nftables[i].set.table !== undefined && content.nftables[i].set.table === 'banIP') {
81 selectOption.push(E('option', { 'value': content.nftables[i].set.name }, content.nftables[i].set.name));
82 }
83 }
84 L.ui.showModal(_('Set Survey'), [
85 E('p', _('List the elements of a specific banIP-related Set.')),
86 E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
87 E('label', { 'class': 'cbi-input-select', 'style': 'padding-top:.5em', 'id': 'run' }, [
88 E('h5', _('Set')),
89 E('select', { 'class': 'cbi-input-select', 'id': 'set' },
90 selectOption
91 )
92 ]),
93 ]),
94 E('div', { 'class': 'left', 'style': 'display:flex; flex-direction:column' }, [
95 '\xa0',
96 E('h5', _('Result')),
97 E('textarea', {
98 'id': 'result',
99 'style': 'width: 100% !important; padding: 5px; font-family: monospace',
100 'readonly': 'readonly',
101 'wrap': 'off',
102 'rows': 20
103 })
104 ]),
105 E('div', { 'class': 'right' }, [
106 E('button', {
107 'class': 'btn cbi-button',
108 'click': L.hideModal
109 }, _('Cancel')),
110 ' ',
111 E('button', {
112 'class': 'btn cbi-button-action',
113 'click': ui.createHandlerFn(this, function (ev) {
114 let set = document.getElementById('set').value;
115 if (set) {
116 document.getElementById('result').textContent = 'The survey is running, please wait...';
117 return L.resolveDefault(fs.exec_direct('/etc/init.d/banip', ['survey', set])).then(function (res) {
118 let result = document.getElementById('result');
119 if (res) {
120 result.textContent = res.trim();
121 } else {
122 result.textContent = _('No Search results!');
123 }
124 document.getElementById('set').value = '';
125 })
126 }
127 document.getElementById('set').focus();
128 })
129 }, _('Survey'))
130 ])
131 ]);
132 document.getElementById('set').focus();
133 }
134 }
135
136 return view.extend({
137 load: function () {
138 return Promise.all([
139 L.resolveDefault(fs.exec_direct('/etc/init.d/banip', ['report', 'json']), ''),
140 L.resolveDefault(fs.exec_direct('/usr/sbin/nft', ['-tj', 'list', 'ruleset']), '')
141 ]);
142 },
143
144 render: function (report) {
145 let content, rowSets, tblSets;
146
147 if (report[0]) {
148 try {
149 content = JSON.parse(report[0]);
150 } catch (e) {
151 content = "";
152 ui.addNotification(null, E('p', _('Unable to parse the report file: %s').format(e.message)), 'error');
153 }
154 } else {
155 content = "";
156 }
157 rowSets = [];
158 tblSets = E('table', { 'class': 'table', 'id': 'sets' }, [
159 E('tr', { 'class': 'tr table-titles' }, [
160 E('th', { 'class': 'th' }, _('Set')),
161 E('th', { 'class': 'th right', 'style': 'padding-right: 20px' }, _('Elements')),
162 E('th', { 'class': 'th' }, _('WAN-Input (packets)')),
163 E('th', { 'class': 'th' }, _('WAN-Forward (packets)')),
164 E('th', { 'class': 'th' }, _('LAN-Forward (packets)')),
165 E('th', { 'class': 'th' }, _('Port/Protocol Limit'))
166 ])
167 ]);
168
169 if (content.sets) {
170 let cnt1, cnt2, cnt3;
171 Object.keys(content.sets).forEach(function (key) {
172 cnt1 = content.sets[key].cnt_input ? ': (' + content.sets[key].cnt_input + ')' : '';
173 cnt2 = content.sets[key].cnt_forwardwan ? ': (' + content.sets[key].cnt_forwardwan + ')' : '';
174 cnt3 = content.sets[key].cnt_forwardlan ? ': (' + content.sets[key].cnt_forwardlan + ')' : '';
175 rowSets.push([
176 E('em', key),
177 E('em', { 'style': 'padding-right: 20px' }, content.sets[key].cnt_elements),
178 E('em', content.sets[key].input + cnt1),
179 E('em', content.sets[key].wan_forward + cnt2),
180 E('em', content.sets[key].lan_forward + cnt3),
181 E('em', content.sets[key].port)
182 ]);
183 });
184 rowSets.push([
185 E('em', { 'style': 'font-weight: bold' }, content.sum_sets),
186 E('em', { 'style': 'font-weight: bold; padding-right: 20px' }, content.sum_setelements),
187 E('em', { 'style': 'font-weight: bold' }, content.sum_setinput + ' (' + content.sum_cntinput + ')'),
188 E('em', { 'style': 'font-weight: bold' }, content.sum_setforwardwan + ' (' + content.sum_cntforwardwan + ')'),
189 E('em', { 'style': 'font-weight: bold' }, content.sum_setforwardlan + ' (' + content.sum_cntforwardlan + ')')
190 ]);
191 }
192 cbi_update_table(tblSets, rowSets);
193
194 return E('div', { 'class': 'cbi-map', 'id': 'map' }, [
195 E('div', { 'class': 'cbi-section' }, [
196 E('p', _('This tab shows the last generated Set Report, press the \'Refresh\' button to get a new one.')),
197 E('p', '\xa0'),
198 E('div', { 'class': 'cbi-value' }, [
199 E('div', { 'class': 'cbi-value-title', 'style': 'margin-bottom:-5px;float:left;width:230px;font-weight:bold;' }, _('Timestamp')),
200 E('div', { 'class': 'cbi-value-title', 'id': 'start', 'style': 'margin-bottom:-5px;float:left;color:#37c;font-weight:bold;' }, content.timestamp || '-')
201 ]),
202 E('hr'),
203 E('div', { 'class': 'cbi-value' }, [
204 E('div', { 'class': 'cbi-value-title', 'style': 'margin-top:-5px;float:left;width:230px;font-weight:bold;' }, _('blocked syn-flood packets')),
205 E('div', { 'class': 'cbi-value-title', 'id': 'start', 'style': 'margin-top:-5px;float:left;color:#37c;font-weight:bold;' }, content.sum_synflood || '-')
206 ]),
207 E('div', { 'class': 'cbi-value' }, [
208 E('div', { 'class': 'cbi-value-title', 'style': 'margin-top:-5px;float:left;width:230px;font-weight:bold;' }, _('blocked udp-flood packets')),
209 E('div', { 'class': 'cbi-value-title', 'id': 'start', 'style': 'margin-top:-5px;float:left;color:#37c;font-weight:bold;' }, content.sum_udpflood || '-')
210 ]),
211 E('div', { 'class': 'cbi-value' }, [
212 E('div', { 'class': 'cbi-value-title', 'style': 'margin-top:-5px;float:left;width:230px;font-weight:bold;' }, _('blocked icmp-flood packets')),
213 E('div', { 'class': 'cbi-value-title', 'id': 'start', 'style': 'margin-top:-5px;float:left;color:#37c;font-weight:bold;' }, content.sum_icmpflood || '-')
214 ]),
215 E('div', { 'class': 'cbi-value' }, [
216 E('div', { 'class': 'cbi-value-title', 'style': 'margin-top:-5px;float:left;width:230px;font-weight:bold;' }, _('blocked invalid ct packets')),
217 E('div', { 'class': 'cbi-value-title', 'id': 'start', 'style': 'margin-top:-5px;float:left;color:#37c;font-weight:bold;' }, content.sum_ctinvalid || '-')
218 ]),
219 E('div', { 'class': 'cbi-value' }, [
220 E('div', { 'class': 'cbi-value-title', 'style': 'margin-top:-5px;float:left;width:230px;font-weight:bold;' }, _('blocked invalid tcp packets')),
221 E('div', { 'class': 'cbi-value-title', 'id': 'start', 'style': 'margin-top:-5px;float:left;color:#37c;font-weight:bold;' }, content.sum_tcpinvalid || '-')
222 ]),
223 E('hr'),
224 E('div', { 'class': 'cbi-value' }, [
225 E('div', { 'class': 'cbi-value-title', 'style': 'margin-top:-5px;float:left;width:230px;font-weight:bold;' }, _('auto-added IPs to allowlist')),
226 E('div', { 'class': 'cbi-value-title', 'id': 'start', 'style': 'margin-top:-5px;float:left;color:#37c;font-weight:bold;' }, content.autoadd_allow || '-')
227 ]),
228 E('div', { 'class': 'cbi-value' }, [
229 E('div', { 'class': 'cbi-value-title', 'style': 'margin-top:-5px;float:left;width:230px;font-weight:bold;' }, _('auto-added IPs to blocklist')),
230 E('div', { 'class': 'cbi-value-title', 'id': 'start', 'style': 'margin-top:-5px;float:left;color:#37c;font-weight:bold;' }, content.autoadd_block || '-')
231 ]),
232 E('div', { 'class': 'right' }, [
233 E('button', {
234 'class': 'btn cbi-button cbi-button-apply',
235 'click': ui.createHandlerFn(this, function () {
236 return handleAction(report, 'survey');
237 })
238 }, [_('Set Survey...')]),
239 '\xa0\xa0\xa0',
240 E('button', {
241 'class': 'btn cbi-button cbi-button-apply',
242 'click': ui.createHandlerFn(this, function () {
243 return handleAction(report, 'search');
244 })
245 }, [_('IP Search...')]),
246 '\xa0\xa0\xa0',
247 E('button', {
248 'class': 'btn cbi-button cbi-button-positive',
249 'click': ui.createHandlerFn(this, function () {
250 location.reload();
251 })
252 }, [_('Refresh')])
253 ]),
254 ])
255 ,
256 E('br'),
257 E('div', { 'class': 'cbi-section' }, [
258 E('div', { 'class': 'left' }, [
259 E('h3', _('Set details')),
260 tblSets
261 ])
262 ])
263 ]);
264 },
265 handleSaveApply: null,
266 handleSave: null,
267 handleReset: null
268 });