debug.js 28 KB

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