debug.js 28 KB

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