debug.js 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
  1. $(document).ready(function() {
  2. // Parse seconds ago to date
  3. // Get "now" timestamp
  4. var ts_now = Math.round((new Date()).getTime() / 1000);
  5. $('.parse_s_ago').each(function(i, parse_s_ago) {
  6. var started_s_ago = parseInt($(this).text(), 10);
  7. if (typeof started_s_ago != 'NaN') {
  8. var started_date = new Date((ts_now - started_s_ago) * 1000);
  9. if (started_date instanceof Date && !isNaN(started_date)) {
  10. var started_local_date = started_date.toLocaleDateString(undefined, {
  11. year: "numeric",
  12. month: "2-digit",
  13. day: "2-digit",
  14. hour: "2-digit",
  15. minute: "2-digit",
  16. second: "2-digit"
  17. });
  18. $(this).text(started_local_date);
  19. } else {
  20. $(this).text('-');
  21. }
  22. }
  23. });
  24. // Parse general dates
  25. $('.parse_date').each(function(i, parse_date) {
  26. var started_date = new Date(Date.parse($(this).text()));
  27. if (typeof started_date != 'NaN') {
  28. var started_local_date = started_date.toLocaleDateString(undefined, {
  29. year: "numeric",
  30. month: "2-digit",
  31. day: "2-digit",
  32. hour: "2-digit",
  33. minute: "2-digit",
  34. second: "2-digit"
  35. });
  36. $(this).text(started_local_date);
  37. }
  38. });
  39. });
  40. jQuery(function($){
  41. if (localStorage.getItem("current_page") === null) {
  42. var current_page = {};
  43. } else {
  44. var current_page = JSON.parse(localStorage.getItem('current_page'));
  45. }
  46. // http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
  47. var entityMap={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};
  48. function escapeHtml(n){return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})}
  49. function humanFileSize(i){if(Math.abs(i)<1024)return i+" B";var B=["KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],e=-1;do{i/=1024,++e}while(Math.abs(i)>=1024&&e<B.length-1);return i.toFixed(1)+" "+B[e]}
  50. function hashCode(t){for(var n=0,r=0;r<t.length;r++)n=t.charCodeAt(r)+((n<<5)-n);return n}
  51. function intToRGB(t){var n=(16777215&t).toString(16).toUpperCase();return"00000".substring(0,6-n.length)+n}
  52. $(".refresh_table").on('click', function(e) {
  53. e.preventDefault();
  54. var table_name = $(this).data('table');
  55. $('#' + table_name).DataTable().ajax.reload();
  56. });
  57. function draw_autodiscover_logs() {
  58. // just recalc width if instance already exists
  59. if ($.fn.DataTable.isDataTable('#autodiscover_log') ) {
  60. $('#autodiscover_log').DataTable().columns.adjust().responsive.recalc();
  61. return;
  62. }
  63. $('#autodiscover_log').DataTable({
  64. processing: true,
  65. serverSide: false,
  66. language: lang_datatables,
  67. order: [[0, 'desc']],
  68. ajax: {
  69. type: "GET",
  70. url: "/api/v1/get/logs/autodiscover/100",
  71. dataSrc: function(data){
  72. return process_table_data(data, 'autodiscover_log');
  73. }
  74. },
  75. columns: [
  76. {
  77. title: lang.time,
  78. data: 'time',
  79. defaultContent: '',
  80. render: function(data, type){
  81. var date = new Date(data ? data * 1000 : 0);
  82. return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
  83. }
  84. },
  85. {
  86. title: 'User-Agent',
  87. data: 'ua',
  88. defaultContent: ''
  89. },
  90. {
  91. title: 'Username',
  92. data: 'user',
  93. defaultContent: ''
  94. },
  95. {
  96. title: 'IP',
  97. data: 'ip',
  98. defaultContent: ''
  99. },
  100. {
  101. title: 'Service',
  102. data: 'service',
  103. defaultContent: ''
  104. }
  105. ]
  106. });
  107. }
  108. function draw_postfix_logs() {
  109. // just recalc width if instance already exists
  110. if ($.fn.DataTable.isDataTable('#postfix_log') ) {
  111. $('#postfix_log').DataTable().columns.adjust().responsive.recalc();
  112. return;
  113. }
  114. $('#postfix_log').DataTable({
  115. processing: true,
  116. serverSide: false,
  117. language: lang_datatables,
  118. order: [[0, 'desc']],
  119. ajax: {
  120. type: "GET",
  121. url: "/api/v1/get/logs/postfix",
  122. dataSrc: function(data){
  123. return process_table_data(data, 'general_syslog');
  124. }
  125. },
  126. columns: [
  127. {
  128. title: lang.time,
  129. data: 'time',
  130. defaultContent: '',
  131. render: function(data, type){
  132. var date = new Date(data ? data * 1000 : 0);
  133. return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
  134. }
  135. },
  136. {
  137. title: lang.priority,
  138. data: 'priority',
  139. defaultContent: ''
  140. },
  141. {
  142. title: lang.message,
  143. data: 'message',
  144. defaultContent: ''
  145. }
  146. ]
  147. });
  148. }
  149. function draw_watchdog_logs() {
  150. // just recalc width if instance already exists
  151. if ($.fn.DataTable.isDataTable('#watchdog_log') ) {
  152. $('#watchdog_log').DataTable().columns.adjust().responsive.recalc();
  153. return;
  154. }
  155. $('#watchdog_log').DataTable({
  156. processing: true,
  157. serverSide: false,
  158. language: lang_datatables,
  159. order: [[0, 'desc']],
  160. ajax: {
  161. type: "GET",
  162. url: "/api/v1/get/logs/watchdog",
  163. dataSrc: function(data){
  164. return process_table_data(data, 'watchdog');
  165. }
  166. },
  167. columns: [
  168. {
  169. title: lang.time,
  170. data: 'time',
  171. defaultContent: '',
  172. render: function(data, type){
  173. var date = new Date(data ? data * 1000 : 0);
  174. return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
  175. }
  176. },
  177. {
  178. title: 'Service',
  179. data: 'service',
  180. defaultContent: ''
  181. },
  182. {
  183. title: 'Trend',
  184. data: 'trend',
  185. defaultContent: ''
  186. },
  187. {
  188. title: lang.message,
  189. data: 'message',
  190. defaultContent: ''
  191. }
  192. ]
  193. });
  194. }
  195. function draw_api_logs() {
  196. // just recalc width if instance already exists
  197. if ($.fn.DataTable.isDataTable('#api_log') ) {
  198. $('#api_log').DataTable().columns.adjust().responsive.recalc();
  199. return;
  200. }
  201. $('#api_log').DataTable({
  202. processing: true,
  203. serverSide: false,
  204. language: lang_datatables,
  205. order: [[0, 'desc']],
  206. ajax: {
  207. type: "GET",
  208. url: "/api/v1/get/logs/api",
  209. dataSrc: function(data){
  210. return process_table_data(data, 'apilog');
  211. }
  212. },
  213. columns: [
  214. {
  215. title: lang.time,
  216. data: 'time',
  217. defaultContent: '',
  218. render: function(data, type){
  219. var date = new Date(data ? data * 1000 : 0);
  220. return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
  221. }
  222. },
  223. {
  224. title: 'URI',
  225. data: 'uri',
  226. defaultContent: ''
  227. },
  228. {
  229. title: 'Method',
  230. data: 'method',
  231. defaultContent: ''
  232. },
  233. {
  234. title: 'IP',
  235. data: 'remote',
  236. defaultContent: ''
  237. },
  238. {
  239. title: 'Data',
  240. data: 'data',
  241. defaultContent: ''
  242. }
  243. ]
  244. });
  245. }
  246. function draw_rl_logs() {
  247. // just recalc width if instance already exists
  248. if ($.fn.DataTable.isDataTable('#rl_log') ) {
  249. $('#rl_log').DataTable().columns.adjust().responsive.recalc();
  250. return;
  251. }
  252. $('#rl_log').DataTable({
  253. processing: true,
  254. serverSide: false,
  255. language: lang_datatables,
  256. order: [[0, 'desc']],
  257. ajax: {
  258. type: "GET",
  259. url: "/api/v1/get/logs/ratelimited",
  260. dataSrc: function(data){
  261. return process_table_data(data, 'rllog');
  262. }
  263. },
  264. columns: [
  265. {
  266. title: ' ',
  267. data: 'indicator',
  268. defaultContent: ''
  269. },
  270. {
  271. title: lang.time,
  272. data: 'time',
  273. defaultContent: '',
  274. render: function(data, type){
  275. var date = new Date(data ? data * 1000 : 0);
  276. return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
  277. }
  278. },
  279. {
  280. title: lang.rate_name,
  281. data: 'rl_name',
  282. defaultContent: ''
  283. },
  284. {
  285. title: lang.sender,
  286. data: 'from',
  287. defaultContent: ''
  288. },
  289. {
  290. title: lang.recipients,
  291. data: 'rcpt',
  292. defaultContent: ''
  293. },
  294. {
  295. title: lang.authed_user,
  296. data: 'user',
  297. defaultContent: ''
  298. },
  299. {
  300. title: 'Msg ID',
  301. data: 'message_id',
  302. defaultContent: ''
  303. },
  304. {
  305. title: 'Header From',
  306. data: 'header_from',
  307. defaultContent: ''
  308. },
  309. {
  310. title: 'Subject',
  311. data: 'header_subject',
  312. defaultContent: ''
  313. },
  314. {
  315. title: 'Hash',
  316. data: 'rl_hash',
  317. defaultContent: ''
  318. },
  319. {
  320. title: 'Rspamd QID',
  321. data: 'qid',
  322. defaultContent: ''
  323. },
  324. {
  325. title: 'IP',
  326. data: 'ip',
  327. defaultContent: ''
  328. },
  329. {
  330. title: lang.action,
  331. data: 'action',
  332. defaultContent: ''
  333. }
  334. ]
  335. });
  336. }
  337. function draw_ui_logs() {
  338. // just recalc width if instance already exists
  339. if ($.fn.DataTable.isDataTable('#ui_logs') ) {
  340. $('#ui_logs').DataTable().columns.adjust().responsive.recalc();
  341. return;
  342. }
  343. $('#ui_logs').DataTable({
  344. processing: true,
  345. serverSide: false,
  346. language: lang_datatables,
  347. order: [[0, 'desc']],
  348. ajax: {
  349. type: "GET",
  350. url: "/api/v1/get/logs/ui",
  351. dataSrc: function(data){
  352. return process_table_data(data, 'mailcow_ui');
  353. }
  354. },
  355. columns: [
  356. {
  357. title: lang.time,
  358. data: 'time',
  359. defaultContent: '',
  360. render: function(data, type){
  361. var date = new Date(data ? data * 1000 : 0);
  362. return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
  363. }
  364. },
  365. {
  366. title: 'Type',
  367. data: 'type',
  368. defaultContent: ''
  369. },
  370. {
  371. title: 'Task',
  372. data: 'task',
  373. defaultContent: ''
  374. },
  375. {
  376. title: 'User',
  377. data: 'user',
  378. defaultContent: ''
  379. },
  380. {
  381. title: 'Role',
  382. data: 'role',
  383. defaultContent: ''
  384. },
  385. {
  386. title: 'IP',
  387. data: 'remote',
  388. defaultContent: ''
  389. },
  390. {
  391. title: lang.message,
  392. data: 'msg',
  393. defaultContent: ''
  394. },
  395. {
  396. title: 'Call',
  397. data: 'call',
  398. defaultContent: ''
  399. }
  400. ]
  401. });
  402. }
  403. function draw_sasl_logs() {
  404. // just recalc width if instance already exists
  405. if ($.fn.DataTable.isDataTable('#sasl_logs') ) {
  406. $('#sasl_logs').DataTable().columns.adjust().responsive.recalc();
  407. return;
  408. }
  409. $('#sasl_logs').DataTable({
  410. processing: true,
  411. serverSide: false,
  412. language: lang_datatables,
  413. order: [[0, 'desc']],
  414. ajax: {
  415. type: "GET",
  416. url: "/api/v1/get/logs/sasl",
  417. dataSrc: function(data){
  418. return process_table_data(data, 'sasl_log_table');
  419. }
  420. },
  421. columns: [
  422. {
  423. title: lang.username,
  424. data: 'username',
  425. defaultContent: ''
  426. },
  427. {
  428. title: lang.service,
  429. data: 'service',
  430. defaultContent: ''
  431. },
  432. {
  433. title: 'IP',
  434. data: 'real_rip',
  435. defaultContent: ''
  436. },
  437. {
  438. title: lang.login_time,
  439. data: 'datetime',
  440. defaultContent: '',
  441. render: function(data, type){
  442. var date = new Date(data.replace(/-/g, "/"));
  443. return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
  444. }
  445. }
  446. ]
  447. });
  448. }
  449. function draw_acme_logs() {
  450. // just recalc width if instance already exists
  451. if ($.fn.DataTable.isDataTable('#acme_log') ) {
  452. $('#acme_log').DataTable().columns.adjust().responsive.recalc();
  453. return;
  454. }
  455. $('#acme_log').DataTable({
  456. processing: true,
  457. serverSide: false,
  458. language: lang_datatables,
  459. order: [[0, 'desc']],
  460. ajax: {
  461. type: "GET",
  462. url: "/api/v1/get/logs/acme",
  463. dataSrc: function(data){
  464. return process_table_data(data, 'general_syslog');
  465. }
  466. },
  467. columns: [
  468. {
  469. title: lang.time,
  470. data: 'time',
  471. defaultContent: '',
  472. render: function(data, type){
  473. var date = new Date(data ? data * 1000 : 0);
  474. return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
  475. }
  476. },
  477. {
  478. title: lang.message,
  479. data: 'message',
  480. defaultContent: ''
  481. }
  482. ]
  483. });
  484. }
  485. function draw_netfilter_logs() {
  486. // just recalc width if instance already exists
  487. if ($.fn.DataTable.isDataTable('#netfilter_log') ) {
  488. $('#netfilter_log').DataTable().columns.adjust().responsive.recalc();
  489. return;
  490. }
  491. $('#netfilter_log').DataTable({
  492. processing: true,
  493. serverSide: false,
  494. language: lang_datatables,
  495. order: [[0, 'desc']],
  496. ajax: {
  497. type: "GET",
  498. url: "/api/v1/get/logs/netfilter",
  499. dataSrc: function(data){
  500. return process_table_data(data, 'general_syslog');
  501. }
  502. },
  503. columns: [
  504. {
  505. title: lang.time,
  506. data: 'time',
  507. defaultContent: '',
  508. render: function(data, type){
  509. var date = new Date(data ? data * 1000 : 0);
  510. return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
  511. }
  512. },
  513. {
  514. title: lang.priority,
  515. data: 'priority',
  516. defaultContent: ''
  517. },
  518. {
  519. title: lang.message,
  520. data: 'message',
  521. defaultContent: ''
  522. }
  523. ]
  524. });
  525. }
  526. function draw_sogo_logs() {
  527. // just recalc width if instance already exists
  528. if ($.fn.DataTable.isDataTable('#sogo_log') ) {
  529. $('#sogo_log').DataTable().columns.adjust().responsive.recalc();
  530. return;
  531. }
  532. $('#sogo_log').DataTable({
  533. processing: true,
  534. serverSide: false,
  535. language: lang_datatables,
  536. order: [[0, 'desc']],
  537. ajax: {
  538. type: "GET",
  539. url: "/api/v1/get/logs/sogo",
  540. dataSrc: function(data){
  541. return process_table_data(data, 'general_syslog');
  542. }
  543. },
  544. columns: [
  545. {
  546. title: lang.time,
  547. data: 'time',
  548. defaultContent: '',
  549. render: function(data, type){
  550. var date = new Date(data ? data * 1000 : 0);
  551. return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
  552. }
  553. },
  554. {
  555. title: lang.priority,
  556. data: 'priority',
  557. defaultContent: ''
  558. },
  559. {
  560. title: lang.message,
  561. data: 'message',
  562. defaultContent: ''
  563. }
  564. ]
  565. });
  566. }
  567. function draw_dovecot_logs() {
  568. // just recalc width if instance already exists
  569. if ($.fn.DataTable.isDataTable('#dovecot_log') ) {
  570. $('#dovecot_log').DataTable().columns.adjust().responsive.recalc();
  571. return;
  572. }
  573. $('#dovecot_log').DataTable({
  574. processing: true,
  575. serverSide: false,
  576. language: lang_datatables,
  577. order: [[0, 'desc']],
  578. ajax: {
  579. type: "GET",
  580. url: "/api/v1/get/logs/dovecot",
  581. dataSrc: function(data){
  582. return process_table_data(data, 'general_syslog');
  583. }
  584. },
  585. columns: [
  586. {
  587. title: lang.time,
  588. data: 'time',
  589. defaultContent: '',
  590. render: function(data, type){
  591. var date = new Date(data ? data * 1000 : 0);
  592. return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
  593. }
  594. },
  595. {
  596. title: lang.priority,
  597. data: 'priority',
  598. defaultContent: ''
  599. },
  600. {
  601. title: lang.message,
  602. data: 'message',
  603. defaultContent: ''
  604. }
  605. ]
  606. });
  607. }
  608. function rspamd_pie_graph() {
  609. $.ajax({
  610. url: '/api/v1/get/rspamd/actions',
  611. async: true,
  612. success: function(data){
  613. console.log(data);
  614. var total = 0;
  615. $(data).map(function(){total += this[1];});
  616. var labels = $.makeArray($(data).map(function(){return this[0] + ' ' + Math.round(this[1]/total * 100) + '%';}));
  617. var values = $.makeArray($(data).map(function(){return this[1];}));
  618. console.log(values);
  619. var graphdata = {
  620. labels: labels,
  621. datasets: [{
  622. data: values,
  623. backgroundColor: ['#DC3023', '#59ABE3', '#FFA400', '#FFA400', '#26A65B']
  624. }]
  625. };
  626. var options = {
  627. responsive: true,
  628. maintainAspectRatio: false,
  629. plugins: {
  630. datalabels: {
  631. color: '#FFF',
  632. font: {
  633. weight: 'bold'
  634. },
  635. display: function(context) {
  636. return context.dataset.data[context.dataIndex] !== 0;
  637. },
  638. formatter: function(value, context) {
  639. return Math.round(value/total*100) + '%';
  640. }
  641. }
  642. }
  643. };
  644. var chartcanvas = document.getElementById('rspamd_donut');
  645. Chart.register('ChartDataLabels');
  646. if(typeof chart == 'undefined') {
  647. chart = new Chart(chartcanvas.getContext("2d"), {
  648. plugins: [ChartDataLabels],
  649. type: 'doughnut',
  650. data: graphdata,
  651. options: options
  652. });
  653. }
  654. else {
  655. chart.destroy();
  656. chart = new Chart(chartcanvas.getContext("2d"), {
  657. plugins: [ChartDataLabels],
  658. type: 'doughnut',
  659. data: graphdata,
  660. options: options
  661. });
  662. }
  663. }
  664. });
  665. }
  666. function draw_rspamd_history() {
  667. // just recalc width if instance already exists
  668. if ($.fn.DataTable.isDataTable('#rspamd_history') ) {
  669. $('#rspamd_history').DataTable().columns.adjust().responsive.recalc();
  670. return;
  671. }
  672. $('#rspamd_history').DataTable({
  673. processing: true,
  674. serverSide: false,
  675. language: lang_datatables,
  676. ajax: {
  677. type: "GET",
  678. url: "/api/v1/get/logs/rspamd-history",
  679. dataSrc: function(data){
  680. return process_table_data(data, 'rspamd_history');
  681. }
  682. },
  683. columns: [
  684. {
  685. title: lang.time,
  686. data: 'time',
  687. defaultContent: '',
  688. render: function(data, type){
  689. var date = new Date(data ? data * 1000 : 0);
  690. return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
  691. }
  692. },
  693. {
  694. title: 'IP address',
  695. data: 'ip',
  696. defaultContent: ''
  697. },
  698. {
  699. title: 'From',
  700. data: 'sender_mime',
  701. defaultContent: ''
  702. },
  703. {
  704. title: 'To',
  705. data: 'rcpt',
  706. defaultContent: ''
  707. },
  708. {
  709. title: 'Subject',
  710. data: 'subject',
  711. defaultContent: ''
  712. },
  713. {
  714. title: 'Action',
  715. data: 'action',
  716. defaultContent: ''
  717. },
  718. {
  719. title: 'Score',
  720. data: 'score',
  721. defaultContent: ''
  722. },
  723. {
  724. title: 'Subject',
  725. data: 'header_subject',
  726. defaultContent: ''
  727. },
  728. {
  729. title: 'Symbols',
  730. data: 'symbols',
  731. defaultContent: ''
  732. },
  733. {
  734. title: 'Msg size',
  735. data: 'size',
  736. defaultContent: ''
  737. },
  738. {
  739. title: 'Scan Time',
  740. data: 'scan_time',
  741. defaultContent: ''
  742. },
  743. {
  744. title: 'ID',
  745. data: 'message-id',
  746. defaultContent: ''
  747. },
  748. {
  749. title: 'Authenticated user',
  750. data: 'user',
  751. defaultContent: ''
  752. }
  753. ]
  754. });
  755. }
  756. function process_table_data(data, table) {
  757. if (table == 'rspamd_history') {
  758. $.each(data, function (i, item) {
  759. if (item.rcpt_mime != "") {
  760. item.rcpt = escapeHtml(item.rcpt_mime.join(", "));
  761. }
  762. else {
  763. item.rcpt = escapeHtml(item.rcpt_smtp.join(", "));
  764. }
  765. item.symbols = Object.keys(item.symbols).sort(function (a, b) {
  766. if (item.symbols[a].score === 0) return 1
  767. if (item.symbols[b].score === 0) return -1
  768. if (item.symbols[b].score < 0 && item.symbols[a].score < 0) {
  769. return item.symbols[a].score - item.symbols[b].score
  770. }
  771. if (item.symbols[b].score > 0 && item.symbols[a].score > 0) {
  772. return item.symbols[b].score - item.symbols[a].score
  773. }
  774. return item.symbols[b].score - item.symbols[a].score
  775. }).map(function(key) {
  776. var sym = item.symbols[key];
  777. if (sym.score < 0) {
  778. sym.score_formatted = '(<span class="text-success"><b>' + sym.score + '</b></span>)'
  779. }
  780. else if (sym.score === 0) {
  781. sym.score_formatted = '(<span><b>' + sym.score + '</b></span>)'
  782. }
  783. else {
  784. sym.score_formatted = '(<span class="text-danger"><b>' + sym.score + '</b></span>)'
  785. }
  786. var str = '<strong>' + key + '</strong> ' + sym.score_formatted;
  787. if (sym.options) {
  788. str += ' [' + escapeHtml(sym.options.join(", ")) + "]";
  789. }
  790. return str
  791. }).join('<br>\n');
  792. item.subject = escapeHtml(item.subject);
  793. var scan_time = item.time_real.toFixed(3);
  794. if (item.time_virtual) {
  795. scan_time += ' / ' + item.time_virtual.toFixed(3);
  796. }
  797. item.scan_time = {
  798. "options": {
  799. "sortValue": item.time_real
  800. },
  801. "value": scan_time
  802. };
  803. if (item.action === 'clean' || item.action === 'no action') {
  804. item.action = "<div class='badge fs-6 bg-success'>" + item.action + "</div>";
  805. } else if (item.action === 'rewrite subject' || item.action === 'add header' || item.action === 'probable spam') {
  806. item.action = "<div class='badge fs-6 bg-warning'>" + item.action + "</div>";
  807. } else if (item.action === 'spam' || item.action === 'reject') {
  808. item.action = "<div class='badge fs-6 bg-danger'>" + item.action + "</div>";
  809. } else {
  810. item.action = "<div class='badge fs-6 bg-info'>" + item.action + "</div>";
  811. }
  812. var score_content;
  813. if (item.score < item.required_score) {
  814. score_content = "[ <span class='text-success'>" + item.score.toFixed(2) + " / " + item.required_score + "</span> ]";
  815. } else {
  816. score_content = "[ <span class='text-danger'>" + item.score.toFixed(2) + " / " + item.required_score + "</span> ]";
  817. }
  818. item.score = {
  819. "options": {
  820. "sortValue": item.score
  821. },
  822. "value": score_content
  823. };
  824. if (item.user == null) {
  825. item.user = "none";
  826. }
  827. });
  828. } else if (table == 'autodiscover_log') {
  829. $.each(data, function (i, item) {
  830. if (item.ua == null) {
  831. item.ua = 'unknown';
  832. } else {
  833. item.ua = escapeHtml(item.ua);
  834. }
  835. item.ua = '<span style="font-size:small">' + item.ua + '</span>';
  836. if (item.service == "activesync") {
  837. item.service = '<span class="badge fs-6 bg-info">ActiveSync</span>';
  838. }
  839. else if (item.service == "imap") {
  840. item.service = '<span class="badge fs-6 bg-success">IMAP, SMTP, Cal-/CardDAV</span>';
  841. }
  842. else {
  843. item.service = '<span class="badge fs-6 bg-danger">' + escapeHtml(item.service) + '</span>';
  844. }
  845. });
  846. } else if (table == 'watchdog') {
  847. $.each(data, function (i, item) {
  848. if (item.message == null) {
  849. item.message = 'Health level: ' + item.lvl + '% (' + item.hpnow + '/' + item.hptotal + ')';
  850. if (item.hpdiff < 0) {
  851. item.trend = '<span class="badge fs-6 bg-danger"><i class="bi bi-caret-down-fill"></i> ' + item.hpdiff + '</span>';
  852. }
  853. else if (item.hpdiff == 0) {
  854. item.trend = '<span class="badge fs-6 bg-info"><i class="bi bi-caret-right-fill"></i> ' + item.hpdiff + '</span>';
  855. }
  856. else {
  857. item.trend = '<span class="badge fs-6 bg-success"><i class="bi bi-caret-up-fill"></i> ' + item.hpdiff + '</span>';
  858. }
  859. }
  860. else {
  861. item.trend = '';
  862. item.service = '';
  863. }
  864. });
  865. } else if (table == 'mailcow_ui') {
  866. $.each(data, function (i, item) {
  867. if (item === null) { return true; }
  868. item.user = escapeHtml(item.user);
  869. item.call = escapeHtml(item.call);
  870. item.task = '<code>' + item.task + '</code>';
  871. item.type = '<span class="badge fs-6 bg-' + item.type + '">' + item.type + '</span>';
  872. });
  873. } else if (table == 'sasl_log_table') {
  874. $.each(data, function (i, item) {
  875. if (item === null) { return true; }
  876. item.username = escapeHtml(item.username);
  877. item.service = '<div class="badge fs-6 bg-secondary">' + item.service.toUpperCase() + '</div>';
  878. });
  879. } else if (table == 'general_syslog') {
  880. $.each(data, function (i, item) {
  881. if (item === null) { return true; }
  882. if (item.message.match("^base64,")) {
  883. try {
  884. item.message = atob(item.message.slice(7)).replace(/\\n/g, "<br />");
  885. } catch(e) {
  886. item.message = item.message.slice(7);
  887. }
  888. } else {
  889. item.message = escapeHtml(item.message);
  890. }
  891. item.call = escapeHtml(item.call);
  892. var danger_class = ["emerg", "alert", "crit", "err"];
  893. var warning_class = ["warning", "warn"];
  894. var info_class = ["notice", "info", "debug"];
  895. if (jQuery.inArray(item.priority, danger_class) !== -1) {
  896. item.priority = '<span class="badge fs-6 bg-danger">' + item.priority + '</span>';
  897. } else if (jQuery.inArray(item.priority, warning_class) !== -1) {
  898. item.priority = '<span class="badge fs-6 bg-warning">' + item.priority + '</span>';
  899. } else if (jQuery.inArray(item.priority, info_class) !== -1) {
  900. item.priority = '<span class="badge fs-6 bg-info">' + item.priority + '</span>';
  901. }
  902. });
  903. } else if (table == 'apilog') {
  904. $.each(data, function (i, item) {
  905. if (item === null) { return true; }
  906. if (item.method == 'GET') {
  907. item.method = '<span class="badge fs-6 bg-success">' + item.method + '</span>';
  908. } else if (item.method == 'POST') {
  909. item.method = '<span class="badge fs-6 bg-warning">' + item.method + '</span>';
  910. }
  911. item.data = escapeHtml(item.data);
  912. });
  913. } else if (table == 'rllog') {
  914. $.each(data, function (i, item) {
  915. if (item.user == null) {
  916. item.user = "none";
  917. }
  918. if (item.rl_hash == null) {
  919. item.rl_hash = "err";
  920. }
  921. item.indicator = '<span style="border-right:6px solid #' + intToRGB(hashCode(item.rl_hash)) + ';padding-left:5px;">&nbsp;</span>';
  922. if (item.rl_hash != 'err') {
  923. item.action = '<a href="#" data-action="delete_selected" data-id="single-hash" data-api-url="delete/rlhash" data-item="' + encodeURI(item.rl_hash) + '" class="btn btn-xs btn-danger"><i class="bi bi-trash"></i> ' + lang.reset_limit + '</a>';
  924. }
  925. });
  926. }
  927. return data
  928. };
  929. $('.add_log_lines').on('click', function (e) {
  930. e.preventDefault();
  931. var log_table= $(this).data("table")
  932. var new_nrows = $(this).data("nrows")
  933. var post_process = $(this).data("post-process")
  934. var log_url = $(this).data("log-url")
  935. if (log_table === undefined || new_nrows === undefined || post_process === undefined || log_url === undefined) {
  936. console.log("no data-table or data-nrows or log_url or data-post-process attr found");
  937. return;
  938. }
  939. // BUG TODO: loading 100 results in loading 10 - loading 1000 results in loading 100
  940. if (table = $('#' + log_table).DataTable()) {
  941. var heading = $('#' + log_table).closest('.card').find('.card-header');
  942. var load_rows = (table.page.len() + 1) + '-' + (table.page.len() + new_nrows)
  943. $.get('/api/v1/get/logs/' + log_url + '/' + load_rows).then(function(data){
  944. if (data.length === undefined) { mailcow_alert_box(lang.no_new_rows, "info"); return; }
  945. var rows = process_table_data(data, post_process);
  946. var rows_now = (table.page.len() + data.length);
  947. $(heading).children('.table-lines').text(rows_now)
  948. mailcow_alert_box(data.length + lang.additional_rows, "success");
  949. table.rows.add(rows).draw();
  950. });
  951. }
  952. })
  953. // detect element visibility changes
  954. function onVisible(element, callback) {
  955. $(document).ready(function() {
  956. element_object = document.querySelector(element);
  957. if (element_object === null) return;
  958. new IntersectionObserver((entries, observer) => {
  959. entries.forEach(entry => {
  960. if(entry.intersectionRatio > 0) {
  961. callback(element_object);
  962. }
  963. });
  964. }).observe(element_object);
  965. });
  966. }
  967. // Draw Table if tab is active
  968. onVisible("[id^=postfix_log]", () => draw_postfix_logs());
  969. onVisible("[id^=dovecot_log]", () => draw_dovecot_logs());
  970. onVisible("[id^=sogo_log]", () => draw_sogo_logs());
  971. onVisible("[id^=watchdog_log]", () => draw_watchdog_logs());
  972. onVisible("[id^=autodiscover_log]", () => draw_autodiscover_logs());
  973. onVisible("[id^=acme_log]", () => draw_acme_logs());
  974. onVisible("[id^=api_log]", () => draw_api_logs());
  975. onVisible("[id^=rl_log]", () => draw_rl_logs());
  976. onVisible("[id^=ui_logs]", () => draw_ui_logs());
  977. onVisible("[id^=sasl_logs]", () => draw_sasl_logs());
  978. onVisible("[id^=netfilter_log]", () => draw_netfilter_logs());
  979. onVisible("[id^=rspamd_history]", () => draw_rspamd_history());
  980. onVisible("[id^=rspamd_donut]", () => rspamd_pie_graph());
  981. });