setreport.js 10 KB

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