public
nobgit
read
NobMail
Based on mailcow: dockerized
Languages
Repository composition by tracked source files.
PHP
49%
JavaScript
35%
HTML
9%
CSS
4%
Shell
2%
Python
1%
Lua
0%
Perl
0%
Ruby
0%
SCSS
0%
Create file
Wiki Documentation
Clone
https://nobgit.com/orgs/nobgit/nobmail.git
ssh://[email protected]:2222/orgs/nobgit/nobmail.git
Commit
[Web] Set pageLength to pagination_size + repect savedState... Fix width in quarantine table.
6ff3f3f0
data/web/css/site/quarantine.css | 206 +--
data/web/js/site/admin.js | 1468 +++++++++----------
data/web/js/site/debug.js | 146 +-
data/web/js/site/edit.js | 442 +++---
data/web/js/site/mailbox.js | 1740 ++++++++++++-----------
data/web/js/site/qhandler.js | 142 +-
data/web/js/site/quarantine.js | 583 ++++----
data/web/js/site/queue.js | 215 +--
data/web/js/site/user.js | 1329 ++++++++---------
data/web/templates/admin.twig | 6 +-
data/web/templates/debug.twig | 40 +-
data/web/templates/domainadmin.twig | 2 +-
data/web/templates/edit.twig | 2 +-
data/web/templates/mailbox.twig | 2 +-
data/web/templates/quarantine.twig | 4 +-
data/web/templates/queue.twig | 2 +-
data/web/templates/user_domainadmin_common.twig | 2 +-
17 files changed, 3190 insertions(+), 3141 deletions(-)
Diff
diff --git a/data/web/css/site/quarantine.css b/data/web/css/site/quarantine.css
index 98a74d66..0455b7c1 100644
--- a/data/web/css/site/quarantine.css
+++ b/data/web/css/site/quarantine.css
@@ -1,102 +1,104 @@
-.pagination a {
- text-decoration: none !important;
-}
-
-.panel.panel-default {
- overflow: visible !important;
-}
-
-.table-responsive {
- overflow: visible !important;
-}
-
-.table-responsive {
- overflow-x: scroll !important;
-}
-
-.footer-add-item {
- display: block;
- text-align: center;
- font-style: italic;
- padding: 10px;
- background: #F5F5F5;
-}
-
-@media (min-width: 992px) {
- .container {
- width: 100%;
- }
-}
-@media (min-width: 1920px) {
- .container {
- width: 80%;
- }
-}
-
-.mass-actions-quarantine {
- user-select: none;
-}
-
-.inputMissingAttr {
- border-color: #FF4136;
-}
-
-.modal#qidDetailModal p {
- word-break: break-all;
-}
-
-span#qid_detail_score {
- font-weight: 700;
- margin-left: 5px;
-}
-
-span.rspamd-symbol {
- display: inline-block;
- margin: 2px 6px 2px 0;
- border-radius: 4px;
- padding: 0 7px;
-}
-
-span.rspamd-symbol.positive {
- background: #4CAF50;
- border: 1px solid #4CAF50;
- color: white;
-}
-
-span.rspamd-symbol.negative {
- background: #ff4136;
- border: 1px solid #ff4136;
- color: white;
-}
-
-span.rspamd-symbol.neutral {
- background: #f5f5f5;
- color: #333;
- border: 1px solid #ccc;
-}
-
-span.rspamd-symbol span.score {
- font-weight: 700;
-}
-
-span.mail-address-item {
- background-color: #f5f5f5;
- border-radius: 4px;
- border: 1px solid #ccc;
- padding: 2px 7px;
- display: inline-block;
- margin: 2px 6px 2px 0;
-}
-
-table tbody tr {
- cursor: pointer;
-}
-
-table tbody tr td input[type="checkbox"] {
- cursor: pointer;
-}
-.label-rspamd-action {
- font-size:110%;
- margin:20px;
-}
-
+.pagination a {
+ text-decoration: none !important;
+}
+
+.panel.panel-default {
+ overflow: visible !important;
+}
+
+.table-responsive {
+ overflow: visible !important;
+}
+
+.table-responsive {
+ overflow-x: scroll !important;
+}
+
+.footer-add-item {
+ display: block;
+ text-align: center;
+ font-style: italic;
+ padding: 10px;
+ background: #F5F5F5;
+}
+
+@media (min-width: 992px) {
+ .container {
+ width: 100%;
+ }
+}
+@media (min-width: 1920px) {
+ .container {
+ width: 80%;
+ }
+}
+
+.mass-actions-quarantine {
+ user-select: none;
+}
+
+.inputMissingAttr {
+ border-color: #FF4136;
+}
+
+.modal#qidDetailModal p {
+ word-break: break-all;
+}
+
+span#qid_detail_score {
+ font-weight: 700;
+ margin-left: 5px;
+}
+
+span.rspamd-symbol {
+ display: inline-block;
+ margin: 2px 6px 2px 0;
+ border-radius: 4px;
+ padding: 0 7px;
+}
+
+span.rspamd-symbol.positive {
+ background: #4CAF50;
+ border: 1px solid #4CAF50;
+ color: white;
+}
+
+span.rspamd-symbol.negative {
+ background: #ff4136;
+ border: 1px solid #ff4136;
+ color: white;
+}
+
+span.rspamd-symbol.neutral {
+ background: #f5f5f5;
+ color: #333;
+ border: 1px solid #ccc;
+}
+
+span.rspamd-symbol span.score {
+ font-weight: 700;
+}
+
+span.mail-address-item {
+ background-color: #f5f5f5;
+ border-radius: 4px;
+ border: 1px solid #ccc;
+ padding: 2px 7px;
+ display: inline-block;
+ margin: 2px 6px 2px 0;
+}
+
+table tbody tr {
+ cursor: pointer;
+}
+
+table tbody tr td input[type="checkbox"] {
+ cursor: pointer;
+}
+.label-rspamd-action {
+ font-size:110%;
+ margin:20px;
+}
+.senders-mw220 {
+ max-width: 220px;
+}
diff --git a/data/web/js/site/admin.js b/data/web/js/site/admin.js
index 0dba1aa8..0e5a9ae6 100644
--- a/data/web/js/site/admin.js
+++ b/data/web/js/site/admin.js
@@ -1,731 +1,737 @@
-// Base64 functions
-var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(r){var t,e,o,a,h,n,c,d="",C=0;for(r=Base64._utf8_encode(r);C<r.length;)a=(t=r.charCodeAt(C++))>>2,h=(3&t)<<4|(e=r.charCodeAt(C++))>>4,n=(15&e)<<2|(o=r.charCodeAt(C++))>>6,c=63&o,isNaN(e)?n=c=64:isNaN(o)&&(c=64),d=d+this._keyStr.charAt(a)+this._keyStr.charAt(h)+this._keyStr.charAt(n)+this._keyStr.charAt(c);return d},decode:function(r){var t,e,o,a,h,n,c="",d=0;for(r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");d<r.length;)t=this._keyStr.indexOf(r.charAt(d++))<<2|(a=this._keyStr.indexOf(r.charAt(d++)))>>4,e=(15&a)<<4|(h=this._keyStr.indexOf(r.charAt(d++)))>>2,o=(3&h)<<6|(n=this._keyStr.indexOf(r.charAt(d++))),c+=String.fromCharCode(t),64!=h&&(c+=String.fromCharCode(e)),64!=n&&(c+=String.fromCharCode(o));return c=Base64._utf8_decode(c)},_utf8_encode:function(r){r=r.replace(/\r\n/g,"\n");for(var t="",e=0;e<r.length;e++){var o=r.charCodeAt(e);o<128?t+=String.fromCharCode(o):o>127&&o<2048?(t+=String.fromCharCode(o>>6|192),t+=String.fromCharCode(63&o|128)):(t+=String.fromCharCode(o>>12|224),t+=String.fromCharCode(o>>6&63|128),t+=String.fromCharCode(63&o|128))}return t},_utf8_decode:function(r){for(var t="",e=0,o=c1=c2=0;e<r.length;)(o=r.charCodeAt(e))<128?(t+=String.fromCharCode(o),e++):o>191&&o<224?(c2=r.charCodeAt(e+1),t+=String.fromCharCode((31&o)<<6|63&c2),e+=2):(c2=r.charCodeAt(e+1),c3=r.charCodeAt(e+2),t+=String.fromCharCode((15&o)<<12|(63&c2)<<6|63&c3),e+=3);return t}};
-jQuery(function($){
- // http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
- var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};
- function jq(myid) {return "#" + myid.replace( /(:|\.|\[|\]|,|=|@)/g, "\\$1" );}
- function escapeHtml(n){return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})}
- function validateRegex(e){var t=e.split("/"),n=e,r="";t.length>1&&(n=t[1],r=t[2]);try{return new RegExp(n,r),!0}catch(e){return!1}}
- 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]}
- function hashCode(t){for(var n=0,r=0;r<t.length;r++)n=t.charCodeAt(r)+((n<<5)-n);return n}
- function intToRGB(t){var n=(16777215&t).toString(16).toUpperCase();return"00000".substring(0,6-n.length)+n}
- $("#dkim_missing_keys").on('click', function(e) {
- e.preventDefault();
- var domains = [];
- $('.dkim_missing').each(function() {
- domains.push($(this).val());
- });
- $('#dkim_add_domains').val(domains);
- });
- $(".arrow-toggle").on('click', function(e) { e.preventDefault(); $(this).find('.arrow').toggleClass("animation"); });
- $("#mass_exclude").change(function(){ $("#mass_include").selectpicker('deselectAll'); });
- $("#mass_include").change(function(){ $("#mass_exclude").selectpicker('deselectAll'); });
- $("#mass_disarm").click(function() { $("#mass_send").attr("disabled", !this.checked); });
- $(".admin-ays-dialog").click(function() { return confirm(lang.ays); });
- $(".validate_rspamd_regex").click(function( event ) {
- event.preventDefault();
- var regex_map_id = $(this).data('regex-map');
- var regex_data = $(jq(regex_map_id)).val().split(/\r?\n/);
- var regex_valid = true;
- for(var i = 0;i < regex_data.length;i++){
- if(regex_data[i].startsWith('#') || !regex_data[i]){
- continue;
- }
- if(!validateRegex(regex_data[i])) {
- mailcow_alert_box('Cannot build regex from line ' + (i+1), 'danger');
- var regex_valid = false;
- break;
- }
- if(!regex_data[i].startsWith('/') || !/\/[ims]?$/.test(regex_data[i])){
- mailcow_alert_box('Line ' + (i+1) + ' is invalid', 'danger');
- var regex_valid = false;
- break;
- }
- }
- if (regex_valid) {
- mailcow_alert_box('Regex OK', 'success');
- $('button[data-id="' + regex_map_id + '"]').attr({"disabled": false});
- }
- });
- $('.textarea-code').on('keyup', function() {
- $('.submit_rspamd_regex').attr({"disabled": true});
- });
- $("#show_rspamd_global_filters").click(function() {
- $.get("inc/ajax/show_rspamd_global_filters.php");
- $("#confirm_show_rspamd_global_filters").hide();
- $("#rspamd_global_filters").removeClass("d-none");
- });
- $("#super_delete").click(function() { return confirm(lang.queue_ays); });
-
- $(".refresh_table").on('click', function(e) {
- e.preventDefault();
- var table_name = $(this).data('table');
- $('#' + table_name).DataTable().ajax.reload();
- });
- function draw_domain_admins() {
- // just recalc width if instance already exists
- if ($.fn.DataTable.isDataTable('#domainadminstable') ) {
- $('#domainadminstable').DataTable().columns.adjust().responsive.recalc();
- return;
- }
-
- $('#domainadminstable').DataTable({
- responsive: true,
- processing: true,
- serverSide: false,
- stateSave: true,
- dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
- "tr" +
- "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
- language: lang_datatables,
- ajax: {
- type: "GET",
- url: "/api/v1/get/domain-admin/all",
- dataSrc: function(data){
- return process_table_data(data, 'domainadminstable');
- }
- },
- columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: lang.username,
- data: 'username',
- defaultContent: ''
- },
- {
- title: lang.admin_domains,
- data: 'selected_domains',
- defaultContent: '',
- },
- {
- title: "TFA",
- data: 'tfa_active',
- defaultContent: '',
- render: function (data, type) {
- if(data == 1) return '<i class="bi bi-check-lg"></i>';
- else return '<i class="bi bi-x-lg"></i>'
- }
- },
- {
- title: lang.active,
- data: 'active',
- defaultContent: '',
- render: function (data, type) {
- if(data == 1) return '<i class="bi bi-check-lg"></i>';
- else return '<i class="bi bi-x-lg"></i>'
- }
- },
- {
- title: lang.action,
- data: 'action',
- className: 'text-md-end dt-sm-head-hidden dt-body-right',
- defaultContent: ''
- },
- ],
- initComplete: function(settings, json){
- }
- });
- }
- function draw_oauth2_clients() {
- // just recalc width if instance already exists
- if ($.fn.DataTable.isDataTable('#oauth2clientstable') ) {
- $('#oauth2clientstable').DataTable().columns.adjust().responsive.recalc();
- return;
- }
-
- $('#oauth2clientstable').DataTable({
- responsive: true,
- processing: true,
- serverSide: false,
- stateSave: true,
- dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
- "tr" +
- "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
- language: lang_datatables,
- ajax: {
- type: "GET",
- url: "/api/v1/get/oauth2-client/all",
- dataSrc: function(data){
- return process_table_data(data, 'oauth2clientstable');
- }
- },
- columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: 'ID',
- data: 'id',
- defaultContent: ''
- },
- {
- title: lang.oauth2_client_id,
- data: 'client_id',
- defaultContent: ''
- },
- {
- title: lang.oauth2_client_secret,
- data: 'client_secret',
- defaultContent: ''
- },
- {
- title: lang.oauth2_redirect_uri,
- data: 'redirect_uri',
- defaultContent: ''
- },
- {
- title: lang.action,
- data: 'action',
- className: 'text-md-end dt-sm-head-hidden dt-body-right',
- defaultContent: ''
- },
- ]
- });
- }
- function draw_admins() {
- // just recalc width if instance already exists
- if ($.fn.DataTable.isDataTable('#adminstable') ) {
- $('#adminstable').DataTable().columns.adjust().responsive.recalc();
- return;
- }
-
- $('#adminstable').DataTable({
- responsive: true,
- processing: true,
- serverSide: false,
- stateSave: true,
- dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
- "tr" +
- "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
- language: lang_datatables,
- ajax: {
- type: "GET",
- url: "/api/v1/get/admin/all",
- dataSrc: function(data){
- return process_table_data(data, 'adminstable');
- }
- },
- columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: lang.username,
- data: 'username',
- defaultContent: ''
- },
- {
- title: "TFA",
- data: 'tfa_active',
- defaultContent: '',
- render: function (data, type) {
- if(data == 1) return '<i class="bi bi-check-lg"></i>';
- else return '<i class="bi bi-x-lg"></i>'
- }
- },
- {
- title: lang.active,
- data: 'active',
- defaultContent: '',
- render: function (data, type) {
- if(data == 1) return '<i class="bi bi-check-lg"></i>';
- else return '<i class="bi bi-x-lg"></i>'
- }
- },
- {
- title: lang.action,
- data: 'action',
- defaultContent: '',
- className: 'text-md-end dt-sm-head-hidden dt-body-right'
- },
- ]
- });
- }
- function draw_fwd_hosts() {
- // just recalc width if instance already exists
- if ($.fn.DataTable.isDataTable('#forwardinghoststable') ) {
- $('#forwardinghoststable').DataTable().columns.adjust().responsive.recalc();
- return;
- }
-
- $('#forwardinghoststable').DataTable({
- responsive: true,
- processing: true,
- serverSide: false,
- stateSave: true,
- dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
- "tr" +
- "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
- language: lang_datatables,
- ajax: {
- type: "GET",
- url: "/api/v1/get/fwdhost/all",
- dataSrc: function(data){
- return process_table_data(data, 'forwardinghoststable');
- }
- },
- columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: lang.host,
- data: 'host',
- defaultContent: ''
- },
- {
- title: lang.source,
- data: 'source',
- defaultContent: ''
- },
- {
- title: lang.spamfilter,
- data: 'keep_spam',
- defaultContent: '',
- render: function(data, type){
- return 'yes'==data?'<i class="bi bi-x-lg"></i>':'no'==data&&'<i class="bi bi-check-lg"></i>';
- }
- },
- {
- title: lang.action,
- data: 'action',
- className: 'text-md-end dt-sm-head-hidden dt-body-right',
- defaultContent: ''
- },
- ]
- });
- }
- function draw_relayhosts() {
- // just recalc width if instance already exists
- if ($.fn.DataTable.isDataTable('#relayhoststable') ) {
- $('#relayhoststable').DataTable().columns.adjust().responsive.recalc();
- return;
- }
-
- $('#relayhoststable').DataTable({
- responsive: true,
- processing: true,
- serverSide: false,
- stateSave: true,
- dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
- "tr" +
- "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
- language: lang_datatables,
- ajax: {
- type: "GET",
- url: "/api/v1/get/relayhost/all",
- dataSrc: function(data){
- return process_table_data(data, 'relayhoststable');
- }
- },
- columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: 'ID',
- data: 'id',
- defaultContent: ''
- },
- {
- title: lang.host,
- data: 'hostname',
- defaultContent: ''
- },
- {
- title: lang.username,
- data: 'username',
- defaultContent: ''
- },
- {
- title: lang.in_use_by,
- data: 'in_use_by',
- defaultContent: ''
- },
- {
- title: lang.active,
- data: 'active',
- defaultContent: '',
- render: function (data, type) {
- if(data == 1) return '<i class="bi bi-check-lg"></i>';
- else return '<i class="bi bi-x-lg"></i>'
- }
- },
- {
- title: lang.action,
- data: 'action',
- className: 'text-md-end dt-sm-head-hidden dt-body-right',
- defaultContent: ''
- },
- ]
- });
- }
- function draw_transport_maps() {
- // just recalc width if instance already exists
- if ($.fn.DataTable.isDataTable('#transportstable') ) {
- $('#transportstable').DataTable().columns.adjust().responsive.recalc();
- return;
- }
-
- $('#transportstable').DataTable({
- responsive: true,
- processing: true,
- serverSide: false,
- stateSave: true,
- dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
- "tr" +
- "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
- language: lang_datatables,
- ajax: {
- type: "GET",
- url: "/api/v1/get/transport/all",
- dataSrc: function(data){
- return process_table_data(data, 'transportstable');
- }
- },
- columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: 'ID',
- data: 'id',
- defaultContent: ''
- },
- {
- title: lang.destination,
- data: 'destination',
- defaultContent: ''
- },
- {
- title: lang.nexthop,
- data: 'nexthop',
- defaultContent: ''
- },
- {
- title: lang.username,
- data: 'username',
- defaultContent: ''
- },
- {
- title: lang.active,
- data: 'active',
- defaultContent: '',
- render: function (data, type) {
- if(data == 1) return '<i class="bi bi-check-lg"></i>';
- else return '<i class="bi bi-x-lg"></i>'
- }
- },
- {
- title: lang.action,
- data: 'action',
- className: 'text-md-end dt-sm-head-hidden dt-body-right',
- defaultContent: ''
- },
- ]
- });
- }
-
- function process_table_data(data, table) {
- if (table == 'relayhoststable') {
- $.each(data, function (i, item) {
- item.action = '<div class="btn-group">' +
- '<a href="#" data-bs-toggle="modal" data-bs-target="#testTransportModal" data-transport-id="' + encodeURI(item.id) + '" data-transport-type="sender-dependent" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-caret-right-fill"></i> Test</a>' +
- '<a href="/edit/relayhost/' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
- '<a href="#" data-action="delete_selected" data-id="single-rlyhost" data-api-url="delete/relayhost" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
- '</div>';
- if (item.used_by_mailboxes == '') { item.in_use_by = item.used_by_domains; }
- else if (item.used_by_domains == '') { item.in_use_by = item.used_by_mailboxes; }
- else { item.in_use_by = item.used_by_mailboxes + '<hr style="margin:5px 0px 5px 0px;">' + item.used_by_domains; }
- item.chkbox = '<input type="checkbox" data-id="rlyhosts" name="multi_select" value="' + item.id + '" />';
- });
- } else if (table == 'transportstable') {
- $.each(data, function (i, item) {
- if (item.is_mx_based) {
- item.destination = '<i class="bi bi-info-circle-fill text-info mx-info" data-bs-toggle="tooltip" title="' + lang.is_mx_based + '"></i> <code>' + item.destination + '</code>';
- }
- if (item.username) {
- item.username = '<i style="color:#' + intToRGB(hashCode(item.nexthop)) + ';" class="bi bi-square-fill"></i> ' + item.username;
- }
- item.action = '<div class="btn-group">' +
- '<a href="#" data-bs-toggle="modal" data-bs-target="#testTransportModal" data-transport-id="' + encodeURI(item.id) + '" data-transport-type="transport-map" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-caret-right-fill"></i> Test</a>' +
- '<a href="/edit/transport/' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
- '<a href="#" data-action="delete_selected" data-id="single-transport" data-api-url="delete/transport" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
- '</div>';
- item.chkbox = '<input type="checkbox" data-id="transports" name="multi_select" value="' + item.id + '" />';
- });
- } else if (table == 'queuetable') {
- $.each(data, function (i, item) {
- item.chkbox = '<input type="checkbox" data-id="mailqitems" name="multi_select" value="' + item.queue_id + '" />';
- rcpts = $.map(item.recipients, function(i) {
- return escapeHtml(i);
- });
- item.recipients = rcpts.join('<hr style="margin:1px!important">');
- item.action = '<div class="btn-group">' +
- '<a href="#" data-bs-toggle="modal" data-bs-target="#showQueuedMsg" data-queue-id="' + encodeURI(item.queue_id) + '" class="btn btn-xs btn-secondary">' + lang.queue_show_message + '</a>' +
- '</div>';
- });
- } else if (table == 'forwardinghoststable') {
- $.each(data, function (i, item) {
- item.action = '<div class="btn-group">' +
- '<a href="#" data-action="delete_selected" data-id="single-fwdhost" data-api-url="delete/fwdhost" data-item="' + encodeURI(item.host) + '" class="btn btn-xs btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
- '</div>';
- item.chkbox = '<input type="checkbox" data-id="fwdhosts" name="multi_select" value="' + item.host + '" />';
- });
- } else if (table == 'oauth2clientstable') {
- $.each(data, function (i, item) {
- item.action = '<div class="btn-group">' +
- '<a href="/edit.php?oauth2client=' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
- '<a href="#" data-action="delete_selected" data-id="single-oauth2-client" data-api-url="delete/oauth2-client" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
- '</div>';
- item.scope = "profile";
- item.grant_types = 'refresh_token password authorization_code';
- item.chkbox = '<input type="checkbox" data-id="oauth2_clients" name="multi_select" value="' + item.id + '" />';
- });
- } else if (table == 'domainadminstable') {
- $.each(data, function (i, item) {
- item.selected_domains = escapeHtml(item.selected_domains);
- item.selected_domains = item.selected_domains.toString().replace(/,/g, "<br>");
- item.chkbox = '<input type="checkbox" data-id="domain_admins" name="multi_select" value="' + item.username + '" />';
- item.action = '<div class="btn-group">' +
- '<a href="/edit/domainadmin/' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
- '<a href="#" data-action="delete_selected" data-id="single-domain-admin" data-api-url="delete/domain-admin" data-item="' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
- '<a href="/index.php?duallogin=' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-xs-third btn-success"><i class="bi bi-person-fill"></i> Login</a>' +
- '</div>';
- });
- } else if (table == 'adminstable') {
- $.each(data, function (i, item) {
- if (admin_username.toLowerCase() == item.username.toLowerCase()) {
- item.usr = '<i class="bi bi-person-check"></i> ' + item.username;
- } else {
- item.usr = item.username;
- }
- item.chkbox = '<input type="checkbox" data-id="admins" name="multi_select" value="' + item.username + '" />';
- item.action = '<div class="btn-group">' +
- '<a href="/edit/admin/' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
- '<a href="#" data-action="delete_selected" data-id="single-admin" data-api-url="delete/admin" data-item="' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
- '</div>';
- });
- }
- return data
- };
-
- // detect element visibility changes
- function onVisible(element, callback) {
- $(document).ready(function() {
- element_object = document.querySelector(element);
- if (element_object === null) return;
-
- new IntersectionObserver((entries, observer) => {
- entries.forEach(entry => {
- if(entry.intersectionRatio > 0) {
- callback(element_object);
- }
- });
- }).observe(element_object);
- });
- }
- // Draw Table if tab is active
- onVisible("[id^=adminstable]", () => draw_admins());
- onVisible("[id^=domainadminstable]", () => draw_domain_admins());
- onVisible("[id^=oauth2clientstable]", () => draw_oauth2_clients());
- onVisible("[id^=forwardinghoststable]", () => draw_fwd_hosts());
- onVisible("[id^=relayhoststable]", () => draw_relayhosts());
- onVisible("[id^=transportstable]", () => draw_transport_maps());
-
-
- $('body').on('click', 'span.footable-toggle', function () {
- event.stopPropagation();
- })
-
- // API IP check toggle
- $("#skip_ip_check_ro").click(function( event ) {
- $("#skip_ip_check_ro").not(this).prop('checked', false);
- if ($("#skip_ip_check_ro:checked").length > 0) {
- $('#allow_from_ro').prop('disabled', true);
- }
- else {
- $("#allow_from_ro").removeAttr('disabled');
- }
- });
- $("#skip_ip_check_rw").click(function( event ) {
- $("#skip_ip_check_rw").not(this).prop('checked', false);
- if ($("#skip_ip_check_rw:checked").length > 0) {
- $('#allow_from_rw').prop('disabled', true);
- }
- else {
- $("#allow_from_rw").removeAttr('disabled');
- }
- });
- // Relayhost
- $('#testRelayhostModal').on('show.bs.modal', function (e) {
- $('#test_relayhost_result').text("-");
- button = $(e.relatedTarget)
- if (button != null) {
- $('#relayhost_id').val(button.data('relayhost-id'));
- }
- })
- $('#test_relayhost').on('click', function (e) {
- e.preventDefault();
- prev = $('#test_relayhost').text();
- $(this).prop("disabled",true);
- $(this).html('<i class="bi bi-arrow-repeat icon-spin"></i> ');
- $.ajax({
- type: 'GET',
- url: 'inc/ajax/relay_check.php',
- dataType: 'text',
- data: $('#test_relayhost_form').serialize(),
- complete: function (data) {
- $('#test_relayhost_result').html(data.responseText);
- $('#test_relayhost').prop("disabled",false);
- $('#test_relayhost').text(prev);
- }
- });
- })
- // Transport
- $('#testTransportModal').on('show.bs.modal', function (e) {
- $('#test_transport_result').text("-");
- button = $(e.relatedTarget)
- if (button != null) {
- $('#transport_id').val(button.data('transport-id'));
- $('#transport_type').val(button.data('transport-type'));
- }
- })
- $('#test_transport').on('click', function (e) {
- e.preventDefault();
- prev = $('#test_transport').text();
- $(this).prop("disabled",true);
- $(this).html('<div class="spinner-border" role="status"><span class="visually-hidden">Loading...</span></div> ');
- $.ajax({
- type: 'GET',
- url: 'inc/ajax/transport_check.php',
- dataType: 'text',
- data: $('#test_transport_form').serialize(),
- complete: function (data) {
- $('#test_transport_result').html(data.responseText);
- $('#test_transport').prop("disabled",false);
- $('#test_transport').text(prev);
- }
- });
- })
- // DKIM private key modal
- $('#showDKIMprivKey').on('show.bs.modal', function (e) {
- $('#priv_key_pre').text("-");
- p_related = $(e.relatedTarget)
- if (p_related != null) {
- var decoded_key = Base64.decode((p_related.data('priv-key')));
- $('#priv_key_pre').text(decoded_key);
- }
- })
- // FIDO2 friendly name modal
- $('#fido2ChangeFn').on('show.bs.modal', function (e) {
- rename_link = $(e.relatedTarget)
- if (rename_link != null) {
- $('#fido2_cid').val(rename_link.data('cid'));
- $('#fido2_subject_desc').text(Base64.decode(rename_link.data('subject')));
- }
- })
- // App links
- function add_table_row(table_id, type) {
- var row = $('<tr />');
- if (type == "app_link") {
- cols = '<td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="app" required></td>';
- cols += '<td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="href" required></td>';
- cols += '<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-secondary h-100 w-100" type="button">' + lang.remove_row + '</a></td>';
- } else if (type == "f2b_regex") {
- cols = '<td><input style="text-align:center" class="input-sm input-xs-lg form-control" data-id="f2b_regex" type="text" value="+" disabled></td>';
- cols += '<td><input class="input-sm input-xs-lg form-control regex-input" data-id="f2b_regex" type="text" name="regex" required></td>';
- cols += '<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-secondary h-100 w-100" type="button">' + lang.remove_row + '</a></td>';
- }
- row.append(cols);
- table_id.append(row);
- }
- $('#app_link_table').on('click', 'tr a', function (e) {
- e.preventDefault();
- $(this).parents('tr').remove();
- });
- $('#f2b_regex_table').on('click', 'tr a', function (e) {
- e.preventDefault();
- $(this).parents('tr').remove();
- });
- $('#add_app_link_row').click(function() {
- add_table_row($('#app_link_table'), "app_link");
- });
- $('#add_f2b_regex_row').click(function() {
- add_table_row($('#f2b_regex_table'), "f2b_regex");
- });
-});
+// Base64 functions
+var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(r){var t,e,o,a,h,n,c,d="",C=0;for(r=Base64._utf8_encode(r);C<r.length;)a=(t=r.charCodeAt(C++))>>2,h=(3&t)<<4|(e=r.charCodeAt(C++))>>4,n=(15&e)<<2|(o=r.charCodeAt(C++))>>6,c=63&o,isNaN(e)?n=c=64:isNaN(o)&&(c=64),d=d+this._keyStr.charAt(a)+this._keyStr.charAt(h)+this._keyStr.charAt(n)+this._keyStr.charAt(c);return d},decode:function(r){var t,e,o,a,h,n,c="",d=0;for(r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");d<r.length;)t=this._keyStr.indexOf(r.charAt(d++))<<2|(a=this._keyStr.indexOf(r.charAt(d++)))>>4,e=(15&a)<<4|(h=this._keyStr.indexOf(r.charAt(d++)))>>2,o=(3&h)<<6|(n=this._keyStr.indexOf(r.charAt(d++))),c+=String.fromCharCode(t),64!=h&&(c+=String.fromCharCode(e)),64!=n&&(c+=String.fromCharCode(o));return c=Base64._utf8_decode(c)},_utf8_encode:function(r){r=r.replace(/\r\n/g,"\n");for(var t="",e=0;e<r.length;e++){var o=r.charCodeAt(e);o<128?t+=String.fromCharCode(o):o>127&&o<2048?(t+=String.fromCharCode(o>>6|192),t+=String.fromCharCode(63&o|128)):(t+=String.fromCharCode(o>>12|224),t+=String.fromCharCode(o>>6&63|128),t+=String.fromCharCode(63&o|128))}return t},_utf8_decode:function(r){for(var t="",e=0,o=c1=c2=0;e<r.length;)(o=r.charCodeAt(e))<128?(t+=String.fromCharCode(o),e++):o>191&&o<224?(c2=r.charCodeAt(e+1),t+=String.fromCharCode((31&o)<<6|63&c2),e+=2):(c2=r.charCodeAt(e+1),c3=r.charCodeAt(e+2),t+=String.fromCharCode((15&o)<<12|(63&c2)<<6|63&c3),e+=3);return t}};
+jQuery(function($){
+ // http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
+ var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};
+ function jq(myid) {return "#" + myid.replace( /(:|\.|\[|\]|,|=|@)/g, "\\$1" );}
+ function escapeHtml(n){return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})}
+ function validateRegex(e){var t=e.split("/"),n=e,r="";t.length>1&&(n=t[1],r=t[2]);try{return new RegExp(n,r),!0}catch(e){return!1}}
+ 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]}
+ function hashCode(t){for(var n=0,r=0;r<t.length;r++)n=t.charCodeAt(r)+((n<<5)-n);return n}
+ function intToRGB(t){var n=(16777215&t).toString(16).toUpperCase();return"00000".substring(0,6-n.length)+n}
+ $("#dkim_missing_keys").on('click', function(e) {
+ e.preventDefault();
+ var domains = [];
+ $('.dkim_missing').each(function() {
+ domains.push($(this).val());
+ });
+ $('#dkim_add_domains').val(domains);
+ });
+ $(".arrow-toggle").on('click', function(e) { e.preventDefault(); $(this).find('.arrow').toggleClass("animation"); });
+ $("#mass_exclude").change(function(){ $("#mass_include").selectpicker('deselectAll'); });
+ $("#mass_include").change(function(){ $("#mass_exclude").selectpicker('deselectAll'); });
+ $("#mass_disarm").click(function() { $("#mass_send").attr("disabled", !this.checked); });
+ $(".admin-ays-dialog").click(function() { return confirm(lang.ays); });
+ $(".validate_rspamd_regex").click(function( event ) {
+ event.preventDefault();
+ var regex_map_id = $(this).data('regex-map');
+ var regex_data = $(jq(regex_map_id)).val().split(/\r?\n/);
+ var regex_valid = true;
+ for(var i = 0;i < regex_data.length;i++){
+ if(regex_data[i].startsWith('#') || !regex_data[i]){
+ continue;
+ }
+ if(!validateRegex(regex_data[i])) {
+ mailcow_alert_box('Cannot build regex from line ' + (i+1), 'danger');
+ var regex_valid = false;
+ break;
+ }
+ if(!regex_data[i].startsWith('/') || !/\/[ims]?$/.test(regex_data[i])){
+ mailcow_alert_box('Line ' + (i+1) + ' is invalid', 'danger');
+ var regex_valid = false;
+ break;
+ }
+ }
+ if (regex_valid) {
+ mailcow_alert_box('Regex OK', 'success');
+ $('button[data-id="' + regex_map_id + '"]').attr({"disabled": false});
+ }
+ });
+ $('.textarea-code').on('keyup', function() {
+ $('.submit_rspamd_regex').attr({"disabled": true});
+ });
+ $("#show_rspamd_global_filters").click(function() {
+ $.get("inc/ajax/show_rspamd_global_filters.php");
+ $("#confirm_show_rspamd_global_filters").hide();
+ $("#rspamd_global_filters").removeClass("d-none");
+ });
+ $("#super_delete").click(function() { return confirm(lang.queue_ays); });
+
+ $(".refresh_table").on('click', function(e) {
+ e.preventDefault();
+ var table_name = $(this).data('table');
+ $('#' + table_name).DataTable().ajax.reload();
+ });
+ function draw_domain_admins() {
+ // just recalc width if instance already exists
+ if ($.fn.DataTable.isDataTable('#domainadminstable') ) {
+ $('#domainadminstable').DataTable().columns.adjust().responsive.recalc();
+ return;
+ }
+
+ $('#domainadminstable').DataTable({
+ responsive: true,
+ processing: true,
+ serverSide: false,
+ stateSave: true,
+ pageLength: pagination_size,
+ dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
+ "tr" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ language: lang_datatables,
+ ajax: {
+ type: "GET",
+ url: "/api/v1/get/domain-admin/all",
+ dataSrc: function(data){
+ return process_table_data(data, 'domainadminstable');
+ }
+ },
+ columns: [
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: lang.username,
+ data: 'username',
+ defaultContent: ''
+ },
+ {
+ title: lang.admin_domains,
+ data: 'selected_domains',
+ defaultContent: '',
+ },
+ {
+ title: "TFA",
+ data: 'tfa_active',
+ defaultContent: '',
+ render: function (data, type) {
+ if(data == 1) return '<i class="bi bi-check-lg"></i>';
+ else return '<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.active,
+ data: 'active',
+ defaultContent: '',
+ render: function (data, type) {
+ if(data == 1) return '<i class="bi bi-check-lg"></i>';
+ else return '<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'text-md-end dt-sm-head-hidden dt-body-right',
+ defaultContent: ''
+ },
+ ],
+ initComplete: function(settings, json){
+ }
+ });
+ }
+ function draw_oauth2_clients() {
+ // just recalc width if instance already exists
+ if ($.fn.DataTable.isDataTable('#oauth2clientstable') ) {
+ $('#oauth2clientstable').DataTable().columns.adjust().responsive.recalc();
+ return;
+ }
+
+ $('#oauth2clientstable').DataTable({
+ responsive: true,
+ processing: true,
+ serverSide: false,
+ stateSave: true,
+ pageLength: pagination_size,
+ dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
+ "tr" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ language: lang_datatables,
+ ajax: {
+ type: "GET",
+ url: "/api/v1/get/oauth2-client/all",
+ dataSrc: function(data){
+ return process_table_data(data, 'oauth2clientstable');
+ }
+ },
+ columns: [
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: 'ID',
+ data: 'id',
+ defaultContent: ''
+ },
+ {
+ title: lang.oauth2_client_id,
+ data: 'client_id',
+ defaultContent: ''
+ },
+ {
+ title: lang.oauth2_client_secret,
+ data: 'client_secret',
+ defaultContent: ''
+ },
+ {
+ title: lang.oauth2_redirect_uri,
+ data: 'redirect_uri',
+ defaultContent: ''
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'text-md-end dt-sm-head-hidden dt-body-right',
+ defaultContent: ''
+ },
+ ]
+ });
+ }
+ function draw_admins() {
+ // just recalc width if instance already exists
+ if ($.fn.DataTable.isDataTable('#adminstable') ) {
+ $('#adminstable').DataTable().columns.adjust().responsive.recalc();
+ return;
+ }
+
+ $('#adminstable').DataTable({
+ responsive: true,
+ processing: true,
+ serverSide: false,
+ stateSave: true,
+ pageLength: pagination_size,
+ dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
+ "tr" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ language: lang_datatables,
+ ajax: {
+ type: "GET",
+ url: "/api/v1/get/admin/all",
+ dataSrc: function(data){
+ return process_table_data(data, 'adminstable');
+ }
+ },
+ columns: [
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: lang.username,
+ data: 'username',
+ defaultContent: ''
+ },
+ {
+ title: "TFA",
+ data: 'tfa_active',
+ defaultContent: '',
+ render: function (data, type) {
+ if(data == 1) return '<i class="bi bi-check-lg"></i>';
+ else return '<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.active,
+ data: 'active',
+ defaultContent: '',
+ render: function (data, type) {
+ if(data == 1) return '<i class="bi bi-check-lg"></i>';
+ else return '<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ defaultContent: '',
+ className: 'text-md-end dt-sm-head-hidden dt-body-right'
+ },
+ ]
+ });
+ }
+ function draw_fwd_hosts() {
+ // just recalc width if instance already exists
+ if ($.fn.DataTable.isDataTable('#forwardinghoststable') ) {
+ $('#forwardinghoststable').DataTable().columns.adjust().responsive.recalc();
+ return;
+ }
+
+ $('#forwardinghoststable').DataTable({
+ responsive: true,
+ processing: true,
+ serverSide: false,
+ stateSave: true,
+ pageLength: pagination_size,
+ dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
+ "tr" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ language: lang_datatables,
+ ajax: {
+ type: "GET",
+ url: "/api/v1/get/fwdhost/all",
+ dataSrc: function(data){
+ return process_table_data(data, 'forwardinghoststable');
+ }
+ },
+ columns: [
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: lang.host,
+ data: 'host',
+ defaultContent: ''
+ },
+ {
+ title: lang.source,
+ data: 'source',
+ defaultContent: ''
+ },
+ {
+ title: lang.spamfilter,
+ data: 'keep_spam',
+ defaultContent: '',
+ render: function(data, type){
+ return 'yes'==data?'<i class="bi bi-x-lg"></i>':'no'==data&&'<i class="bi bi-check-lg"></i>';
+ }
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'text-md-end dt-sm-head-hidden dt-body-right',
+ defaultContent: ''
+ },
+ ]
+ });
+ }
+ function draw_relayhosts() {
+ // just recalc width if instance already exists
+ if ($.fn.DataTable.isDataTable('#relayhoststable') ) {
+ $('#relayhoststable').DataTable().columns.adjust().responsive.recalc();
+ return;
+ }
+
+ $('#relayhoststable').DataTable({
+ responsive: true,
+ processing: true,
+ serverSide: false,
+ stateSave: true,
+ pageLength: pagination_size,
+ dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
+ "tr" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ language: lang_datatables,
+ ajax: {
+ type: "GET",
+ url: "/api/v1/get/relayhost/all",
+ dataSrc: function(data){
+ return process_table_data(data, 'relayhoststable');
+ }
+ },
+ columns: [
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: 'ID',
+ data: 'id',
+ defaultContent: ''
+ },
+ {
+ title: lang.host,
+ data: 'hostname',
+ defaultContent: ''
+ },
+ {
+ title: lang.username,
+ data: 'username',
+ defaultContent: ''
+ },
+ {
+ title: lang.in_use_by,
+ data: 'in_use_by',
+ defaultContent: ''
+ },
+ {
+ title: lang.active,
+ data: 'active',
+ defaultContent: '',
+ render: function (data, type) {
+ if(data == 1) return '<i class="bi bi-check-lg"></i>';
+ else return '<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'text-md-end dt-sm-head-hidden dt-body-right',
+ defaultContent: ''
+ },
+ ]
+ });
+ }
+ function draw_transport_maps() {
+ // just recalc width if instance already exists
+ if ($.fn.DataTable.isDataTable('#transportstable') ) {
+ $('#transportstable').DataTable().columns.adjust().responsive.recalc();
+ return;
+ }
+
+ $('#transportstable').DataTable({
+ responsive: true,
+ processing: true,
+ serverSide: false,
+ stateSave: true,
+ pageLength: pagination_size,
+ dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
+ "tr" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ language: lang_datatables,
+ ajax: {
+ type: "GET",
+ url: "/api/v1/get/transport/all",
+ dataSrc: function(data){
+ return process_table_data(data, 'transportstable');
+ }
+ },
+ columns: [
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: 'ID',
+ data: 'id',
+ defaultContent: ''
+ },
+ {
+ title: lang.destination,
+ data: 'destination',
+ defaultContent: ''
+ },
+ {
+ title: lang.nexthop,
+ data: 'nexthop',
+ defaultContent: ''
+ },
+ {
+ title: lang.username,
+ data: 'username',
+ defaultContent: ''
+ },
+ {
+ title: lang.active,
+ data: 'active',
+ defaultContent: '',
+ render: function (data, type) {
+ if(data == 1) return '<i class="bi bi-check-lg"></i>';
+ else return '<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'text-md-end dt-sm-head-hidden dt-body-right',
+ defaultContent: ''
+ },
+ ]
+ });
+ }
+
+ function process_table_data(data, table) {
+ if (table == 'relayhoststable') {
+ $.each(data, function (i, item) {
+ item.action = '<div class="btn-group">' +
+ '<a href="#" data-bs-toggle="modal" data-bs-target="#testTransportModal" data-transport-id="' + encodeURI(item.id) + '" data-transport-type="sender-dependent" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-caret-right-fill"></i> Test</a>' +
+ '<a href="/edit/relayhost/' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
+ '<a href="#" data-action="delete_selected" data-id="single-rlyhost" data-api-url="delete/relayhost" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
+ '</div>';
+ if (item.used_by_mailboxes == '') { item.in_use_by = item.used_by_domains; }
+ else if (item.used_by_domains == '') { item.in_use_by = item.used_by_mailboxes; }
+ else { item.in_use_by = item.used_by_mailboxes + '<hr style="margin:5px 0px 5px 0px;">' + item.used_by_domains; }
+ item.chkbox = '<input type="checkbox" data-id="rlyhosts" name="multi_select" value="' + item.id + '" />';
+ });
+ } else if (table == 'transportstable') {
+ $.each(data, function (i, item) {
+ if (item.is_mx_based) {
+ item.destination = '<i class="bi bi-info-circle-fill text-info mx-info" data-bs-toggle="tooltip" title="' + lang.is_mx_based + '"></i> <code>' + item.destination + '</code>';
+ }
+ if (item.username) {
+ item.username = '<i style="color:#' + intToRGB(hashCode(item.nexthop)) + ';" class="bi bi-square-fill"></i> ' + item.username;
+ }
+ item.action = '<div class="btn-group">' +
+ '<a href="#" data-bs-toggle="modal" data-bs-target="#testTransportModal" data-transport-id="' + encodeURI(item.id) + '" data-transport-type="transport-map" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-caret-right-fill"></i> Test</a>' +
+ '<a href="/edit/transport/' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
+ '<a href="#" data-action="delete_selected" data-id="single-transport" data-api-url="delete/transport" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
+ '</div>';
+ item.chkbox = '<input type="checkbox" data-id="transports" name="multi_select" value="' + item.id + '" />';
+ });
+ } else if (table == 'queuetable') {
+ $.each(data, function (i, item) {
+ item.chkbox = '<input type="checkbox" data-id="mailqitems" name="multi_select" value="' + item.queue_id + '" />';
+ rcpts = $.map(item.recipients, function(i) {
+ return escapeHtml(i);
+ });
+ item.recipients = rcpts.join('<hr style="margin:1px!important">');
+ item.action = '<div class="btn-group">' +
+ '<a href="#" data-bs-toggle="modal" data-bs-target="#showQueuedMsg" data-queue-id="' + encodeURI(item.queue_id) + '" class="btn btn-xs btn-secondary">' + lang.queue_show_message + '</a>' +
+ '</div>';
+ });
+ } else if (table == 'forwardinghoststable') {
+ $.each(data, function (i, item) {
+ item.action = '<div class="btn-group">' +
+ '<a href="#" data-action="delete_selected" data-id="single-fwdhost" data-api-url="delete/fwdhost" data-item="' + encodeURI(item.host) + '" class="btn btn-xs btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
+ '</div>';
+ item.chkbox = '<input type="checkbox" data-id="fwdhosts" name="multi_select" value="' + item.host + '" />';
+ });
+ } else if (table == 'oauth2clientstable') {
+ $.each(data, function (i, item) {
+ item.action = '<div class="btn-group">' +
+ '<a href="/edit.php?oauth2client=' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
+ '<a href="#" data-action="delete_selected" data-id="single-oauth2-client" data-api-url="delete/oauth2-client" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
+ '</div>';
+ item.scope = "profile";
+ item.grant_types = 'refresh_token password authorization_code';
+ item.chkbox = '<input type="checkbox" data-id="oauth2_clients" name="multi_select" value="' + item.id + '" />';
+ });
+ } else if (table == 'domainadminstable') {
+ $.each(data, function (i, item) {
+ item.selected_domains = escapeHtml(item.selected_domains);
+ item.selected_domains = item.selected_domains.toString().replace(/,/g, "<br>");
+ item.chkbox = '<input type="checkbox" data-id="domain_admins" name="multi_select" value="' + item.username + '" />';
+ item.action = '<div class="btn-group">' +
+ '<a href="/edit/domainadmin/' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
+ '<a href="#" data-action="delete_selected" data-id="single-domain-admin" data-api-url="delete/domain-admin" data-item="' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
+ '<a href="/index.php?duallogin=' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-xs-third btn-success"><i class="bi bi-person-fill"></i> Login</a>' +
+ '</div>';
+ });
+ } else if (table == 'adminstable') {
+ $.each(data, function (i, item) {
+ if (admin_username.toLowerCase() == item.username.toLowerCase()) {
+ item.usr = '<i class="bi bi-person-check"></i> ' + item.username;
+ } else {
+ item.usr = item.username;
+ }
+ item.chkbox = '<input type="checkbox" data-id="admins" name="multi_select" value="' + item.username + '" />';
+ item.action = '<div class="btn-group">' +
+ '<a href="/edit/admin/' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
+ '<a href="#" data-action="delete_selected" data-id="single-admin" data-api-url="delete/admin" data-item="' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
+ '</div>';
+ });
+ }
+ return data
+ };
+
+ // detect element visibility changes
+ function onVisible(element, callback) {
+ $(document).ready(function() {
+ element_object = document.querySelector(element);
+ if (element_object === null) return;
+
+ new IntersectionObserver((entries, observer) => {
+ entries.forEach(entry => {
+ if(entry.intersectionRatio > 0) {
+ callback(element_object);
+ }
+ });
+ }).observe(element_object);
+ });
+ }
+ // Draw Table if tab is active
+ onVisible("[id^=adminstable]", () => draw_admins());
+ onVisible("[id^=domainadminstable]", () => draw_domain_admins());
+ onVisible("[id^=oauth2clientstable]", () => draw_oauth2_clients());
+ onVisible("[id^=forwardinghoststable]", () => draw_fwd_hosts());
+ onVisible("[id^=relayhoststable]", () => draw_relayhosts());
+ onVisible("[id^=transportstable]", () => draw_transport_maps());
+
+
+ $('body').on('click', 'span.footable-toggle', function () {
+ event.stopPropagation();
+ })
+
+ // API IP check toggle
+ $("#skip_ip_check_ro").click(function( event ) {
+ $("#skip_ip_check_ro").not(this).prop('checked', false);
+ if ($("#skip_ip_check_ro:checked").length > 0) {
+ $('#allow_from_ro').prop('disabled', true);
+ }
+ else {
+ $("#allow_from_ro").removeAttr('disabled');
+ }
+ });
+ $("#skip_ip_check_rw").click(function( event ) {
+ $("#skip_ip_check_rw").not(this).prop('checked', false);
+ if ($("#skip_ip_check_rw:checked").length > 0) {
+ $('#allow_from_rw').prop('disabled', true);
+ }
+ else {
+ $("#allow_from_rw").removeAttr('disabled');
+ }
+ });
+ // Relayhost
+ $('#testRelayhostModal').on('show.bs.modal', function (e) {
+ $('#test_relayhost_result').text("-");
+ button = $(e.relatedTarget)
+ if (button != null) {
+ $('#relayhost_id').val(button.data('relayhost-id'));
+ }
+ })
+ $('#test_relayhost').on('click', function (e) {
+ e.preventDefault();
+ prev = $('#test_relayhost').text();
+ $(this).prop("disabled",true);
+ $(this).html('<i class="bi bi-arrow-repeat icon-spin"></i> ');
+ $.ajax({
+ type: 'GET',
+ url: 'inc/ajax/relay_check.php',
+ dataType: 'text',
+ data: $('#test_relayhost_form').serialize(),
+ complete: function (data) {
+ $('#test_relayhost_result').html(data.responseText);
+ $('#test_relayhost').prop("disabled",false);
+ $('#test_relayhost').text(prev);
+ }
+ });
+ })
+ // Transport
+ $('#testTransportModal').on('show.bs.modal', function (e) {
+ $('#test_transport_result').text("-");
+ button = $(e.relatedTarget)
+ if (button != null) {
+ $('#transport_id').val(button.data('transport-id'));
+ $('#transport_type').val(button.data('transport-type'));
+ }
+ })
+ $('#test_transport').on('click', function (e) {
+ e.preventDefault();
+ prev = $('#test_transport').text();
+ $(this).prop("disabled",true);
+ $(this).html('<div class="spinner-border" role="status"><span class="visually-hidden">Loading...</span></div> ');
+ $.ajax({
+ type: 'GET',
+ url: 'inc/ajax/transport_check.php',
+ dataType: 'text',
+ data: $('#test_transport_form').serialize(),
+ complete: function (data) {
+ $('#test_transport_result').html(data.responseText);
+ $('#test_transport').prop("disabled",false);
+ $('#test_transport').text(prev);
+ }
+ });
+ })
+ // DKIM private key modal
+ $('#showDKIMprivKey').on('show.bs.modal', function (e) {
+ $('#priv_key_pre').text("-");
+ p_related = $(e.relatedTarget)
+ if (p_related != null) {
+ var decoded_key = Base64.decode((p_related.data('priv-key')));
+ $('#priv_key_pre').text(decoded_key);
+ }
+ })
+ // FIDO2 friendly name modal
+ $('#fido2ChangeFn').on('show.bs.modal', function (e) {
+ rename_link = $(e.relatedTarget)
+ if (rename_link != null) {
+ $('#fido2_cid').val(rename_link.data('cid'));
+ $('#fido2_subject_desc').text(Base64.decode(rename_link.data('subject')));
+ }
+ })
+ // App links
+ function add_table_row(table_id, type) {
+ var row = $('<tr />');
+ if (type == "app_link") {
+ cols = '<td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="app" required></td>';
+ cols += '<td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="href" required></td>';
+ cols += '<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-secondary h-100 w-100" type="button">' + lang.remove_row + '</a></td>';
+ } else if (type == "f2b_regex") {
+ cols = '<td><input style="text-align:center" class="input-sm input-xs-lg form-control" data-id="f2b_regex" type="text" value="+" disabled></td>';
+ cols += '<td><input class="input-sm input-xs-lg form-control regex-input" data-id="f2b_regex" type="text" name="regex" required></td>';
+ cols += '<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-secondary h-100 w-100" type="button">' + lang.remove_row + '</a></td>';
+ }
+ row.append(cols);
+ table_id.append(row);
+ }
+ $('#app_link_table').on('click', 'tr a', function (e) {
+ e.preventDefault();
+ $(this).parents('tr').remove();
+ });
+ $('#f2b_regex_table').on('click', 'tr a', function (e) {
+ e.preventDefault();
+ $(this).parents('tr').remove();
+ });
+ $('#add_app_link_row').click(function() {
+ add_table_row($('#app_link_table'), "app_link");
+ });
+ $('#add_f2b_regex_row').click(function() {
+ add_table_row($('#f2b_regex_table'), "f2b_regex");
+ });
+});
diff --git a/data/web/js/site/debug.js b/data/web/js/site/debug.js
index a7b06e5a..e0b9a5ab 100644
--- a/data/web/js/site/debug.js
+++ b/data/web/js/site/debug.js
@@ -34,7 +34,7 @@ $(document).ready(function() {
});
// set update loop container list
- containersToUpdate = {}
+ containersToUpdate = {};
// set default ChartJs Font Color
Chart.defaults.color = '#999';
// create host cpu and mem charts
@@ -44,14 +44,13 @@ $(document).ready(function() {
check_update(mailcow_info.version_tag, mailcow_info.project_url);
}
$("#maiclow_version").click(function(){
- if (mailcow_cc_role !== "admin" && mailcow_cc_role !== "domainadmin" ||
- mailcow_info.branch !== "master")
+ if (mailcow_cc_role !== "admin" && mailcow_cc_role !== "domainadmin" || mailcow_info.branch !== "master")
return;
showVersionModal("Version " + mailcow_info.version_tag, mailcow_info.version_tag);
})
// get public ips
- $("#host_show_ip").click(function(){
+ $("#host_show_ip").click(function(){
$("#host_show_ip").find(".text").addClass("d-none");
$("#host_show_ip").find(".spinner-border").removeClass("d-none");
@@ -76,7 +75,7 @@ $(document).ready(function() {
$("#host_ipv6").addClass("d-block");
}).catch(function(error){
console.log(error);
-
+
$("#host_ipv6").removeClass("d-none");
$("#host_ipv6").addClass("d-block");
$("#host_ipv6").addClass("text-danger");
@@ -119,10 +118,11 @@ jQuery(function($){
}
var table = $('#autodiscover_log').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: log_pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -188,10 +188,11 @@ jQuery(function($){
}
var table = $('#postfix_log').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: log_pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -242,10 +243,11 @@ jQuery(function($){
}
var table = $('#watchdog_log').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: log_pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -300,10 +302,11 @@ jQuery(function($){
}
var table = $('#api_log').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: log_pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -352,7 +355,7 @@ jQuery(function($){
}
]
});
-
+
table.on('responsive-resize', function (e, datatable, columns){
hideTableExpandCollapseBtn('#tab-api-logs', '#api_log');
});
@@ -365,10 +368,11 @@ jQuery(function($){
}
var table = $('#rl_log').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: log_pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -455,7 +459,7 @@ jQuery(function($){
}
]
});
-
+
table.on('responsive-resize', function (e, datatable, columns){
hideTableExpandCollapseBtn('#tab-rl-logs', '#rl_log');
});
@@ -468,10 +472,11 @@ jQuery(function($){
}
var table = $('#ui_logs').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: log_pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -538,7 +543,7 @@ jQuery(function($){
}
]
});
-
+
table.on('responsive-resize', function (e, datatable, columns){
hideTableExpandCollapseBtn('#tab-ui-logs', '#ui_log');
});
@@ -551,10 +556,11 @@ jQuery(function($){
}
var table = $('#sasl_logs').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: log_pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -598,7 +604,7 @@ jQuery(function($){
}
]
});
-
+
table.on('responsive-resize', function (e, datatable, columns){
hideTableExpandCollapseBtn('#tab-sasl-logs', '#sasl_logs');
});
@@ -611,10 +617,11 @@ jQuery(function($){
}
var table = $('#acme_log').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: log_pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -647,7 +654,7 @@ jQuery(function($){
}
]
});
-
+
table.on('responsive-resize', function (e, datatable, columns){
hideTableExpandCollapseBtn('#tab-acme-logs', '#acme_log');
});
@@ -660,10 +667,11 @@ jQuery(function($){
}
var table = $('#netfilter_log').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: log_pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -701,7 +709,7 @@ jQuery(function($){
}
]
});
-
+
table.on('responsive-resize', function (e, datatable, columns){
hideTableExpandCollapseBtn('#tab-netfilter-logs', '#netfilter_log');
});
@@ -714,10 +722,11 @@ jQuery(function($){
}
var table = $('#sogo_log').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: log_pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -755,7 +764,7 @@ jQuery(function($){
}
]
});
-
+
table.on('responsive-resize', function (e, datatable, columns){
hideTableExpandCollapseBtn('#tab-sogo-logs', '#sogo_log');
});
@@ -768,10 +777,11 @@ jQuery(function($){
}
var table = $('#dovecot_log').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: log_pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -883,10 +893,11 @@ jQuery(function($){
}
var table = $('#rspamd_history').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: log_pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -983,7 +994,7 @@ jQuery(function($){
}
]
});
-
+
table.on('responsive-resize', function (e, datatable, columns){
hideTableExpandCollapseBtn('#tab-rspamd-history', '#rspamd_history');
});
@@ -998,31 +1009,31 @@ jQuery(function($){
item.rcpt = escapeHtml(item.rcpt_smtp.join(", "));
}
item.symbols = Object.keys(item.symbols).sort(function (a, b) {
- if (item.symbols[a].score === 0) return 1
- if (item.symbols[b].score === 0) return -1
+ if (item.symbols[a].score === 0) return 1;
+ if (item.symbols[b].score === 0) return -1;
if (item.symbols[b].score < 0 && item.symbols[a].score < 0) {
- return item.symbols[a].score - item.symbols[b].score
+ return item.symbols[a].score - item.symbols[b].score;
}
if (item.symbols[b].score > 0 && item.symbols[a].score > 0) {
- return item.symbols[b].score - item.symbols[a].score
+ return item.symbols[b].score - item.symbols[a].score;
}
- return item.symbols[b].score - item.symbols[a].score
+ return item.symbols[b].score - item.symbols[a].score;
}).map(function(key) {
var sym = item.symbols[key];
if (sym.score < 0) {
- sym.score_formatted = '(<span class="text-success"><b>' + sym.score + '</b></span>)'
+ sym.score_formatted = '(<span class="text-success"><b>' + sym.score + '</b></span>)';
}
else if (sym.score === 0) {
- sym.score_formatted = '(<span><b>' + sym.score + '</b></span>)'
+ sym.score_formatted = '(<span><b>' + sym.score + '</b></span>)';
}
else {
- sym.score_formatted = '(<span class="text-danger"><b>' + sym.score + '</b></span>)'
+ sym.score_formatted = '(<span class="text-danger"><b>' + sym.score + '</b></span>)';
}
var str = '<strong>' + key + '</strong> ' + sym.score_formatted;
if (sym.options) {
str += ' [' + escapeHtml(sym.options.join(", ")) + "]";
}
- return str
+ return str;
}).join('<br>\n');
item.subject = escapeHtml(item.subject);
var scan_time = item.time_real.toFixed(3);
@@ -1155,14 +1166,14 @@ jQuery(function($){
}
});
}
- return data
+ return data;
};
$('.add_log_lines').on('click', function (e) {
e.preventDefault();
- var log_table= $(this).data("table")
- var new_nrows = $(this).data("nrows")
- var post_process = $(this).data("post-process")
- var log_url = $(this).data("log-url")
+ var log_table= $(this).data("table");
+ var new_nrows = $(this).data("nrows");
+ var post_process = $(this).data("post-process");
+ var log_url = $(this).data("log-url");
if (log_table === undefined || new_nrows === undefined || post_process === undefined || log_url === undefined) {
console.log("no data-table or data-nrows or log_url or data-post-process attr found");
return;
@@ -1184,9 +1195,9 @@ jQuery(function($){
})
function hideTableExpandCollapseBtn(tab, table){
if ($(table).hasClass('collapsed'))
- $(tab).find(".table_collapse_option").show();
+ $(tab).find(".table_collapse_option").show();
else
- $(tab).find(".table_collapse_option").hide();
+ $(tab).find(".table_collapse_option").hide();
}
// detect element visibility changes
@@ -1220,7 +1231,6 @@ jQuery(function($){
onVisible("[id^=rspamd_donut]", () => rspamd_pie_graph());
-
// start polling host stats if tab is active
onVisible("[id^=tab-containers]", () => update_stats());
// start polling container stats if collapse is active
@@ -1303,9 +1313,9 @@ function update_stats(timeout=5){
if (mem_chart.data.labels.length > 30) mem_chart.data.labels.shift();
cpu_chart.data.datasets[0].data.push(data.cpu.usage);
- if (cpu_chart.data.datasets[0].data.length > 30) cpu_chart.data.datasets[0].data.shift();
+ if (cpu_chart.data.datasets[0].data.length > 30) cpu_chart.data.datasets[0].data.shift();
mem_chart.data.datasets[0].data.push(data.memory.usage);
- if (mem_chart.data.datasets[0].data.length > 30) mem_chart.data.datasets[0].data.shift();
+ if (mem_chart.data.datasets[0].data.length > 30) mem_chart.data.datasets[0].data.shift();
cpu_chart.update();
mem_chart.update();
@@ -1464,23 +1474,23 @@ function createReadWriteChart(chart_id, read_lable, write_lable){
};
var optionsNet = {
interaction: {
- mode: 'index'
+ mode: 'index'
},
scales: {
yAxis: {
min: 0,
grid: {
- display: false
+ display: false
},
ticks: {
callback: function(i, index, ticks) {
- return formatBytes(i);
+ return formatBytes(i);
}
}
},
xAxis: {
grid: {
- display: false
+ display: false
}
}
}
@@ -1528,13 +1538,13 @@ function createHostCpuAndMemChart(){
};
var optionsCpu = {
interaction: {
- mode: 'index'
+ mode: 'index'
},
scales: {
yAxis: {
min: 0,
grid: {
- display: false
+ display: false
},
ticks: {
callback: function(i, index, ticks) {
@@ -1544,7 +1554,7 @@ function createHostCpuAndMemChart(){
},
xAxis: {
grid: {
- display: false
+ display: false
}
}
}
@@ -1566,13 +1576,13 @@ function createHostCpuAndMemChart(){
};
var optionsMem = {
interaction: {
- mode: 'index'
+ mode: 'index'
},
scales: {
yAxis: {
min: 0,
grid: {
- display: false
+ display: false
},
ticks: {
callback: function(i, index, ticks) {
@@ -1582,7 +1592,7 @@ function createHostCpuAndMemChart(){
},
xAxis: {
grid: {
- display: false
+ display: false
}
}
}
@@ -1678,22 +1688,22 @@ function parseGithubMarkdownLinks(inputText) {
replacePattern1 = /(\b(https?):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
replacedText = inputText.replace(replacePattern1, (matched, index, original, input_string) => {
- if (matched.includes('github.com')){
- // return short link if it's github link
- last_uri_path = matched.split('/');
- last_uri_path = last_uri_path[last_uri_path.length - 1];
-
- // adjust Full Changelog link to match last git version and new git version, if link is a compare link
- if (matched.includes('/compare/') && mailcow_info.last_version_tag !== ''){
- matched = matched.replace(last_uri_path, mailcow_info.last_version_tag + '...' + mailcow_info.version_tag);
- last_uri_path = mailcow_info.last_version_tag + '...' + mailcow_info.version_tag;
- }
+ if (matched.includes('github.com')){
+ // return short link if it's github link
+ last_uri_path = matched.split('/');
+ last_uri_path = last_uri_path[last_uri_path.length - 1];
+
+ // adjust Full Changelog link to match last git version and new git version, if link is a compare link
+ if (matched.includes('/compare/') && mailcow_info.last_version_tag !== ''){
+ matched = matched.replace(last_uri_path, mailcow_info.last_version_tag + '...' + mailcow_info.version_tag);
+ last_uri_path = mailcow_info.last_version_tag + '...' + mailcow_info.version_tag;
+ }
- return '<a href="' + matched + '" target="_blank">' + last_uri_path + '</a><br>';
- };
+ return '<a href="' + matched + '" target="_blank">' + last_uri_path + '</a><br>';
+ };
- // if it's not a github link, return complete link
- return '<a href="' + matched + '" target="_blank">' + matched + '</a>';
+ // if it's not a github link, return complete link
+ return '<a href="' + matched + '" target="_blank">' + matched + '</a>';
});
return replacedText;
diff --git a/data/web/js/site/edit.js b/data/web/js/site/edit.js
index 4c57b35e..4680bdfa 100644
--- a/data/web/js/site/edit.js
+++ b/data/web/js/site/edit.js
@@ -1,220 +1,222 @@
-$(document).ready(function() {
- $(".arrow-toggle").on('click', function(e) { e.preventDefault(); $(this).find('.arrow').toggleClass("animation"); });
- $("#pushover_delete").click(function() { return confirm(lang.delete_ays); });
- $(".goto_checkbox").click(function( event ) {
- $("form[data-id='editalias'] .goto_checkbox").not(this).prop('checked', false);
- if ($("form[data-id='editalias'] .goto_checkbox:checked").length > 0) {
- $('#textarea_alias_goto').prop('disabled', true);
- }
- else {
- $("#textarea_alias_goto").removeAttr('disabled');
- }
- });
- $("#disable_sender_check").click(function( event ) {
- if ($("form[data-id='editmailbox'] #disable_sender_check:checked").length > 0) {
- $('#editSelectSenderACL').prop('disabled', true);
- $('#editSelectSenderACL').selectpicker('refresh');
- }
- else {
- $('#editSelectSenderACL').prop('disabled', false);
- $('#editSelectSenderACL').selectpicker('refresh');
- }
- });
- if ($("form[data-id='editalias'] .goto_checkbox:checked").length > 0) {
- $('#textarea_alias_goto').prop('disabled', true);
- }
-
- $("#mailbox-password-warning-close").click(function( event ) {
- $('#mailbox-passwd-hidden-info').addClass('hidden');
- $('#mailbox-passwd-form-groups').removeClass('hidden');
- });
- // Sender ACL
- if ($("#editSelectSenderACL option[value='\*']:selected").length > 0){
- $("#sender_acl_disabled").show();
- }
- $('#editSelectSenderACL').change(function() {
- if ($("#editSelectSenderACL option[value='\*']:selected").length > 0){
- $("#sender_acl_disabled").show();
- }
- else {
- $("#sender_acl_disabled").hide();
- }
- });
- // Resources
- if ($("#editSelectMultipleBookings").val() == "custom") {
- $("#multiple_bookings_custom_div").show();
- $('input[name=multiple_bookings]').val($("#multiple_bookings_custom").val());
- }
- $("#editSelectMultipleBookings").change(function() {
- $('input[name=multiple_bookings]').val($("#editSelectMultipleBookings").val());
- if ($('input[name=multiple_bookings]').val() == "custom") {
- $("#multiple_bookings_custom_div").show();
- }
- else {
- $("#multiple_bookings_custom_div").hide();
- }
- });
- $("#multiple_bookings_custom").bind("change keypress keyup blur", function() {
- $('input[name=multiple_bookings]').val($("#multiple_bookings_custom").val());
- });
-
- // load tags
- if ($('#tags').length){
- var tagsEl = $('#tags').parent().find('.tag-values')[0];
- console.log($(tagsEl).val())
- var tags = JSON.parse($(tagsEl).val());
- $(tagsEl).val("");
-
- for (var i = 0; i < tags.length; i++)
- addTag($('#tags'), tags[i]);
- }
-});
-
-jQuery(function($){
- // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
- function validateEmail(email) {
- var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
- return re.test(email);
- }
- function draw_wl_policy_domain_table() {
- $('#wl_policy_domain_table').DataTable({
- responsive: true,
- processing: true,
- serverSide: false,
- stateSave: true,
- dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
- "tr" +
- "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
- language: lang_datatables,
- ajax: {
- type: "GET",
- url: '/api/v1/get/policy_wl_domain/' + table_for_domain,
- dataSrc: function(data){
- $.each(data, function (i, item) {
- if (!validateEmail(item.object)) {
- item.chkbox = '<input type="checkbox" data-id="policy_wl_domain" name="multi_select" value="' + item.prefid + '" />';
- }
- else {
- item.chkbox = '<input type="checkbox" disabled title="' + lang_user.spamfilter_table_domain_policy + '" />';
- }
- });
-
- return data;
- }
- },
- columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: 'ID',
- data: 'prefid',
- defaultContent: ''
- },
- {
- title: lang_user.spamfilter_table_rule,
- data: 'value',
- defaultContent: ''
- },
- {
- title: 'Scope',
- data: 'object',
- defaultContent: ''
- }
- ]
- });
- }
- function draw_bl_policy_domain_table() {
- $('#bl_policy_domain_table').DataTable({
- responsive: true,
- processing: true,
- serverSide: false,
- stateSave: true,
- dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
- "tr" +
- "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
- language: lang_datatables,
- ajax: {
- type: "GET",
- url: '/api/v1/get/policy_bl_domain/' + table_for_domain,
- dataSrc: function(data){
- $.each(data, function (i, item) {
- if (!validateEmail(item.object)) {
- item.chkbox = '<input type="checkbox" data-id="policy_bl_domain" name="multi_select" value="' + item.prefid + '" />';
- }
- else {
- item.chkbox = '<input type="checkbox" disabled tooltip="' + lang_user.spamfilter_table_domain_policy + '" />';
- }
- });
-
- return data;
- }
- },
- columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: 'ID',
- data: 'prefid',
- defaultContent: ''
- },
- {
- title: lang_user.spamfilter_table_rule,
- data: 'value',
- defaultContent: ''
- },
- {
- title: 'Scope',
- data: 'object',
- defaultContent: ''
- }
- ]
- });
- }
-
-
- // detect element visibility changes
- function onVisible(element, callback) {
- $(document).ready(function() {
- element_object = document.querySelector(element);
- if (element_object === null) return;
-
- new IntersectionObserver((entries, observer) => {
- entries.forEach(entry => {
- if(entry.intersectionRatio > 0) {
- callback(element_object);
- observer.disconnect();
- }
- });
- }).observe(element_object);
- });
- }
- // Draw Table if tab is active
- onVisible("[id^=wl_policy_domain_table]", () => draw_wl_policy_domain_table());
- onVisible("[id^=bl_policy_domain_table]", () => draw_bl_policy_domain_table());
-});
+$(document).ready(function() {
+ $(".arrow-toggle").on('click', function(e) { e.preventDefault(); $(this).find('.arrow').toggleClass("animation"); });
+ $("#pushover_delete").click(function() { return confirm(lang.delete_ays); });
+ $(".goto_checkbox").click(function( event ) {
+ $("form[data-id='editalias'] .goto_checkbox").not(this).prop('checked', false);
+ if ($("form[data-id='editalias'] .goto_checkbox:checked").length > 0) {
+ $('#textarea_alias_goto').prop('disabled', true);
+ }
+ else {
+ $("#textarea_alias_goto").removeAttr('disabled');
+ }
+ });
+ $("#disable_sender_check").click(function( event ) {
+ if ($("form[data-id='editmailbox'] #disable_sender_check:checked").length > 0) {
+ $('#editSelectSenderACL').prop('disabled', true);
+ $('#editSelectSenderACL').selectpicker('refresh');
+ }
+ else {
+ $('#editSelectSenderACL').prop('disabled', false);
+ $('#editSelectSenderACL').selectpicker('refresh');
+ }
+ });
+ if ($("form[data-id='editalias'] .goto_checkbox:checked").length > 0) {
+ $('#textarea_alias_goto').prop('disabled', true);
+ }
+
+ $("#mailbox-password-warning-close").click(function( event ) {
+ $('#mailbox-passwd-hidden-info').addClass('hidden');
+ $('#mailbox-passwd-form-groups').removeClass('hidden');
+ });
+ // Sender ACL
+ if ($("#editSelectSenderACL option[value='\*']:selected").length > 0){
+ $("#sender_acl_disabled").show();
+ }
+ $('#editSelectSenderACL').change(function() {
+ if ($("#editSelectSenderACL option[value='\*']:selected").length > 0){
+ $("#sender_acl_disabled").show();
+ }
+ else {
+ $("#sender_acl_disabled").hide();
+ }
+ });
+ // Resources
+ if ($("#editSelectMultipleBookings").val() == "custom") {
+ $("#multiple_bookings_custom_div").show();
+ $('input[name=multiple_bookings]').val($("#multiple_bookings_custom").val());
+ }
+ $("#editSelectMultipleBookings").change(function() {
+ $('input[name=multiple_bookings]').val($("#editSelectMultipleBookings").val());
+ if ($('input[name=multiple_bookings]').val() == "custom") {
+ $("#multiple_bookings_custom_div").show();
+ }
+ else {
+ $("#multiple_bookings_custom_div").hide();
+ }
+ });
+ $("#multiple_bookings_custom").bind("change keypress keyup blur", function() {
+ $('input[name=multiple_bookings]').val($("#multiple_bookings_custom").val());
+ });
+
+ // load tags
+ if ($('#tags').length){
+ var tagsEl = $('#tags').parent().find('.tag-values')[0];
+ console.log($(tagsEl).val())
+ var tags = JSON.parse($(tagsEl).val());
+ $(tagsEl).val("");
+
+ for (var i = 0; i < tags.length; i++)
+ addTag($('#tags'), tags[i]);
+ }
+});
+
+jQuery(function($){
+ // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
+ function validateEmail(email) {
+ var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
+ return re.test(email);
+ }
+ function draw_wl_policy_domain_table() {
+ $('#wl_policy_domain_table').DataTable({
+ responsive: true,
+ processing: true,
+ serverSide: false,
+ stateSave: true,
+ pageLength: pagination_size,
+ dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
+ "tr" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ language: lang_datatables,
+ ajax: {
+ type: "GET",
+ url: '/api/v1/get/policy_wl_domain/' + table_for_domain,
+ dataSrc: function(data){
+ $.each(data, function (i, item) {
+ if (!validateEmail(item.object)) {
+ item.chkbox = '<input type="checkbox" data-id="policy_wl_domain" name="multi_select" value="' + item.prefid + '" />';
+ }
+ else {
+ item.chkbox = '<input type="checkbox" disabled title="' + lang_user.spamfilter_table_domain_policy + '" />';
+ }
+ });
+
+ return data;
+ }
+ },
+ columns: [
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: 'ID',
+ data: 'prefid',
+ defaultContent: ''
+ },
+ {
+ title: lang_user.spamfilter_table_rule,
+ data: 'value',
+ defaultContent: ''
+ },
+ {
+ title: 'Scope',
+ data: 'object',
+ defaultContent: ''
+ }
+ ]
+ });
+ }
+ function draw_bl_policy_domain_table() {
+ $('#bl_policy_domain_table').DataTable({
+ responsive: true,
+ processing: true,
+ serverSide: false,
+ stateSave: true,
+ pageLength: pagination_size,
+ dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
+ "tr" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ language: lang_datatables,
+ ajax: {
+ type: "GET",
+ url: '/api/v1/get/policy_bl_domain/' + table_for_domain,
+ dataSrc: function(data){
+ $.each(data, function (i, item) {
+ if (!validateEmail(item.object)) {
+ item.chkbox = '<input type="checkbox" data-id="policy_bl_domain" name="multi_select" value="' + item.prefid + '" />';
+ }
+ else {
+ item.chkbox = '<input type="checkbox" disabled tooltip="' + lang_user.spamfilter_table_domain_policy + '" />';
+ }
+ });
+
+ return data;
+ }
+ },
+ columns: [
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: 'ID',
+ data: 'prefid',
+ defaultContent: ''
+ },
+ {
+ title: lang_user.spamfilter_table_rule,
+ data: 'value',
+ defaultContent: ''
+ },
+ {
+ title: 'Scope',
+ data: 'object',
+ defaultContent: ''
+ }
+ ]
+ });
+ }
+
+
+ // detect element visibility changes
+ function onVisible(element, callback) {
+ $(document).ready(function() {
+ element_object = document.querySelector(element);
+ if (element_object === null) return;
+
+ new IntersectionObserver((entries, observer) => {
+ entries.forEach(entry => {
+ if(entry.intersectionRatio > 0) {
+ callback(element_object);
+ observer.disconnect();
+ }
+ });
+ }).observe(element_object);
+ });
+ }
+ // Draw Table if tab is active
+ onVisible("[id^=wl_policy_domain_table]", () => draw_wl_policy_domain_table());
+ onVisible("[id^=bl_policy_domain_table]", () => draw_bl_policy_domain_table());
+});
diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js
index b93b1819..49cce1b2 100644
--- a/data/web/js/site/mailbox.js
+++ b/data/web/js/site/mailbox.js
@@ -77,7 +77,7 @@ $(document).ready(function() {
$('.dns-modal-body').html(xhr.responseText);
}
});
- });
+ });
// @Open Domain add modal
$('#addDomainModal').on('show.bs.modal', function(e) {
$.ajax({
@@ -85,24 +85,24 @@ $(document).ready(function() {
data: {},
dataType: 'json',
success: async function(data){
- $('#domain_templates').find('option').remove();
+ $('#domain_templates').find('option').remove();
$('#domain_templates').selectpicker('destroy');
$('#domain_templates').selectpicker();
for (var i = 0; i < data.length; i++){
if (data[i].template === "Default"){
- $('#domain_templates').prepend($('<option>', {
- 'value': data[i].id,
- 'text': data[i].template,
- 'data-attributes': JSON.stringify(data[i].attributes),
- 'selected': true
+ $('#domain_templates').prepend($('<option>', {
+ 'value': data[i].id,
+ 'text': data[i].template,
+ 'data-attributes': JSON.stringify(data[i].attributes),
+ 'selected': true
}));
setDomainTemplateData(data[i].attributes);
} else {
- $('#domain_templates').append($('<option>', {
- 'value': data[i].id,
- 'text': data[i].template,
- 'data-attributes': JSON.stringify(data[i].attributes),
- 'selected': false
+ $('#domain_templates').append($('<option>', {
+ 'value': data[i].id,
+ 'text': data[i].template,
+ 'data-attributes': JSON.stringify(data[i].attributes),
+ 'selected': false
}));
}
};
@@ -127,24 +127,24 @@ $(document).ready(function() {
data: {},
dataType: 'json',
success: async function(data){
- $('#mailbox_templates').find('option').remove();
+ $('#mailbox_templates').find('option').remove();
$('#mailbox_templates').selectpicker('destroy');
$('#mailbox_templates').selectpicker();
for (var i = 0; i < data.length; i++){
if (data[i].template === "Default"){
- $('#mailbox_templates').prepend($('<option>', {
- 'value': data[i].id,
- 'text': data[i].template,
- 'data-attributes': JSON.stringify(data[i].attributes),
- 'selected': true
+ $('#mailbox_templates').prepend($('<option>', {
+ 'value': data[i].id,
+ 'text': data[i].template,
+ 'data-attributes': JSON.stringify(data[i].attributes),
+ 'selected': true
}));
setMailboxTemplateData(data[i].attributes);
} else {
- $('#mailbox_templates').append($('<option>', {
- value: data[i].id,
- text : data[i].template,
- 'data-attributes': JSON.stringify(data[i].attributes),
- 'selected': false
+ $('#mailbox_templates').append($('<option>', {
+ value: data[i].id,
+ text : data[i].template,
+ 'data-attributes': JSON.stringify(data[i].attributes),
+ 'selected': false
}));
}
};
@@ -229,20 +229,20 @@ $(document).ready(function() {
} else {
$('#addDomain_gal').prop('checked', false);
}
-
+
if (template.active == 1){
$('#addDomain_active').prop('checked', true);
} else {
$('#addDomain_active').prop('checked', false);
}
-
+
$("#addDomain_rl_value").val(template.rl_value);
$('#addDomain_rl_frame').selectpicker('val', template.rl_frame);
$("#dkim_selector").val(template.dkim_selector);
if (!template.key_size)
template.key_size = 2048;
$('#key_size').selectpicker('val', template.key_size.toString());
-
+
if (template.backupmx == 1){
$('#addDomain_relay_domain').prop('checked', true);
} else {
@@ -259,7 +259,7 @@ $(document).ready(function() {
$('#addDomain_relay_unknown_only').prop('checked', false);
}
-
+
// load tags
$('#addDomain_tags').val("");
$($('#addDomain_tags').parent().find(".tag-values")[0]).val("");
@@ -404,7 +404,7 @@ $(document).ready(function() {
} else {
$('#sogo_access').prop('checked', false);
}
-
+
// load tags
$('#addMailbox_tags').val("");
$($('#addMailbox_tags').parent().find(".tag-values")[0]).val("");
@@ -417,11 +417,11 @@ jQuery(function($){
// http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
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]}
function unix_time_format(i){return""==i?'<i class="bi bi-x"></i>':new Date(i?1e3*i:0).toLocaleDateString(void 0,{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"})}
-
+
$(".refresh_table").on('click', function(e) {
e.preventDefault();
var table_name = $(this).data('table');
-
+
if ($.fn.DataTable.isDataTable('#' + table_name))
$('#' + table_name).DataTable().ajax.reload();
});
@@ -433,10 +433,11 @@ jQuery(function($){
}
var table = $('#domain_table').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -617,8 +618,8 @@ jQuery(function($){
defaultContent: ''
},
]
- });
-
+ });
+
table.on('responsive-resize', function (e, datatable, columns){
hideTableExpandCollapseBtn('#tab-domains', '#domain_table');
});
@@ -631,15 +632,16 @@ jQuery(function($){
}
var table = $('#templates_domain_table').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
language: lang_datatables,
- order:[[2, 'desc']],
+ order: [[2, 'desc']],
initComplete: function(){
hideTableExpandCollapseBtn('#tab-templates-domains', '#templates_domain_table');
},
@@ -666,13 +668,13 @@ jQuery(function($){
}
item.attributes.rl_value = escapeHtml(item.attributes.rl_value);
-
+
if (item.template.toLowerCase() == "default"){
item.action = '<div class="btn-group">' +
'<a href="/edit/template/' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
'</div>';
}
- else{
+ else {
item.action = '<div class="btn-group">' +
'<a href="/edit/template/' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
'<a href="#" data-action="delete_selected" data-id="single-template" data-api-url="delete/domain/template" data-item="' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
@@ -693,138 +695,138 @@ jQuery(function($){
}
},
columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 1
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 1
- },
- {
- title: "ID",
- data: 'id',
- responsivePriority: 2,
- defaultContent: ''
- },
- {
- title: lang.template,
- data: 'template',
- responsivePriority: 3,
- defaultContent: ''
- },
- {
- title: lang.max_aliases,
- data: 'attributes.max_num_aliases_for_domain',
- defaultContent: '',
- },
- {
- title: lang.max_mailboxes,
- data: 'attributes.max_num_mboxes_for_domain',
- defaultContent: '',
- },
- {
- title: lang.mailbox_defquota,
- data: 'attributes.def_quota_for_mbox',
- defaultContent: '',
- },
- {
- title: lang.max_quota,
- data: 'attributes.max_quota_for_mbox',
- defaultContent: '',
- },
- {
- title: lang.domain_quota_total,
- data: 'attributes.max_quota_for_domain',
- defaultContent: '',
- },
- {
- title: lang.gal,
- data: 'attributes.gal',
- defaultContent: '',
- render: function (data, type) {
- return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
- }
- },
- {
- title: lang.backup_mx,
- data: 'attributes.backupmx',
- defaultContent: '',
- render: function (data, type) {
- return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
- }
- },
- {
- title: lang.relay_all,
- data: 'attributes.relay_all_recipients',
- defaultContent: '',
- render: function (data, type) {
- return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
- }
- },
- {
- title: lang.relay_unknown,
- data: 'attributes.relay_unknown_only',
- defaultContent: '',
- render: function (data, type) {
- return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
- }
- },
- {
- title: lang.active,
- data: 'attributes.active',
- defaultContent: '',
- responsivePriority: 4,
- render: function (data, type) {
- return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
- }
- },
- {
- title: 'rl_frame',
- data: 'attributes.rl_frame',
- defaultContent: '',
- class: 'none',
- },
- {
- title: 'rl_value',
- data: 'attributes.rl_value',
- defaultContent: '',
- class: 'none',
- },
- {
- title: lang.dkim_domains_selector,
- data: 'attributes.dkim_selector',
- defaultContent: '',
- class: 'none',
- },
- {
- title: lang.dkim_key_length,
- data: 'attributes.key_size',
- defaultContent: '',
- class: 'none',
- },
- {
- title: 'Tags',
- data: 'attributes.tags',
- defaultContent: '',
- className: 'none'
- },
- {
- title: lang.action,
- data: 'action',
- className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md',
- responsivePriority: 6,
- defaultContent: ''
- },
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 1
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 1
+ },
+ {
+ title: "ID",
+ data: 'id',
+ responsivePriority: 2,
+ defaultContent: ''
+ },
+ {
+ title: lang.template,
+ data: 'template',
+ responsivePriority: 3,
+ defaultContent: ''
+ },
+ {
+ title: lang.max_aliases,
+ data: 'attributes.max_num_aliases_for_domain',
+ defaultContent: '',
+ },
+ {
+ title: lang.max_mailboxes,
+ data: 'attributes.max_num_mboxes_for_domain',
+ defaultContent: '',
+ },
+ {
+ title: lang.mailbox_defquota,
+ data: 'attributes.def_quota_for_mbox',
+ defaultContent: '',
+ },
+ {
+ title: lang.max_quota,
+ data: 'attributes.max_quota_for_mbox',
+ defaultContent: '',
+ },
+ {
+ title: lang.domain_quota_total,
+ data: 'attributes.max_quota_for_domain',
+ defaultContent: '',
+ },
+ {
+ title: lang.gal,
+ data: 'attributes.gal',
+ defaultContent: '',
+ render: function (data, type) {
+ return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.backup_mx,
+ data: 'attributes.backupmx',
+ defaultContent: '',
+ render: function (data, type) {
+ return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.relay_all,
+ data: 'attributes.relay_all_recipients',
+ defaultContent: '',
+ render: function (data, type) {
+ return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.relay_unknown,
+ data: 'attributes.relay_unknown_only',
+ defaultContent: '',
+ render: function (data, type) {
+ return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.active,
+ data: 'attributes.active',
+ defaultContent: '',
+ responsivePriority: 4,
+ render: function (data, type) {
+ return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: 'rl_frame',
+ data: 'attributes.rl_frame',
+ defaultContent: '',
+ class: 'none',
+ },
+ {
+ title: 'rl_value',
+ data: 'attributes.rl_value',
+ defaultContent: '',
+ class: 'none',
+ },
+ {
+ title: lang.dkim_domains_selector,
+ data: 'attributes.dkim_selector',
+ defaultContent: '',
+ class: 'none',
+ },
+ {
+ title: lang.dkim_key_length,
+ data: 'attributes.key_size',
+ defaultContent: '',
+ class: 'none',
+ },
+ {
+ title: 'Tags',
+ data: 'attributes.tags',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md',
+ responsivePriority: 6,
+ defaultContent: ''
+ },
]
});
@@ -840,10 +842,11 @@ jQuery(function($){
}
var table = $('#mailbox_table').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -927,7 +930,7 @@ jQuery(function($){
'<div class="progress-bar-mailbox progress-bar progress-bar-' + item.percent_class + '" role="progressbar" aria-valuenow="' + item.percent_in_use + '" aria-valuemin="0" aria-valuemax="100" ' +
'style="min-width:2em;width:' + item.percent_in_use + '%">' + item.percent_in_use + '%' + '</div></div>';
item.username = escapeHtml(item.username);
-
+
if (Array.isArray(item.tags)){
var tags = '';
for (var i = 0; i < item.tags.length; i++)
@@ -942,167 +945,167 @@ jQuery(function($){
}
},
columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 1
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 2
- },
- {
- title: lang.username,
- data: 'username',
- responsivePriority: 3,
- defaultContent: ''
- },
- {
- title: lang.domain_quota,
- data: 'quota.value',
- responsivePriority: 8,
- defaultContent: '',
- orderData: 23
- },
- {
- title: lang.last_mail_login,
- data: 'last_mail_login',
- defaultContent: '',
- responsivePriority: 7,
- render: function (data, type) {
- res = data.split("/");
- return '<div class="badge bg-info mb-2">IMAP @ ' + unix_time_format(Number(res[0])) + '</div><br>' +
- '<div class="badge bg-info mb-2">POP3 @ ' + unix_time_format(Number(res[1])) + '</div><br>' +
- '<div class="badge bg-info">SMTP @ ' + unix_time_format(Number(res[2])) + '</div>';
- }
- },
- {
- title: lang.last_pw_change,
- data: 'last_pw_change',
- defaultContent: ''
- },
- {
- title: lang.in_use,
- data: 'in_use',
- defaultContent: '',
- responsivePriority: 9,
- className: 'dt-data-w100'
- },
- {
- title: lang.fname,
- data: 'name',
- defaultContent: '',
- className: 'none'
- },
- {
- title: lang.domain,
- data: 'domain',
- defaultContent: '',
- className: 'none'
- },
- {
- title: lang.tls_enforce_in,
- data: 'tls_enforce_in',
- defaultContent: '',
- className: 'none'
- },
- {
- title: lang.tls_enforce_out,
- data: 'tls_enforce_out',
- defaultContent: '',
- className: 'none'
- },
- {
- title: 'SMTP',
- data: 'smtp_access',
- defaultContent: '',
- className: 'none'
- },
- {
- title: 'IMAP',
- data: 'imap_access',
- defaultContent: '',
- className: 'none'
- },
- {
- title: 'POP3',
- data: 'pop3_access',
- defaultContent: '',
- className: 'none'
- },
- {
- title: 'SIEVE',
- data: 'sieve_access',
- defaultContent: '',
- className: 'none'
- },
- {
- title: lang.quarantine_notification,
- data: 'quarantine_notification',
- defaultContent: '',
- className: 'none'
- },
- {
- title: lang.quarantine_category,
- data: 'quarantine_category',
- defaultContent: '',
- className: 'none'
- },
- {
- title: lang.msg_num,
- data: 'messages',
- defaultContent: '',
- responsivePriority: 5
- },
- {
- title: lang.created_on,
- data: 'created',
- defaultContent: '',
- className: 'none'
- },
- {
- title: lang.last_modified,
- data: 'modified',
- defaultContent: '',
- className: 'none'
- },
- {
- title: 'Tags',
- data: 'tags',
- defaultContent: '',
- className: 'none'
- },
- {
- title: lang.active,
- data: 'active',
- defaultContent: '',
- responsivePriority: 4,
- render: function (data, type) {
- return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
- }
- },
- {
- title: lang.action,
- data: 'action',
- className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md',
- responsivePriority: 6,
- defaultContent: ''
- },
- {
- title: "",
- data: 'quota.sortBy',
- responsivePriority: 8,
- defaultContent: '',
- className: "d-none"
- },
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 1
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 2
+ },
+ {
+ title: lang.username,
+ data: 'username',
+ responsivePriority: 3,
+ defaultContent: ''
+ },
+ {
+ title: lang.domain_quota,
+ data: 'quota.value',
+ responsivePriority: 8,
+ defaultContent: '',
+ orderData: 23
+ },
+ {
+ title: lang.last_mail_login,
+ data: 'last_mail_login',
+ defaultContent: '',
+ responsivePriority: 7,
+ render: function (data, type) {
+ res = data.split("/");
+ return '<div class="badge bg-info mb-2">IMAP @ ' + unix_time_format(Number(res[0])) + '</div><br>' +
+ '<div class="badge bg-info mb-2">POP3 @ ' + unix_time_format(Number(res[1])) + '</div><br>' +
+ '<div class="badge bg-info">SMTP @ ' + unix_time_format(Number(res[2])) + '</div>';
+ }
+ },
+ {
+ title: lang.last_pw_change,
+ data: 'last_pw_change',
+ defaultContent: ''
+ },
+ {
+ title: lang.in_use,
+ data: 'in_use',
+ defaultContent: '',
+ responsivePriority: 9,
+ className: 'dt-data-w100'
+ },
+ {
+ title: lang.fname,
+ data: 'name',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: lang.domain,
+ data: 'domain',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: lang.tls_enforce_in,
+ data: 'tls_enforce_in',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: lang.tls_enforce_out,
+ data: 'tls_enforce_out',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: 'SMTP',
+ data: 'smtp_access',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: 'IMAP',
+ data: 'imap_access',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: 'POP3',
+ data: 'pop3_access',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: 'SIEVE',
+ data: 'sieve_access',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: lang.quarantine_notification,
+ data: 'quarantine_notification',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: lang.quarantine_category,
+ data: 'quarantine_category',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: lang.msg_num,
+ data: 'messages',
+ defaultContent: '',
+ responsivePriority: 5
+ },
+ {
+ title: lang.created_on,
+ data: 'created',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: lang.last_modified,
+ data: 'modified',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: 'Tags',
+ data: 'tags',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: lang.active,
+ data: 'active',
+ defaultContent: '',
+ responsivePriority: 4,
+ render: function (data, type) {
+ return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
+ }
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md',
+ responsivePriority: 6,
+ defaultContent: ''
+ },
+ {
+ title: "",
+ data: 'quota.sortBy',
+ responsivePriority: 8,
+ defaultContent: '',
+ className: "d-none"
+ },
]
});
@@ -1118,15 +1121,16 @@ jQuery(function($){
}
var table = $('#templates_mbox_table').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
language: lang_datatables,
- order:[[2, 'desc']],
+ order: [[2, 'desc']],
initComplete: function(){
hideTableExpandCollapseBtn('#tab-templates-mbox', '#templates_mbox_table');
},
@@ -1175,17 +1179,17 @@ jQuery(function($){
item.attributes.quarantine_category = lang.q_all;
}
-
+
if (item.template.toLowerCase() == "default"){
- item.action = '<div class="btn-group">' +
- '<a href="/edit/template/' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
- '</div>';
+ item.action = '<div class="btn-group">' +
+ '<a href="/edit/template/' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
+ '</div>';
}
else {
- item.action = '<div class="btn-group">' +
- '<a href="/edit/template/' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
- '<a href="#" data-action="delete_selected" data-id="single-template" data-api-url="delete/mailbox/template" data-item="' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
- '</div>';
+ item.action = '<div class="btn-group">' +
+ '<a href="/edit/template/' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
+ '<a href="#" data-action="delete_selected" data-id="single-template" data-api-url="delete/mailbox/template" data-item="' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
+ '</div>';
}
if (Array.isArray(item.attributes.tags)){
@@ -1230,12 +1234,12 @@ jQuery(function($){
data: 'template',
responsivePriority: 3,
defaultContent: ''
- },
+ },
{
title: lang.domain_quota,
data: 'attributes.quota',
defaultContent: '',
- },
+ },
{
title: lang.tls_enforce_in,
data: 'attributes.tls_enforce_in',
@@ -1282,7 +1286,7 @@ jQuery(function($){
data: 'attributes.quarantine_category',
defaultContent: '',
className: 'none'
- },
+ },
{
title: lang.force_pw_update,
data: 'attributes.force_pw_update',
@@ -1291,25 +1295,25 @@ jQuery(function($){
render: function (data, type) {
return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
}
- },
+ },
{
title: "rl_frame",
data: 'attributes.rl_frame',
defaultContent: '',
class: 'none',
- },
+ },
{
title: 'rl_value',
data: 'attributes.rl_value',
defaultContent: '',
class: 'none',
- },
+ },
{
title: 'Tags',
data: 'attributes.tags',
defaultContent: '',
className: 'none'
- },
+ },
{
title: lang.active,
data: 'attributes.active',
@@ -1318,7 +1322,7 @@ jQuery(function($){
render: function (data, type) {
return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
}
- },
+ },
{
title: lang.action,
data: 'action',
@@ -1328,7 +1332,7 @@ jQuery(function($){
},
]
});
-
+
table.on('responsive-resize', function (e, datatable, columns){
hideTableExpandCollapseBtn('#tab-templates-mbox', '#templates_mbox_table');
});
@@ -1341,10 +1345,11 @@ jQuery(function($){
}
var table = $('#resource_table').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -1377,65 +1382,65 @@ jQuery(function($){
}
},
columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 1
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 2
- },
- {
- title: lang.description,
- data: 'description',
- responsivePriority: 3,
- defaultContent: ''
- },
- {
- title: lang.alias,
- data: 'name',
- defaultContent: ''
- },
- {
- title: lang.kind,
- data: 'kind',
- defaultContent: ''
- },
- {
- title: lang.domain,
- data: 'domain',
- responsivePriority: 4,
- defaultContent: ''
- },
- {
- title: lang.multiple_bookings,
- data: 'multiple_bookings',
- defaultContent: ''
- },
- {
- title: lang.active,
- data: 'active',
- defaultContent: '',
- render: function (data, type) {
- return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
- }
- },
- {
- title: lang.action,
- data: 'action',
- responsivePriority: 5,
- defaultContent: '',
- className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right'
- },
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 1
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 2
+ },
+ {
+ title: lang.description,
+ data: 'description',
+ responsivePriority: 3,
+ defaultContent: ''
+ },
+ {
+ title: lang.alias,
+ data: 'name',
+ defaultContent: ''
+ },
+ {
+ title: lang.kind,
+ data: 'kind',
+ defaultContent: ''
+ },
+ {
+ title: lang.domain,
+ data: 'domain',
+ responsivePriority: 4,
+ defaultContent: ''
+ },
+ {
+ title: lang.multiple_bookings,
+ data: 'multiple_bookings',
+ defaultContent: ''
+ },
+ {
+ title: lang.active,
+ data: 'active',
+ defaultContent: '',
+ render: function (data, type) {
+ return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
+ }
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ responsivePriority: 5,
+ defaultContent: '',
+ className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right'
+ },
]
});
@@ -1448,14 +1453,14 @@ jQuery(function($){
// Domains
var optgroup = "<optgroup label='" + lang.domains + "'>";
$.each(data.domains, function(index, domain){
- optgroup += "<option value='" + domain + "'>" + domain + "</option>"
+ optgroup += "<option value='" + domain + "'>" + domain + "</option>";
});
- optgroup += "</optgroup>"
+ optgroup += "</optgroup>";
$('#bcc-local-dest').append(optgroup);
// Alias domains
var optgroup = "<optgroup label='" + lang.domain_aliases + "'>";
$.each(data.alias_domains, function(index, alias_domain){
- optgroup += "<option value='" + alias_domain + "'>" + alias_domain + "</option>"
+ optgroup += "<option value='" + alias_domain + "'>" + alias_domain + "</option>";
});
optgroup += "</optgroup>"
$('#bcc-local-dest').append(optgroup);
@@ -1463,9 +1468,9 @@ jQuery(function($){
$.each(data.mailboxes, function(mailbox, aliases){
var optgroup = "<optgroup label='" + mailbox + "'>";
$.each(aliases, function(index, alias){
- optgroup += "<option value='" + alias + "'>" + alias + "</option>"
+ optgroup += "<option value='" + alias + "'>" + alias + "</option>";
});
- optgroup += "</optgroup>"
+ optgroup += "</optgroup>";
$('#bcc-local-dest').append(optgroup);
});
// Finish
@@ -1477,17 +1482,18 @@ jQuery(function($){
$('#bcc_table').DataTable().columns.adjust().responsive.recalc();
return;
}
-
+
var table = $('#bcc_table').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
language: lang_datatables,
- order:[[2, 'desc']],
+ order: [[2, 'desc']],
initComplete: function(){
hideTableExpandCollapseBtn('#collapse-tab-bcc', '#bcc_table');
},
@@ -1514,65 +1520,65 @@ jQuery(function($){
}
},
columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 1
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 2
- },
- {
- title: 'ID',
- data: 'id',
- responsivePriority: 3,
- defaultContent: ''
- },
- {
- title: lang.bcc_type,
- data: 'type',
- defaultContent: ''
- },
- {
- title: lang.bcc_local_dest,
- data: 'local_dest',
- defaultContent: ''
- },
- {
- title: lang.bcc_destinations,
- data: 'bcc_dest',
- defaultContent: ''
- },
- {
- title: lang.domain,
- data: 'domain',
- responsivePriority: 4,
- defaultContent: ''
- },
- {
- title: lang.active,
- data: 'active',
- defaultContent: '',
- render: function (data, type) {
- return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
- }
- },
- {
- title: lang.action,
- data: 'action',
- className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right',
- responsivePriority: 5,
- defaultContent: ''
- },
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 1
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 2
+ },
+ {
+ title: 'ID',
+ data: 'id',
+ responsivePriority: 3,
+ defaultContent: ''
+ },
+ {
+ title: lang.bcc_type,
+ data: 'type',
+ defaultContent: ''
+ },
+ {
+ title: lang.bcc_local_dest,
+ data: 'local_dest',
+ defaultContent: ''
+ },
+ {
+ title: lang.bcc_destinations,
+ data: 'bcc_dest',
+ defaultContent: ''
+ },
+ {
+ title: lang.domain,
+ data: 'domain',
+ responsivePriority: 4,
+ defaultContent: ''
+ },
+ {
+ title: lang.active,
+ data: 'active',
+ defaultContent: '',
+ render: function (data, type) {
+ return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
+ }
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right',
+ responsivePriority: 5,
+ defaultContent: ''
+ },
]
});
@@ -1588,15 +1594,16 @@ jQuery(function($){
}
var table = $('#recipient_map_table').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
language: lang_datatables,
- order:[[2, 'desc']],
+ order: [[2, 'desc']],
initComplete: function(){
hideTableExpandCollapseBtn('#collapse-tab-bcc-filters', '#recipient_map_table');
},
@@ -1605,7 +1612,7 @@ jQuery(function($){
url: "/api/v1/get/recipient_map/all",
dataSrc: function(json){
if (role !== "admin") return null;
-
+
$.each(json, function (i, item) {
item.recipient_map_old = escapeHtml(item.recipient_map_old);
item.recipient_map_new = escapeHtml(item.recipient_map_new);
@@ -1620,58 +1627,58 @@ jQuery(function($){
}
},
columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 1
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 2
- },
- {
- title: 'ID',
- data: 'id',
- responsivePriority: 3,
- defaultContent: ''
- },
- {
- title: lang.recipient_map_old,
- data: 'recipient_map_old',
- defaultContent: ''
- },
- {
- title: lang.recipient_map_new,
- data: 'recipient_map_new',
- defaultContent: '',
- responsivePriority: 4
- },
- {
- title: lang.active,
- data: 'active',
- defaultContent: '',
- render: function (data, type) {
- return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
- }
- },
- {
- title: lang.action,
- data: 'action',
- className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right',
- responsivePriority: 5,
- defaultContent: ''
- },
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 1
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 2
+ },
+ {
+ title: 'ID',
+ data: 'id',
+ responsivePriority: 3,
+ defaultContent: ''
+ },
+ {
+ title: lang.recipient_map_old,
+ data: 'recipient_map_old',
+ defaultContent: ''
+ },
+ {
+ title: lang.recipient_map_new,
+ data: 'recipient_map_new',
+ defaultContent: '',
+ responsivePriority: 4
+ },
+ {
+ title: lang.active,
+ data: 'active',
+ defaultContent: '',
+ render: function (data, type) {
+ return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right',
+ responsivePriority: 5,
+ defaultContent: ''
+ },
]
});
-
+
table.on('responsive-resize', function (e, datatable, columns){
hideTableExpandCollapseBtn('#collapse-tab-bcc-filters', '#recipient_map_table');
});
@@ -1684,15 +1691,16 @@ jQuery(function($){
}
var table = $('#tls_policy_table').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
language: lang_datatables,
- order:[[2, 'desc']],
+ order: [[2, 'desc']],
initComplete: function(){
hideTableExpandCollapseBtn('#tab-tls-policy', '#tls_policy_table');
},
@@ -1701,7 +1709,7 @@ jQuery(function($){
url: "/api/v1/get/tls-policy-map/all",
dataSrc: function(json){
if (role !== "admin") return null;
-
+
$.each(json, function (i, item) {
item.dest = escapeHtml(item.dest);
item.policy = '<b>' + escapeHtml(item.policy) + '</b>';
@@ -1721,63 +1729,63 @@ jQuery(function($){
}
},
columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 1
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 2
- },
- {
- title: 'ID',
- data: 'id',
- responsivePriority: 3,
- defaultContent: ''
- },
- {
- title: lang.tls_map_dest,
- data: 'dest',
- defaultContent: '',
- responsivePriority: 4
- },
- {
- title: lang.tls_map_policy,
- data: 'policy',
- defaultContent: ''
- },
- {
- title: lang.tls_map_parameters,
- data: 'parameters',
- defaultContent: ''
- },
- {
- title: lang.active,
- data: 'active',
- defaultContent: '',
- render: function (data, type) {
- return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
- }
- },
- {
- title: lang.action,
- data: 'action',
- className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right',
- responsivePriority: 5,
- defaultContent: ''
- },
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 1
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 2
+ },
+ {
+ title: 'ID',
+ data: 'id',
+ responsivePriority: 3,
+ defaultContent: ''
+ },
+ {
+ title: lang.tls_map_dest,
+ data: 'dest',
+ defaultContent: '',
+ responsivePriority: 4
+ },
+ {
+ title: lang.tls_map_policy,
+ data: 'policy',
+ defaultContent: ''
+ },
+ {
+ title: lang.tls_map_parameters,
+ data: 'parameters',
+ defaultContent: ''
+ },
+ {
+ title: lang.active,
+ data: 'active',
+ defaultContent: '',
+ render: function (data, type) {
+ return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right',
+ responsivePriority: 5,
+ defaultContent: ''
+ },
]
});
-
+
table.on('responsive-resize', function (e, datatable, columns){
hideTableExpandCollapseBtn('#tab-tls-policy', '#tls_policy_table');
});
@@ -1790,15 +1798,16 @@ jQuery(function($){
}
var table = $('#alias_table').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
language: lang_datatables,
- order:[[2, 'desc']],
+ order: [[2, 'desc']],
initComplete: function(){
hideTableExpandCollapseBtn('#tab-mbox-aliases', '#alias_table');
},
@@ -1849,88 +1858,88 @@ jQuery(function($){
}
},
columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 1
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 2
- },
- {
- title: 'ID',
- data: 'id',
- responsivePriority: 3,
- defaultContent: ''
- },
- {
- title: lang.alias,
- data: 'address',
- responsivePriority: 4,
- defaultContent: ''
- },
- {
- title: lang.target_address,
- data: 'goto',
- defaultContent: ''
- },
- {
- title: lang.domain,
- data: 'domain',
- defaultContent: '',
- responsivePriority: 5,
- },
- {
- title: lang.bcc_destinations,
- data: 'bcc_dest',
- defaultContent: ''
- },
- {
- title: lang.sogo_visible,
- data: 'sogo_visible',
- defaultContent: '',
- render: function(data, type){
- return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
- }
- },
- {
- title: lang.public_comment,
- data: 'public_comment',
- defaultContent: ''
- },
- {
- title: lang.private_comment,
- data: 'private_comment',
- defaultContent: ''
- },
- {
- title: lang.active,
- data: 'active',
- defaultContent: '',
- responsivePriority: 6,
- render: function (data, type) {
- return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
- }
- },
- {
- title: lang.action,
- data: 'action',
- className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right',
- responsivePriority: 5,
- defaultContent: ''
- },
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 1
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 2
+ },
+ {
+ title: 'ID',
+ data: 'id',
+ responsivePriority: 3,
+ defaultContent: ''
+ },
+ {
+ title: lang.alias,
+ data: 'address',
+ responsivePriority: 4,
+ defaultContent: ''
+ },
+ {
+ title: lang.target_address,
+ data: 'goto',
+ defaultContent: ''
+ },
+ {
+ title: lang.domain,
+ data: 'domain',
+ defaultContent: '',
+ responsivePriority: 5,
+ },
+ {
+ title: lang.bcc_destinations,
+ data: 'bcc_dest',
+ defaultContent: ''
+ },
+ {
+ title: lang.sogo_visible,
+ data: 'sogo_visible',
+ defaultContent: '',
+ render: function(data, type){
+ return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.public_comment,
+ data: 'public_comment',
+ defaultContent: ''
+ },
+ {
+ title: lang.private_comment,
+ data: 'private_comment',
+ defaultContent: ''
+ },
+ {
+ title: lang.active,
+ data: 'active',
+ defaultContent: '',
+ responsivePriority: 6,
+ render: function (data, type) {
+ return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right',
+ responsivePriority: 5,
+ defaultContent: ''
+ },
]
});
-
+
table.on('responsive-resize', function (e, datatable, columns){
hideTableExpandCollapseBtn('#tab-mbox-aliases', '#alias_table');
});
@@ -1943,10 +1952,11 @@ jQuery(function($){
}
var table = $('#aliasdomain_table').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
@@ -1978,50 +1988,50 @@ jQuery(function($){
}
},
columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 1
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 2
- },
- {
- title: lang.alias,
- data: 'alias_domain',
- responsivePriority: 3,
- defaultContent: ''
- },
- {
- title: lang.target_domain,
- data: 'target_domain',
- responsivePriority: 4,
- defaultContent: ''
- },
- {
- title: lang.active,
- data: 'active',
- defaultContent: '',
- render: function (data, type) {
- return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
- }
- },
- {
- title: lang.action,
- data: 'action',
- className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right',
- responsivePriority: 5,
- defaultContent: ''
- },
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 1
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 2
+ },
+ {
+ title: lang.alias,
+ data: 'alias_domain',
+ responsivePriority: 3,
+ defaultContent: ''
+ },
+ {
+ title: lang.target_domain,
+ data: 'target_domain',
+ responsivePriority: 4,
+ defaultContent: ''
+ },
+ {
+ title: lang.active,
+ data: 'active',
+ defaultContent: '',
+ render: function (data, type) {
+ return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right',
+ responsivePriority: 5,
+ defaultContent: ''
+ },
]
});
@@ -2037,15 +2047,16 @@ jQuery(function($){
}
var table = $('#sync_job_table').DataTable({
- responsive: true,
+ responsive: true,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
language: lang_datatables,
- order:[[2, 'desc']],
+ order: [[2, 'desc']],
initComplete: function(){
hideTableExpandCollapseBtn('#tab-syncjobs', '#sync_job_table');
},
@@ -2082,9 +2093,9 @@ jQuery(function($){
item.success = '<i class="text-' + (item.success == 1 ? 'success' : 'danger') + ' bi bi-' + (item.success == 1 ? 'check-lg' : 'x-lg') + '"></i>';
}
if (lang['syncjob_'+item.exit_status]) {
- item.exit_status = lang['syncjob_'+item.exit_status];
+ item.exit_status = lang['syncjob_'+item.exit_status];
} else if (item.success != '-') {
- item.exit_status = lang.syncjob_check_log;
+ item.exit_status = lang.syncjob_check_log;
}
item.exit_status = item.success + ' ' + item.exit_status;
});
@@ -2093,87 +2104,87 @@ jQuery(function($){
}
},
columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 1
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 2
- },
- {
- title: 'ID',
- data: 'id',
- responsivePriority: 3,
- defaultContent: ''
- },
- {
- title: lang.owner,
- data: 'user2',
- responsivePriority: 4,
- defaultContent: ''
- },
- {
- title: 'Server',
- data: 'server_w_port',
- defaultContent: ''
- },
- {
- title: lang.last_run,
- data: 'last_run',
- defaultContent: ''
- },
- {
- title: lang.syncjob_last_run_result,
- data: 'exit_status',
- defaultContent: ''
- },
- {
- title: 'Log',
- data: 'log',
- defaultContent: ''
- },
- {
- title: lang.active,
- data: 'active',
- defaultContent: '',
- render: function (data, type) {
- return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
- }
- },
- {
- title: lang.status,
- data: 'is_running',
- defaultContent: ''
- },
- {
- title: lang.excludes,
- data: 'exclude',
- defaultContent: '',
- className: 'none'
- },
- {
- title: lang.mins_interval,
- data: 'mins_interval',
- defaultContent: '',
- className: 'none'
- },
- {
- title: lang.action,
- data: 'action',
- className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right',
- responsivePriority: 5,
- defaultContent: ''
- },
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 1
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 2
+ },
+ {
+ title: 'ID',
+ data: 'id',
+ responsivePriority: 3,
+ defaultContent: ''
+ },
+ {
+ title: lang.owner,
+ data: 'user2',
+ responsivePriority: 4,
+ defaultContent: ''
+ },
+ {
+ title: 'Server',
+ data: 'server_w_port',
+ defaultContent: ''
+ },
+ {
+ title: lang.last_run,
+ data: 'last_run',
+ defaultContent: ''
+ },
+ {
+ title: lang.syncjob_last_run_result,
+ data: 'exit_status',
+ defaultContent: ''
+ },
+ {
+ title: 'Log',
+ data: 'log',
+ defaultContent: ''
+ },
+ {
+ title: lang.active,
+ data: 'active',
+ defaultContent: '',
+ render: function (data, type) {
+ return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
+ }
+ },
+ {
+ title: lang.status,
+ data: 'is_running',
+ defaultContent: ''
+ },
+ {
+ title: lang.excludes,
+ data: 'exclude',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: lang.mins_interval,
+ data: 'mins_interval',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right',
+ responsivePriority: 5,
+ defaultContent: ''
+ },
]
});
@@ -2189,16 +2200,17 @@ jQuery(function($){
}
var table = $('#filter_table').DataTable({
- responsive: true,
+ responsive: true,
autoWidth: false,
processing: true,
serverSide: false,
stateSave: true,
+ pageLength: pagination_size,
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
"tr" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
language: lang_datatables,
- order:[[2, 'desc']],
+ order: [[2, 'desc']],
initComplete: function(){
hideTableExpandCollapseBtn('#tab-filters', '#filter_table');
},
@@ -2226,64 +2238,64 @@ jQuery(function($){
}
},
columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 1
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 2
- },
- {
- title: 'ID',
- data: 'id',
- responsivePriority: 2,
- defaultContent: ''
- },
- {
- title: lang.active,
- data: 'active',
- responsivePriority: 3,
- defaultContent: ''
- },
- {
- title: 'Type',
- data: 'filter_type',
- responsivePriority: 4,
- defaultContent: ''
- },
- {
- title: lang.owner,
- data: 'username',
- defaultContent: ''
- },
- {
- title: lang.description,
- data: 'script_desc',
- defaultContent: ''
- },
- {
- title: 'Script',
- data: 'script_data',
- defaultContent: '',
- className: 'none'
- },
- {
- title: lang.action,
- data: 'action',
- className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right',
- responsivePriority: 5,
- defaultContent: ''
- },
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 1
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 2
+ },
+ {
+ title: 'ID',
+ data: 'id',
+ responsivePriority: 2,
+ defaultContent: ''
+ },
+ {
+ title: lang.active,
+ data: 'active',
+ responsivePriority: 3,
+ defaultContent: ''
+ },
+ {
+ title: 'Type',
+ data: 'filter_type',
+ responsivePriority: 4,
+ defaultContent: ''
+ },
+ {
+ title: lang.owner,
+ data: 'username',
+ defaultContent: ''
+ },
+ {
+ title: lang.description,
+ data: 'script_desc',
+ defaultContent: ''
+ },
+ {
+ title: 'Script',
+ data: 'script_data',
+ defaultContent: '',
+ className: 'none'
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'dt-sm-head-hidden dt-data-w100 dtr-col-md dt-body-right',
+ responsivePriority: 5,
+ defaultContent: ''
+ },
]
});
@@ -2294,11 +2306,11 @@ jQuery(function($){
function hideTableExpandCollapseBtn(tab, table){
if ($(table).hasClass('collapsed'))
- $(tab).find(".table_collapse_option").show();
+ $(tab).find(".table_collapse_option").show();
else
- $(tab).find(".table_collapse_option").hide();
+ $(tab).find(".table_collapse_option").hide();
}
-
+
// detect element visibility changes
function onVisible(element, callback) {
$(document).ready(function() {
diff --git a/data/web/js/site/qhandler.js b/data/web/js/site/qhandler.js
index 4fcc9634..8a8471f2 100644
--- a/data/web/js/site/qhandler.js
+++ b/data/web/js/site/qhandler.js
@@ -1,71 +1,71 @@
-jQuery(function($){
- var qitem = $('legend').data('hash');
- var qError = $("#qid_error");
- $.ajax({
- url: '/inc/ajax/qitem_details.php',
- data: { hash: qitem },
- dataType: 'json',
- success: function(data){
- $('[data-id="qitems_single"]').each(function(index) {
- $(this).attr("data-item", qitem);
- });
- $('#qid_detail_subj').text(data.subject);
- $('#qid_detail_hfrom').text(data.header_from);
- $('#qid_detail_efrom').text(data.env_from);
- $('#qid_detail_score').html('');
- $('#qid_detail_symbols').html('');
- $('#qid_detail_recipients').html('');
- $('#qid_detail_fuzzy').html('');
- if (typeof data.fuzzy_hashes === 'object' && data.fuzzy_hashes !== null && data.fuzzy_hashes.length !== 0) {
- $.each(data.fuzzy_hashes, function (index, value) {
- $('#qid_detail_fuzzy').append('<p style="font-family:monospace">' + value + '</p>');
- });
- } else {
- $('#qid_detail_fuzzy').append('-');
- }
- if (typeof data.symbols !== 'undefined') {
- data.symbols.sort(function (a, b) {
- if (a.score === 0) return 1
- if (b.score === 0) return -1
- if (b.score < 0 && a.score < 0) {
- return a.score - b.score
- }
- if (b.score > 0 && a.score > 0) {
- return b.score - a.score
- }
- return b.score - a.score
- })
- $.each(data.symbols, function (index, value) {
- var highlightClass = ''
- if (value.score > 0) highlightClass = 'negative'
- else if (value.score < 0) highlightClass = 'positive'
- else highlightClass = 'neutral'
- $('#qid_detail_symbols').append('<span data-bs-toggle="tooltip" class="rspamd-symbol ' + highlightClass + '" title="' + (value.options ? value.options.join(', ') : '') + '">' + value.name + ' (<span class="score">' + value.score + '</span>)</span>');
- });
- $('[data-bs-toggle="tooltip"]').tooltip()
- }
- if (typeof data.score !== 'undefined' && typeof data.action !== 'undefined') {
- if (data.action === "add header") {
- $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + data.score + '</b> - ' + lang.junk_folder + '</span>');
- } else if (data.action === "reject") {
- $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-danger"><b>' + data.score + '</b> - ' + lang.rejected + '</span>');
- } else if (data.action === "rewrite subject") {
- $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + data.score + '</b> - ' + lang.rewrite_subject + '</span>');
- }
- }
- if (typeof data.recipients !== 'undefined') {
- $.each(data.recipients, function(index, value) {
- var elem = $('<span class="mail-address-item"></span>');
- elem.text(value.address + ' (' + value.type.toUpperCase() + ')');
- $('#qid_detail_recipients').append(elem);
- });
- }
- },
- error: function(data){
- if (typeof data.error !== 'undefined') {
- qError.text("Error loading quarantine item");
- qError.show();
- }
- }
- });
-});
+jQuery(function($){
+ var qitem = $('legend').data('hash');
+ var qError = $("#qid_error");
+ $.ajax({
+ url: '/inc/ajax/qitem_details.php',
+ data: { hash: qitem },
+ dataType: 'json',
+ success: function(data){
+ $('[data-id="qitems_single"]').each(function(index) {
+ $(this).attr("data-item", qitem);
+ });
+ $('#qid_detail_subj').text(data.subject);
+ $('#qid_detail_hfrom').text(data.header_from);
+ $('#qid_detail_efrom').text(data.env_from);
+ $('#qid_detail_score').html('');
+ $('#qid_detail_symbols').html('');
+ $('#qid_detail_recipients').html('');
+ $('#qid_detail_fuzzy').html('');
+ if (typeof data.fuzzy_hashes === 'object' && data.fuzzy_hashes !== null && data.fuzzy_hashes.length !== 0) {
+ $.each(data.fuzzy_hashes, function (index, value) {
+ $('#qid_detail_fuzzy').append('<p style="font-family:monospace">' + value + '</p>');
+ });
+ } else {
+ $('#qid_detail_fuzzy').append('-');
+ }
+ if (typeof data.symbols !== 'undefined') {
+ data.symbols.sort(function (a, b) {
+ if (a.score === 0) return 1;
+ if (b.score === 0) return -1;
+ if (b.score < 0 && a.score < 0) {
+ return a.score - b.score;
+ }
+ if (b.score > 0 && a.score > 0) {
+ return b.score - a.score;
+ }
+ return b.score - a.score;
+ })
+ $.each(data.symbols, function (index, value) {
+ var highlightClass = '';
+ if (value.score > 0) highlightClass = 'negative';
+ else if (value.score < 0) highlightClass = 'positive';
+ else highlightClass = 'neutral';
+ $('#qid_detail_symbols').append('<span data-bs-toggle="tooltip" class="rspamd-symbol ' + highlightClass + '" title="' + (value.options ? value.options.join(', ') : '') + '">' + value.name + ' (<span class="score">' + value.score + '</span>)</span>');
+ });
+ $('[data-bs-toggle="tooltip"]').tooltip();
+ }
+ if (typeof data.score !== 'undefined' && typeof data.action !== 'undefined') {
+ if (data.action === "add header") {
+ $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + data.score + '</b> - ' + lang.junk_folder + '</span>');
+ } else if (data.action === "reject") {
+ $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-danger"><b>' + data.score + '</b> - ' + lang.rejected + '</span>');
+ } else if (data.action === "rewrite subject") {
+ $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + data.score + '</b> - ' + lang.rewrite_subject + '</span>');
+ }
+ }
+ if (typeof data.recipients !== 'undefined') {
+ $.each(data.recipients, function(index, value) {
+ var elem = $('<span class="mail-address-item"></span>');
+ elem.text(value.address + ' (' + value.type.toUpperCase() + ')');
+ $('#qid_detail_recipients').append(elem);
+ });
+ }
+ },
+ error: function(data){
+ if (typeof data.error !== 'undefined') {
+ qError.text("Error loading quarantine item");
+ qError.show();
+ }
+ }
+ });
+});
diff --git a/data/web/js/site/quarantine.js b/data/web/js/site/quarantine.js
index 7da3a7dd..e69863f7 100644
--- a/data/web/js/site/quarantine.js
+++ b/data/web/js/site/quarantine.js
@@ -1,286 +1,297 @@
-// Base64 functions
-var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(r){var t,e,o,a,h,n,c,d="",C=0;for(r=Base64._utf8_encode(r);C<r.length;)a=(t=r.charCodeAt(C++))>>2,h=(3&t)<<4|(e=r.charCodeAt(C++))>>4,n=(15&e)<<2|(o=r.charCodeAt(C++))>>6,c=63&o,isNaN(e)?n=c=64:isNaN(o)&&(c=64),d=d+this._keyStr.charAt(a)+this._keyStr.charAt(h)+this._keyStr.charAt(n)+this._keyStr.charAt(c);return d},decode:function(r){var t,e,o,a,h,n,c="",d=0;for(r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");d<r.length;)t=this._keyStr.indexOf(r.charAt(d++))<<2|(a=this._keyStr.indexOf(r.charAt(d++)))>>4,e=(15&a)<<4|(h=this._keyStr.indexOf(r.charAt(d++)))>>2,o=(3&h)<<6|(n=this._keyStr.indexOf(r.charAt(d++))),c+=String.fromCharCode(t),64!=h&&(c+=String.fromCharCode(e)),64!=n&&(c+=String.fromCharCode(o));return c=Base64._utf8_decode(c)},_utf8_encode:function(r){r=r.replace(/\r\n/g,"\n");for(var t="",e=0;e<r.length;e++){var o=r.charCodeAt(e);o<128?t+=String.fromCharCode(o):o>127&&o<2048?(t+=String.fromCharCode(o>>6|192),t+=String.fromCharCode(63&o|128)):(t+=String.fromCharCode(o>>12|224),t+=String.fromCharCode(o>>6&63|128),t+=String.fromCharCode(63&o|128))}return t},_utf8_decode:function(r){for(var t="",e=0,o=c1=c2=0;e<r.length;)(o=r.charCodeAt(e))<128?(t+=String.fromCharCode(o),e++):o>191&&o<224?(c2=r.charCodeAt(e+1),t+=String.fromCharCode((31&o)<<6|63&c2),e+=2):(c2=r.charCodeAt(e+1),c3=r.charCodeAt(e+2),t+=String.fromCharCode((15&o)<<12|(63&c2)<<6|63&c3),e+=3);return t}};
-
-jQuery(function($){
- acl_data = JSON.parse(acl);
- // http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
- var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};
- function escapeHtml(n){return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})}
- 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]}
- $(".refresh_table").on('click', function(e) {
- e.preventDefault();
- var table_name = $(this).data('table');
- $('#' + table_name).DataTable().ajax.reload();
- });
- function draw_quarantine_table() {
- var table = $('#quarantinetable').DataTable({
- responsive: true,
- processing: true,
- serverSide: false,
- stateSave: true,
- dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
- "tr" +
- "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
- language: lang_datatables,
- initComplete: function(){
- hideTableExpandCollapseBtn('#quarantinetable');
- },
- ajax: {
- type: "GET",
- url: "/api/v1/get/quarantine/all",
- dataSrc: function(data){
- $.each(data, function (i, item) {
- if (item.subject === null) {
- item.subject = '';
- } else {
- item.subject = escapeHtml(item.subject);
- }
- if (item.score === null) {
- item.score = '-';
- }
- if (item.virus_flag > 0) {
- item.virus = '<span class="badge fs-6 bg-danger">' + lang.high_danger + '</span>';
- } else {
- item.virus = '<span class="badge fs-6 bg-secondary">' + lang.neutral_danger + '</span>';
- }
- if (item.action === "reject") {
- item.rspamdaction = '<span class="badge fs-6 bg-danger">' + lang.rejected + '</span>';
- } else if (item.action === "add header") {
- item.rspamdaction = '<span class="badge fs-6 bg-warning">' + lang.junk_folder + '</span>';
- } else if (item.action === "rewrite subject") {
- item.rspamdaction = '<span class="badge fs-6 bg-warning">' + lang.rewrite_subject + '</span>';
- }
- if(item.notified > 0) {
- item.notified = '✔';
- } else {
- item.notified = '✖';
- }
- if (acl_data.login_as === 1) {
- item.action = '<div class="btn-group">' +
- '<a href="#" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-info show_qid_info"><i class="bi bi-box-arrow-up-right"></i> ' + lang.show_item + '</a>' +
- '<a href="#" data-action="delete_selected" data-id="del-single-qitem" data-api-url="delete/qitem" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
- '</div>';
- }
- else {
- item.action = '<div class="btn-group">' +
- '<a href="#" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-info show_qid_info"><i class="bi bi-file-earmark-text"></i> ' + lang.show_item + '</a>' +
- '</div>';
- }
- item.chkbox = '<input type="checkbox" data-id="qitems" name="multi_select" value="' + item.id + '" />';
- });
-
- return data;
- }
- },
- columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: 'ID',
- data: 'id',
- defaultContent: ''
- },
- {
- title: lang.qid,
- data: 'qid',
- defaultContent: ''
- },
- {
- title: lang.sender,
- data: 'sender',
- defaultContent: ''
- },
- {
- title: lang.subj,
- data: 'subject',
- defaultContent: ''
- },
- {
- title: lang.rspamd_result,
- data: 'rspamdaction',
- defaultContent: ''
- },
- {
- title: lang.rcpt,
- data: 'rcpt',
- defaultContent: ''
- },
- {
- title: lang.danger,
- data: 'virus',
- defaultContent: ''
- },
- {
- title: lang.spam_score,
- data: 'score',
- defaultContent: ''
- },
- {
- title: lang.notified,
- data: 'notified',
- defaultContent: ''
- },
- {
- title: lang.received,
- data: 'created',
- defaultContent: '',
- createdCell: function(td, cellData) {
- $(td).attr({
- "data-order": cellData,
- "data-sort": cellData
- });
-
- var date = new Date(cellData ? cellData * 1000 : 0);
- var dateString = date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
- $(td).html(dateString);
- }
- },
- {
- title: lang.action,
- data: 'action',
- className: 'text-md-end dt-sm-head-hidden dt-body-right',
- defaultContent: ''
- },
- ]
- });
-
- table.on('responsive-resize', function (e, datatable, columns){
- hideTableExpandCollapseBtn('#quarantinetable');
- });
- }
-
- $('body').on('click', '.show_qid_info', function (e) {
- e.preventDefault();
- var qitem = $(this).attr('data-item');
- var qError = $("#qid_error");
-
- $('#qidDetailModal').modal('show');
- qError.hide();
-
- $.ajax({
- url: '/inc/ajax/qitem_details.php',
- data: { id: qitem },
- dataType: 'json',
- success: function(data){
-
- $('[data-id="qitems_single"]').each(function(index) {
- $(this).attr("data-item", qitem);
- });
-
- $("#quick_download_link").attr("onclick", "window.open('/inc/ajax/qitem_details.php?id=" + qitem + "&eml', '_blank')");
- $("#quick_release_link").attr("onclick", "window.open('/inc/ajax/qitem_details.php?id=" + qitem + "&quick_release', '_blank')");
- $("#quick_delete_link").attr("onclick", "window.open('/inc/ajax/qitem_details.php?id=" + qitem + "&quick_delete', '_blank')");
-
- $('#qid_detail_subj').text(data.subject);
- $('#qid_detail_hfrom').text(data.header_from);
- $('#qid_detail_efrom').text(data.env_from);
- $('#qid_detail_score').html('');
- $('#qid_detail_recipients').html('');
- $('#qid_detail_symbols').html('');
- $('#qid_detail_fuzzy').html('');
- if (typeof data.symbols !== 'undefined') {
- data.symbols.sort(function (a, b) {
- if (a.score === 0) return 1
- if (b.score === 0) return -1
- if (b.score < 0 && a.score < 0) {
- return a.score - b.score
- }
- if (b.score > 0 && a.score > 0) {
- return b.score - a.score
- }
- return b.score - a.score
- })
- $.each(data.symbols, function (index, value) {
- var highlightClass = ''
- if (value.score > 0) highlightClass = 'negative'
- else if (value.score < 0) highlightClass = 'positive'
- else highlightClass = 'neutral'
- $('#qid_detail_symbols').append('<span data-bs-toggle="tooltip" class="rspamd-symbol ' + highlightClass + '" title="' + (value.options ? value.options.join(', ') : '') + '">' + value.name + ' (<span class="score">' + value.score + '</span>)</span>');
- });
- $('[data-bs-toggle="tooltip"]').tooltip()
- }
- if (typeof data.fuzzy_hashes === 'object' && data.fuzzy_hashes !== null && data.fuzzy_hashes.length !== 0) {
- $.each(data.fuzzy_hashes, function (index, value) {
- $('#qid_detail_fuzzy').append('<p style="font-family:monospace">' + value + '</p>');
- });
- } else {
- $('#qid_detail_fuzzy').append('-');
- }
- if (typeof data.score !== 'undefined' && typeof data.action !== 'undefined') {
- if (data.action == "add header") {
- $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + data.score + '</b> - ' + lang.junk_folder + '</span>');
- } else if (data.action == "reject") {
- $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-danger"><b>' + data.score + '</b> - ' + lang.rejected + '</span>');
- } else if (data.action == "rewrite subject") {
- $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + data.score + '</b> - ' + lang.rewrite_subject + '</span>');
- }
- }
- if (typeof data.recipients !== 'undefined') {
- $.each(data.recipients, function(index, value) {
- var elem = $('<span class="mail-address-item"></span>');
- elem.text(value.address + ' (' + value.type.toUpperCase() + ')');
- $('#qid_detail_recipients').append(elem);
- });
- }
- $('#qid_detail_text').text(data.text_plain);
- $('#qid_detail_text_from_html').text(data.text_html);
- var qAtts = $("#qid_detail_atts");
- if (typeof data.attachments !== 'undefined') {
- qAtts.text('');
- $.each(data.attachments, function(index, value) {
- qAtts.append(
- '<p><a href="/inc/ajax/qitem_details.php?id=' + qitem + '&att=' + index + '" target="_blank">' + value[0] + '</a> (' + value[1] + ')' +
- ' - <small><a href="' + value[3] + '" target="_blank">' + lang.check_hash + '</a></small></p>'
- );
- });
- }
- else {
- qAtts.text('-');
- }
- },
- error: function(data){
- if (typeof data.error !== 'undefined') {
- $('#qid_detail_subj').text('-');
- $('#qid_detail_hfrom').text('-');
- $('#qid_detail_efrom').text('-');
- $('#qid_detail_score').html('-');
- $('#qid_detail_recipients').html('-');
- $('#qid_detail_symbols').html('-');
- $('#qid_detail_fuzzy').html('-');
- $('#qid_detail_text').text('-');
- $('#qid_detail_text_from_html').text('-');
- qError.text("Error loading quarantine item");
- qError.show();
- }
- }
- });
- });
-
- $('body').on('click', 'span.footable-toggle', function () {
- event.stopPropagation();
- })
-
- // Initial table drawings
- draw_quarantine_table();
-
-
- function hideTableExpandCollapseBtn(table){
- if ($(table).hasClass('collapsed'))
- $(".table_collapse_option").show();
- else
- $(".table_collapse_option").hide();
- }
-});
+// Base64 functions
+var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(r){var t,e,o,a,h,n,c,d="",C=0;for(r=Base64._utf8_encode(r);C<r.length;)a=(t=r.charCodeAt(C++))>>2,h=(3&t)<<4|(e=r.charCodeAt(C++))>>4,n=(15&e)<<2|(o=r.charCodeAt(C++))>>6,c=63&o,isNaN(e)?n=c=64:isNaN(o)&&(c=64),d=d+this._keyStr.charAt(a)+this._keyStr.charAt(h)+this._keyStr.charAt(n)+this._keyStr.charAt(c);return d},decode:function(r){var t,e,o,a,h,n,c="",d=0;for(r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");d<r.length;)t=this._keyStr.indexOf(r.charAt(d++))<<2|(a=this._keyStr.indexOf(r.charAt(d++)))>>4,e=(15&a)<<4|(h=this._keyStr.indexOf(r.charAt(d++)))>>2,o=(3&h)<<6|(n=this._keyStr.indexOf(r.charAt(d++))),c+=String.fromCharCode(t),64!=h&&(c+=String.fromCharCode(e)),64!=n&&(c+=String.fromCharCode(o));return c=Base64._utf8_decode(c)},_utf8_encode:function(r){r=r.replace(/\r\n/g,"\n");for(var t="",e=0;e<r.length;e++){var o=r.charCodeAt(e);o<128?t+=String.fromCharCode(o):o>127&&o<2048?(t+=String.fromCharCode(o>>6|192),t+=String.fromCharCode(63&o|128)):(t+=String.fromCharCode(o>>12|224),t+=String.fromCharCode(o>>6&63|128),t+=String.fromCharCode(63&o|128))}return t},_utf8_decode:function(r){for(var t="",e=0,o=c1=c2=0;e<r.length;)(o=r.charCodeAt(e))<128?(t+=String.fromCharCode(o),e++):o>191&&o<224?(c2=r.charCodeAt(e+1),t+=String.fromCharCode((31&o)<<6|63&c2),e+=2):(c2=r.charCodeAt(e+1),c3=r.charCodeAt(e+2),t+=String.fromCharCode((15&o)<<12|(63&c2)<<6|63&c3),e+=3);return t}};
+
+jQuery(function($){
+ acl_data = JSON.parse(acl);
+ // http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
+ var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};
+ function escapeHtml(n){return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})}
+ 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]}
+ $(".refresh_table").on('click', function(e) {
+ e.preventDefault();
+ var table_name = $(this).data('table');
+ $('#' + table_name).DataTable().ajax.reload();
+ });
+ function draw_quarantine_table() {
+ var table = $('#quarantinetable').DataTable({
+ responsive: true,
+ processing: true,
+ serverSide: false,
+ stateSave: true,
+ pageLength: pagination_size,
+ order: [[2, 'desc']],
+ lengthMenu: [
+ [10, 25, 50, 100, -1],
+ [10, 25, 50, 100, 'all']
+ ],
+ pagingType: 'first_last_numbers',
+ aColumns: [
+ { sWidth: '8.25%' },
+ { sClass: 'classDataTable' }
+ ],
+ dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
+ "tr" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ language: lang_datatables,
+ initComplete: function(){
+ hideTableExpandCollapseBtn('#quarantinetable');
+ },
+ ajax: {
+ type: "GET",
+ url: "/api/v1/get/quarantine/all",
+ dataSrc: function(data){
+ $.each(data, function (i, item) {
+ if (item.subject === null) {
+ item.subject = '';
+ } else {
+ item.subject = escapeHtml(item.subject);
+ }
+ if (item.score === null) {
+ item.score = '-';
+ }
+ if (item.virus_flag > 0) {
+ item.virus = '<span class="badge fs-6 bg-danger">' + lang.high_danger + '</span>';
+ } else {
+ item.virus = '<span class="badge fs-6 bg-secondary">' + lang.neutral_danger + '</span>';
+ }
+ if (item.action === "reject") {
+ item.rspamdaction = '<span class="badge fs-6 bg-danger">' + lang.rejected + '</span>';
+ } else if (item.action === "add header") {
+ item.rspamdaction = '<span class="badge fs-6 bg-warning">' + lang.junk_folder + '</span>';
+ } else if (item.action === "rewrite subject") {
+ item.rspamdaction = '<span class="badge fs-6 bg-warning">' + lang.rewrite_subject + '</span>';
+ }
+ if(item.notified > 0) {
+ item.notified = '✔';
+ } else {
+ item.notified = '✖';
+ }
+ if (acl_data.login_as === 1) {
+ item.action = '<div class="btn-group">' +
+ '<a href="#" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-info show_qid_info"><i class="bi bi-box-arrow-up-right"></i> ' + lang.show_item + '</a>' +
+ '<a href="#" data-action="delete_selected" data-id="del-single-qitem" data-api-url="delete/qitem" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
+ '</div>';
+ }
+ else {
+ item.action = '<div class="btn-group">' +
+ '<a href="#" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-info show_qid_info"><i class="bi bi-file-earmark-text"></i> ' + lang.show_item + '</a>' +
+ '</div>';
+ }
+ item.chkbox = '<input type="checkbox" data-id="qitems" name="multi_select" value="' + item.id + '" />';
+ });
+
+ return data;
+ }
+ },
+ columns: [
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: 'ID',
+ data: 'id',
+ defaultContent: ''
+ },
+ {
+ title: lang.qid,
+ data: 'qid',
+ defaultContent: ''
+ },
+ {
+ title: lang.sender,
+ data: 'sender',
+ className: 'senders-mw220',
+ defaultContent: ''
+ },
+ {
+ title: lang.subj,
+ data: 'subject',
+ defaultContent: ''
+ },
+ {
+ title: lang.rspamd_result,
+ data: 'rspamdaction',
+ defaultContent: ''
+ },
+ {
+ title: lang.rcpt,
+ data: 'rcpt',
+ defaultContent: ''
+ },
+ {
+ title: lang.danger,
+ data: 'virus',
+ defaultContent: ''
+ },
+ {
+ title: lang.spam_score,
+ data: 'score',
+ defaultContent: ''
+ },
+ {
+ title: lang.notified,
+ data: 'notified',
+ defaultContent: ''
+ },
+ {
+ title: lang.received,
+ data: 'created',
+ defaultContent: '',
+ createdCell: function(td, cellData) {
+ $(td).attr({
+ "data-order": cellData,
+ "data-sort": cellData
+ });
+
+ var date = new Date(cellData ? cellData * 1000 : 0);
+ var dateString = date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
+ $(td).html(dateString);
+ }
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'text-md-end dt-sm-head-hidden dt-body-right',
+ defaultContent: ''
+ },
+ ]
+ });
+
+ table.on('responsive-resize', function (e, datatable, columns){
+ hideTableExpandCollapseBtn('#quarantinetable');
+ });
+ }
+
+ $('body').on('click', '.show_qid_info', function (e) {
+ e.preventDefault();
+ var qitem = $(this).attr('data-item');
+ var qError = $("#qid_error");
+
+ $('#qidDetailModal').modal('show');
+ qError.hide();
+
+ $.ajax({
+ url: '/inc/ajax/qitem_details.php',
+ data: { id: qitem },
+ dataType: 'json',
+ success: function(data){
+
+ $('[data-id="qitems_single"]').each(function(index) {
+ $(this).attr("data-item", qitem);
+ });
+
+ $("#quick_download_link").attr("onclick", "window.open('/inc/ajax/qitem_details.php?id=" + qitem + "&eml', '_blank')");
+ $("#quick_release_link").attr("onclick", "window.open('/inc/ajax/qitem_details.php?id=" + qitem + "&quick_release', '_blank')");
+ $("#quick_delete_link").attr("onclick", "window.open('/inc/ajax/qitem_details.php?id=" + qitem + "&quick_delete', '_blank')");
+
+ $('#qid_detail_subj').text(data.subject);
+ $('#qid_detail_hfrom').text(data.header_from);
+ $('#qid_detail_efrom').text(data.env_from);
+ $('#qid_detail_score').html('');
+ $('#qid_detail_recipients').html('');
+ $('#qid_detail_symbols').html('');
+ $('#qid_detail_fuzzy').html('');
+ if (typeof data.symbols !== 'undefined') {
+ data.symbols.sort(function (a, b) {
+ if (a.score === 0) return 1;
+ if (b.score === 0) return -1;
+ if (b.score < 0 && a.score < 0) {
+ return a.score - b.score;
+ }
+ if (b.score > 0 && a.score > 0) {
+ return b.score - a.score;
+ }
+ return b.score - a.score;
+ })
+ $.each(data.symbols, function (index, value) {
+ var highlightClass = '';
+ if (value.score > 0) highlightClass = 'negative';
+ else if (value.score < 0) highlightClass = 'positive';
+ else highlightClass = 'neutral';
+ $('#qid_detail_symbols').append('<span data-bs-toggle="tooltip" class="rspamd-symbol ' + highlightClass + '" title="' + (value.options ? value.options.join(', ') : '') + '">' + value.name + ' (<span class="score">' + value.score + '</span>)</span>');
+ });
+ $('[data-bs-toggle="tooltip"]').tooltip();
+ }
+ if (typeof data.fuzzy_hashes === 'object' && data.fuzzy_hashes !== null && data.fuzzy_hashes.length !== 0) {
+ $.each(data.fuzzy_hashes, function (index, value) {
+ $('#qid_detail_fuzzy').append('<p style="font-family:monospace">' + value + '</p>');
+ });
+ } else {
+ $('#qid_detail_fuzzy').append('-');
+ }
+ if (typeof data.score !== 'undefined' && typeof data.action !== 'undefined') {
+ if (data.action == "add header") {
+ $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + data.score + '</b> - ' + lang.junk_folder + '</span>');
+ } else if (data.action == "reject") {
+ $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-danger"><b>' + data.score + '</b> - ' + lang.rejected + '</span>');
+ } else if (data.action == "rewrite subject") {
+ $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + data.score + '</b> - ' + lang.rewrite_subject + '</span>');
+ }
+ }
+ if (typeof data.recipients !== 'undefined') {
+ $.each(data.recipients, function(index, value) {
+ var elem = $('<span class="mail-address-item"></span>');
+ elem.text(value.address + ' (' + value.type.toUpperCase() + ')');
+ $('#qid_detail_recipients').append(elem);
+ });
+ }
+ $('#qid_detail_text').text(data.text_plain);
+ $('#qid_detail_text_from_html').text(data.text_html);
+ var qAtts = $("#qid_detail_atts");
+ if (typeof data.attachments !== 'undefined') {
+ qAtts.text('');
+ $.each(data.attachments, function(index, value) {
+ qAtts.append(
+ '<p><a href="/inc/ajax/qitem_details.php?id=' + qitem + '&att=' + index + '" target="_blank">' + value[0] + '</a> (' + value[1] + ')' +
+ ' - <small><a href="' + value[3] + '" target="_blank">' + lang.check_hash + '</a></small></p>'
+ );
+ });
+ }
+ else {
+ qAtts.text('-');
+ }
+ },
+ error: function(data){
+ if (typeof data.error !== 'undefined') {
+ $('#qid_detail_subj').text('-');
+ $('#qid_detail_hfrom').text('-');
+ $('#qid_detail_efrom').text('-');
+ $('#qid_detail_score').html('-');
+ $('#qid_detail_recipients').html('-');
+ $('#qid_detail_symbols').html('-');
+ $('#qid_detail_fuzzy').html('-');
+ $('#qid_detail_text').text('-');
+ $('#qid_detail_text_from_html').text('-');
+ qError.text("Error loading quarantine item");
+ qError.show();
+ }
+ }
+ });
+ });
+
+ $('body').on('click', 'span.footable-toggle', function () {
+ event.stopPropagation();
+ })
+
+ // Initial table drawings
+ draw_quarantine_table();
+
+ function hideTableExpandCollapseBtn(table){
+ if ($(table).hasClass('collapsed'))
+ $(".table_collapse_option").show();
+ else
+ $(".table_collapse_option").hide();
+ }
+});
diff --git a/data/web/js/site/queue.js b/data/web/js/site/queue.js
index ebebaff8..bc4c7369 100644
--- a/data/web/js/site/queue.js
+++ b/data/web/js/site/queue.js
@@ -1,127 +1,128 @@
jQuery(function($){
- $(".refresh_table").on('click', function(e) {
- e.preventDefault();
- var table_name = $(this).data('table');
- $('#' + table_name).DataTable().ajax.reload();
- });
+ $(".refresh_table").on('click', function(e) {
+ e.preventDefault();
+ var table_name = $(this).data('table');
+ $('#' + table_name).DataTable().ajax.reload();
+ });
- 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]}
+ 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]}
- // Queue item
- $('#showQueuedMsg').on('show.bs.modal', function (e) {
- $('#queue_msg_content').text(lang.loading);
- button = $(e.relatedTarget)
- if (button != null) {
- $('#queue_id').text(button.data('queue-id'));
+ // Queue item
+ $('#showQueuedMsg').on('show.bs.modal', function (e) {
+ $('#queue_msg_content').text(lang.loading);
+ button = $(e.relatedTarget)
+ if (button != null) {
+ $('#queue_id').text(button.data('queue-id'));
+ }
+ $.ajax({
+ type: 'GET',
+ url: '/api/v1/get/postcat/' + button.data('queue-id'),
+ dataType: 'text',
+ complete: function (data) {
+ $('#queue_msg_content').text(data.responseText);
}
- $.ajax({
- type: 'GET',
- url: '/api/v1/get/postcat/' + button.data('queue-id'),
- dataType: 'text',
- complete: function (data) {
- $('#queue_msg_content').text(data.responseText);
- }
- });
- })
+ });
+ })
- function draw_queue() {
- // just recalc width if instance already exists
- if ($.fn.DataTable.isDataTable('#queuetable') ) {
- $('#queuetable').DataTable().columns.adjust().responsive.recalc();
- return;
- }
+ function draw_queue() {
+ // just recalc width if instance already exists
+ if ($.fn.DataTable.isDataTable('#queuetable') ) {
+ $('#queuetable').DataTable().columns.adjust().responsive.recalc();
+ return;
+ }
- $('#queuetable').DataTable({
- responsive: true,
- processing: true,
- serverSide: false,
- stateSave: true,
- dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
- "tr" +
- "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
- language: lang_datatables,
- ajax: {
- type: "GET",
- url: "/api/v1/get/mailq/all",
- dataSrc: function(data){
- $.each(data, function (i, item) {
- item.chkbox = '<input type="checkbox" data-id="mailqitems" name="multi_select" value="' + item.queue_id + '" />';
- rcpts = $.map(item.recipients, function(i) {
- return escapeHtml(i);
- });
- item.recipients = rcpts.join('<hr style="margin:1px!important">');
- item.action = '<div class="btn-group">' +
- '<a href="#" data-bs-toggle="modal" data-bs-target="#showQueuedMsg" data-queue-id="' + encodeURI(item.queue_id) + '" class="btn btn-xs btn-secondary">' + lang.show_message + '</a>' +
+ $('#queuetable').DataTable({
+ responsive: true,
+ processing: true,
+ serverSide: false,
+ stateSave: true,
+ pageLength: pagination_size,
+ dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
+ "tr" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ language: lang_datatables,
+ ajax: {
+ type: "GET",
+ url: "/api/v1/get/mailq/all",
+ dataSrc: function(data){
+ $.each(data, function (i, item) {
+ item.chkbox = '<input type="checkbox" data-id="mailqitems" name="multi_select" value="' + item.queue_id + '" />';
+ rcpts = $.map(item.recipients, function(i) {
+ return escapeHtml(i);
+ });
+ item.recipients = rcpts.join('<hr style="margin:1px!important">');
+ item.action = '<div class="btn-group">' +
+ '<a href="#" data-bs-toggle="modal" data-bs-target="#showQueuedMsg" data-queue-id="' + encodeURI(item.queue_id) + '" class="btn btn-xs btn-secondary">' + lang.show_message + '</a>' +
'</div>';
});
return data;
}
},
columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: 'QID',
- data: 'queue_id',
- defaultContent: ''
- },
- {
- title: 'Queue',
- data: 'queue_name',
- defaultContent: ''
- },
- {
- title: lang_admin.arrival_time,
- data: 'arrival_time',
- defaultContent: '',
- render: function (data, type){
- var date = new Date(data ? data * 1000 : 0);
- return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
- }
- },
- {
- title: lang_admin.message_size,
- data: 'message_size',
- defaultContent: '',
- render: function (data, type){
- return humanFileSize(data);
- }
- },
- {
- title: lang_admin.sender,
- data: 'sender',
- defaultContent: ''
- },
- {
- title: lang_admin.recipients,
- data: 'recipients',
- defaultContent: ''
- },
- {
- title: lang_admin.action,
- data: 'action',
- className: 'text-md-end dt-sm-head-hidden dt-body-right',
- defaultContent: ''
- },
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: 'QID',
+ data: 'queue_id',
+ defaultContent: ''
+ },
+ {
+ title: 'Queue',
+ data: 'queue_name',
+ defaultContent: ''
+ },
+ {
+ title: lang_admin.arrival_time,
+ data: 'arrival_time',
+ defaultContent: '',
+ render: function (data, type){
+ var date = new Date(data ? data * 1000 : 0);
+ return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
+ }
+ },
+ {
+ title: lang_admin.message_size,
+ data: 'message_size',
+ defaultContent: '',
+ render: function (data, type){
+ return humanFileSize(data);
+ }
+ },
+ {
+ title: lang_admin.sender,
+ data: 'sender',
+ defaultContent: ''
+ },
+ {
+ title: lang_admin.recipients,
+ data: 'recipients',
+ defaultContent: ''
+ },
+ {
+ title: lang_admin.action,
+ data: 'action',
+ className: 'text-md-end dt-sm-head-hidden dt-body-right',
+ defaultContent: ''
+ },
]
});
}
draw_queue();
-})
\ No newline at end of file
+})
diff --git a/data/web/js/site/user.js b/data/web/js/site/user.js
index d1b9780f..d93e692f 100644
--- a/data/web/js/site/user.js
+++ b/data/web/js/site/user.js
@@ -1,662 +1,667 @@
-// Base64 functions
-var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(r){var t,e,o,a,h,n,c,d="",C=0;for(r=Base64._utf8_encode(r);C<r.length;)a=(t=r.charCodeAt(C++))>>2,h=(3&t)<<4|(e=r.charCodeAt(C++))>>4,n=(15&e)<<2|(o=r.charCodeAt(C++))>>6,c=63&o,isNaN(e)?n=c=64:isNaN(o)&&(c=64),d=d+this._keyStr.charAt(a)+this._keyStr.charAt(h)+this._keyStr.charAt(n)+this._keyStr.charAt(c);return d},decode:function(r){var t,e,o,a,h,n,c="",d=0;for(r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");d<r.length;)t=this._keyStr.indexOf(r.charAt(d++))<<2|(a=this._keyStr.indexOf(r.charAt(d++)))>>4,e=(15&a)<<4|(h=this._keyStr.indexOf(r.charAt(d++)))>>2,o=(3&h)<<6|(n=this._keyStr.indexOf(r.charAt(d++))),c+=String.fromCharCode(t),64!=h&&(c+=String.fromCharCode(e)),64!=n&&(c+=String.fromCharCode(o));return c=Base64._utf8_decode(c)},_utf8_encode:function(r){r=r.replace(/\r\n/g,"\n");for(var t="",e=0;e<r.length;e++){var o=r.charCodeAt(e);o<128?t+=String.fromCharCode(o):o>127&&o<2048?(t+=String.fromCharCode(o>>6|192),t+=String.fromCharCode(63&o|128)):(t+=String.fromCharCode(o>>12|224),t+=String.fromCharCode(o>>6&63|128),t+=String.fromCharCode(63&o|128))}return t},_utf8_decode:function(r){for(var t="",e=0,o=c1=c2=0;e<r.length;)(o=r.charCodeAt(e))<128?(t+=String.fromCharCode(o),e++):o>191&&o<224?(c2=r.charCodeAt(e+1),t+=String.fromCharCode((31&o)<<6|63&c2),e+=2):(c2=r.charCodeAt(e+1),c3=r.charCodeAt(e+2),t+=String.fromCharCode((15&o)<<12|(63&c2)<<6|63&c3),e+=3);return t}};
-$(document).ready(function() {
- // Spam score slider
- var spam_slider = $('#spam_score')[0];
- if (typeof spam_slider !== 'undefined') {
- noUiSlider.create(spam_slider, {
- start: user_spam_score,
- connect: [true, true, true],
- range: {
- 'min': [0], //stepsize is 50.000
- '50%': [10],
- '70%': [20, 5],
- '80%': [50, 10],
- '90%': [100, 100],
- '95%': [1000, 1000],
- 'max': [5000]
- },
- });
- var connect = spam_slider.querySelectorAll('.noUi-connect');
- var classes = ['c-1-color', 'c-2-color', 'c-3-color'];
- for (var i = 0; i < connect.length; i++) {
- connect[i].classList.add(classes[i]);
- }
- spam_slider.noUiSlider.on('update', function (values, handle) {
- $('.spam-ham-score').text('< ' + Math.round(values[0] * 10) / 10);
- $('.spam-spam-score').text(Math.round(values[0] * 10) / 10 + ' - ' + Math.round(values[1] * 10) / 10);
- $('.spam-reject-score').text('> ' + Math.round(values[1] * 10) / 10);
- $('#spam_score_value').val((Math.round(values[0] * 10) / 10) + ',' + (Math.round(values[1] * 10) / 10));
- });
- }
- // syncjobLogModal
- $('#syncjobLogModal').on('show.bs.modal', function(e) {
- var syncjob_id = $(e.relatedTarget).data('syncjob-id');
- $.ajax({
- url: '/inc/ajax/syncjob_logs.php',
- data: { id: syncjob_id },
- dataType: 'text',
- success: function(data){
- $(e.currentTarget).find('#logText').text(data);
- },
- error: function(xhr, status, error) {
- $(e.currentTarget).find('#logText').text(xhr.responseText);
- }
- });
- });
- $(".arrow-toggle").on('click', function(e) { e.preventDefault(); $(this).find('.arrow').toggleClass("animation"); });
- $("#pushover_delete").click(function() { return confirm(lang.delete_ays); });
-
-});
-jQuery(function($){
- // http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
- var entityMap = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": ''',
- '/': '/',
- '`': '`',
- '=': '='
- };
- function escapeHtml(string) {
- return String(string).replace(/[&<>"'`=\/]/g, function (s) {
- return entityMap[s];
- });
- }
- // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
- function validateEmail(email) {
- var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
- return re.test(email);
- }
- function unix_time_format(tm) {
- var date = new Date(tm ? tm * 1000 : 0);
- return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
- }
- acl_data = JSON.parse(acl);
-
- $('.clear-last-logins').on('click', function () {if (confirm(lang.delete_ays)) {last_logins('reset');}})
- $(".login-history").on('click', function(e) {e.preventDefault(); last_logins('get', $(this).data('days'));$(this).addClass('active').siblings().removeClass('active');});
-
- function last_logins(action, days = 7) {
- if (action == 'get') {
- $('.last-login').html('<i class="bi bi-hourglass"></i>' + lang.waiting);
- $.ajax({
- dataType: 'json',
- url: '/api/v1/get/last-login/' + encodeURIComponent(mailcow_cc_username) + '/' + days,
- jsonp: false,
- error: function () {
- console.log('error reading last logins');
- },
- success: function (data) {
- $('.last-login').html();
- if (data.ui.time) {
- $('.last-login').html('<i class="bi bi-person-fill"></i> ' + lang.last_ui_login + ': ' + unix_time_format(data.ui.time));
- } else {
- $('.last-login').text(lang.no_last_login);
- }
- if (data.sasl) {
- $('.last-login').append('<ul class="list-group">');
- $.each(data.sasl, function (i, item) {
- var datetime = new Date(item.datetime.replace(/-/g, "/"));
- var local_datetime = datetime.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
- var service = '<div class="badge fs-6 bg-secondary">' + item.service.toUpperCase() + '</div>';
- var app_password = item.app_password ? ' <a href="/edit/app-passwd/' + item.app_password + '"><i class="bi bi-app-indicator"></i> ' + escapeHtml(item.app_password_name || "App") + '</a>' : '';
- var real_rip = item.real_rip.startsWith("Web") ? item.real_rip : '<a href="https://bgp.he.net/ip/' + item.real_rip + '" target="_blank">' + item.real_rip + "</a>";
- var ip_location = item.location ? ' <span class="flag-icon flag-icon-' + item.location.toLowerCase() + '"></span>' : '';
- var ip_data = real_rip + ip_location + app_password;
- $(".last-login").append('<li class="list-group-item">' + local_datetime + " " + service + " " + lang.from + " " + ip_data + "</li>");
- })
- $('.last-login').append('</ul>');
- }
- }
- })
- } else if (action == 'reset') {
- $.ajax({
- dataType: 'json',
- url: '/api/v1/get/reset-last-login/' + encodeURIComponent(mailcow_cc_username),
- jsonp: false,
- error: function () {
- console.log('cannot reset last logins');
- },
- success: function (data) {
- last_logins('get');
- }
- })
- }
- }
-
- function draw_tla_table() {
- // just recalc width if instance already exists
- if ($.fn.DataTable.isDataTable('#tla_table') ) {
- $('#tla_table').DataTable().columns.adjust().responsive.recalc();
- return;
- }
-
- $('#tla_table').DataTable({
- responsive: true,
- processing: true,
- serverSide: false,
- stateSave: true,
- dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
- "tr" +
- "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
- language: lang_datatables,
- ajax: {
- type: "GET",
- url: "/api/v1/get/time_limited_aliases",
- dataSrc: function(data){
- console.log(data);
- $.each(data, function (i, item) {
- if (acl_data.spam_alias === 1) {
- item.action = '<div class="btn-group">' +
- '<a href="#" data-action="delete_selected" data-id="single-tla" data-api-url="delete/time_limited_alias" data-item="' + encodeURIComponent(item.address) + '" class="btn btn-xs btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
- '</div>';
- item.chkbox = '<input type="checkbox" data-id="tla" name="multi_select" value="' + encodeURIComponent(item.address) + '" />';
- item.address = escapeHtml(item.address);
- }
- else {
- item.chkbox = '<input type="checkbox" disabled />';
- item.action = '<span>-</span>';
- }
- });
-
- return data;
- }
- },
- columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: lang.alias,
- data: 'address',
- defaultContent: ''
- },
- {
- title: lang.alias_valid_until,
- data: 'validity',
- defaultContent: '',
- render: function (data, type) {
- var date = new Date(data ? data * 1000 : 0);
- return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
- }
- },
- {
- title: lang.created_on,
- data: 'created',
- defaultContent: '',
- render: function (data, type) {
- var date = new Date(data.replace(/-/g, "/"));
- return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
- }
- },
- {
- title: lang.action,
- data: 'action',
- className: 'text-md-end dt-sm-head-hidden dt-body-right',
- defaultContent: ''
- }
- ]
- });
- }
- function draw_sync_job_table() {
- // just recalc width if instance already exists
- if ($.fn.DataTable.isDataTable('#sync_job_table') ) {
- $('#sync_job_table').DataTable().columns.adjust().responsive.recalc();
- return;
- }
-
- $('#sync_job_table').DataTable({
- responsive: true,
- processing: true,
- serverSide: false,
- stateSave: true,
- dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
- "tr" +
- "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
- language: lang_datatables,
- ajax: {
- type: "GET",
- url: '/api/v1/get/syncjobs/' + encodeURIComponent(mailcow_cc_username) + '/no_log',
- dataSrc: function(data){
- console.log(data);
- $.each(data, function (i, item) {
- item.user1 = escapeHtml(item.user1);
- item.log = '<a href="#syncjobLogModal" data-bs-toggle="modal" data-syncjob-id="' + item.id + '">' + lang.open_logs + '</a>'
- if (!item.exclude > 0) {
- item.exclude = '-';
- } else {
- item.exclude = '<code>' + escapeHtml(item.exclude) + '</code>';
- }
- item.server_w_port = escapeHtml(item.user1 + '@' + item.host1 + ':' + item.port1);
- if (acl_data.syncjobs === 1) {
- item.action = '<div class="btn-group">' +
- '<a href="/edit/syncjob/' + item.id + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
- '<a href="#" data-action="delete_selected" data-id="single-syncjob" data-api-url="delete/syncjob" data-item="' + item.id + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
- '</div>';
- item.chkbox = '<input type="checkbox" data-id="syncjob" name="multi_select" value="' + item.id + '" />';
- }
- else {
- item.action = '<span>-</span>';
- item.chkbox = '<input type="checkbox" disabled />';
- }
- if (item.is_running == 1) {
- item.is_running = '<span id="active-script" class="badge fs-6 bg-success">' + lang.running + '</span>';
- } else {
- item.is_running = '<span id="inactive-script" class="badge fs-6 bg-warning">' + lang.waiting + '</span>';
- }
- if (!item.last_run > 0) {
- item.last_run = lang.waiting;
- }
- if (item.success == null) {
- item.success = '-';
- item.exit_status = '';
- } else {
- item.success = '<i class="text-' + (item.success == 1 ? 'success' : 'danger') + ' bi bi-' + (item.success == 1 ? 'check-lg' : 'x-lg') + '"></i>';
- }
- if (lang['syncjob_'+item.exit_status]) {
- item.exit_status = lang['syncjob_'+item.exit_status];
- } else if (item.success != '-') {
- item.exit_status = lang.syncjob_check_log;
- }
- item.exit_status = item.success + ' ' + item.exit_status;
- });
-
- return data;
- }
- },
- columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 1
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: '',
- responsivePriority: 2
- },
- {
- title: 'ID',
- data: 'id',
- defaultContent: '',
- responsivePriority: 3
- },
- {
- title: 'Server',
- data: 'server_w_port',
- defaultContent: ''
- },
- {
- title: lang.username,
- data: 'user1',
- defaultContent: '',
- responsivePriority: 3
- },
- {
- title: lang.last_run,
- data: 'last_run',
- defaultContent: ''
- },
- {
- title: lang.syncjob_last_run_result,
- data: 'exit_status',
- defaultContent: ''
- },
- {
- title: 'Log',
- data: 'log',
- defaultContent: ''
- },
- {
- title: lang.active,
- data: 'active',
- defaultContent: '',
- render: function (data, type) {
- return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>'
- }
- },
- {
- title: lang.status,
- data: 'is_running',
- defaultContent: '',
- responsivePriority: 5
- },
- {
- title: lang.encryption,
- data: 'enc1',
- defaultContent: ''
- },
- {
- title: lang.excludes,
- data: 'exclude',
- defaultContent: ''
- },
- {
- title: lang.interval + " (min)",
- data: 'mins_interval',
- defaultContent: ''
- },
- {
- title: lang.action,
- data: 'action',
- className: 'text-md-end dt-sm-head-hidden dt-body-right',
- defaultContent: '',
- responsivePriority: 5
- }
- ]
- });
- }
- function draw_app_passwd_table() {
- // just recalc width if instance already exists
- if ($.fn.DataTable.isDataTable('#app_passwd_table') ) {
- $('#app_passwd_table').DataTable().columns.adjust().responsive.recalc();
- return;
- }
-
- $('#app_passwd_table').DataTable({
- responsive: true,
- processing: true,
- serverSide: false,
- stateSave: true,
- dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
- "tr" +
- "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
- language: lang_datatables,
- ajax: {
- type: "GET",
- url: '/api/v1/get/app-passwd/all',
- dataSrc: function(data){
- console.log(data);
- $.each(data, function (i, item) {
- item.name = escapeHtml(item.name)
- item.protocols = []
- if (item.imap_access == 1) { item.protocols.push("<code>IMAP</code>"); }
- if (item.smtp_access == 1) { item.protocols.push("<code>SMTP</code>"); }
- if (item.eas_access == 1) { item.protocols.push("<code>EAS/ActiveSync</code>"); }
- if (item.dav_access == 1) { item.protocols.push("<code>DAV</code>"); }
- if (item.pop3_access == 1) { item.protocols.push("<code>POP3</code>"); }
- if (item.sieve_access == 1) { item.protocols.push("<code>Sieve</code>"); }
- item.protocols = item.protocols.join(" ")
- if (acl_data.app_passwds === 1) {
- item.action = '<div class="btn-group">' +
- '<a href="/edit/app-passwd/' + item.id + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
- '<a href="#" data-action="delete_selected" data-id="single-apppasswd" data-api-url="delete/app-passwd" data-item="' + item.id + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
- '</div>';
- item.chkbox = '<input type="checkbox" data-id="apppasswd" name="multi_select" value="' + item.id + '" />';
- }
- else {
- item.action = '<span>-</span>';
- item.chkbox = '<input type="checkbox" disabled />';
- }
- });
-
- return data;
- }
- },
- columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: 'ID',
- data: 'id',
- defaultContent: ''
- },
- {
- title: lang.app_name,
- data: 'name',
- defaultContent: ''
- },
- {
- title: lang.allowed_protocols,
- data: 'protocols',
- defaultContent: ''
- },
- {
- title: lang.active,
- data: 'active',
- defaultContent: '',
- render: function (data, type) {
- return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>'
- }
- },
- {
- title: lang.action,
- data: 'action',
- className: 'text-md-end dt-sm-head-hidden dt-body-right',
- defaultContent: ''
- }
- ]
- });
- }
- function draw_wl_policy_mailbox_table() {
- // just recalc width if instance already exists
- if ($.fn.DataTable.isDataTable('#wl_policy_mailbox_table') ) {
- $('#wl_policy_mailbox_table').DataTable().columns.adjust().responsive.recalc();
- return;
- }
-
- $('#wl_policy_mailbox_table').DataTable({
- responsive: true,
- processing: true,
- serverSide: false,
- stateSave: true,
- dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
- "tr" +
- "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
- language: lang_datatables,
- ajax: {
- type: "GET",
- url: '/api/v1/get/policy_wl_mailbox',
- dataSrc: function(data){
- console.log(data);
- $.each(data, function (i, item) {
- if (validateEmail(item.object)) {
- item.chkbox = '<input type="checkbox" data-id="policy_wl_mailbox" name="multi_select" value="' + item.prefid + '" />';
- }
- else {
- item.chkbox = '<input type="checkbox" disabled title="' + lang.spamfilter_table_domain_policy + '" />';
- }
- if (acl_data.spam_policy === 0) {
- item.chkbox = '<input type="checkbox" disabled />';
- }
- });
-
- return data;
- }
- },
- columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: 'ID',
- data: 'prefid',
- defaultContent: ''
- },
- {
- title: lang.spamfilter_table_rule,
- data: 'value',
- defaultContent: ''
- },
- {
- title:'Scope',
- data: 'object',
- defaultContent: ''
- }
- ]
- });
- }
- function draw_bl_policy_mailbox_table() {
- // just recalc width if instance already exists
- if ($.fn.DataTable.isDataTable('#bl_policy_mailbox_table') ) {
- $('#bl_policy_mailbox_table').DataTable().columns.adjust().responsive.recalc();
- return;
- }
-
- $('#bl_policy_mailbox_table').DataTable({
- responsive: true,
- processing: true,
- serverSide: false,
- stateSave: true,
- dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
- "tr" +
- "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
- language: lang_datatables,
- ajax: {
- type: "GET",
- url: '/api/v1/get/policy_bl_mailbox',
- dataSrc: function(data){
- console.log(data);
- $.each(data, function (i, item) {
- if (validateEmail(item.object)) {
- item.chkbox = '<input type="checkbox" data-id="policy_bl_mailbox" name="multi_select" value="' + item.prefid + '" />';
- }
- else {
- item.chkbox = '<input type="checkbox" disabled tooltip="' + lang.spamfilter_table_domain_policy + '" />';
- }
- if (acl_data.spam_policy === 0) {
- item.chkbox = '<input type="checkbox" disabled />';
- }
- });
-
- return data;
- }
- },
- columns: [
- {
- // placeholder, so checkbox will not block child row toggle
- title: '',
- data: null,
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: '',
- data: 'chkbox',
- searchable: false,
- orderable: false,
- defaultContent: ''
- },
- {
- title: 'ID',
- data: 'prefid',
- defaultContent: ''
- },
- {
- title: lang.spamfilter_table_rule,
- data: 'value',
- defaultContent: ''
- },
- {
- title:'Scope',
- data: 'object',
- defaultContent: ''
- }
- ]
- });
- }
-
- // FIDO2 friendly name modal
- $('#fido2ChangeFn').on('show.bs.modal', function (e) {
- rename_link = $(e.relatedTarget)
- if (rename_link != null) {
- $('#fido2_cid').val(rename_link.data('cid'));
- $('#fido2_subject_desc').text(Base64.decode(rename_link.data('subject')));
- }
- })
-
- // Sieve data modal
- $('#userFilterModal').on('show.bs.modal', function(e) {
- $('#user_sieve_filter').text(lang.loading);
- $.ajax({
- dataType: 'json',
- url: '/api/v1/get/active-user-sieve/' + encodeURIComponent(mailcow_cc_username),
- jsonp: false,
- error: function () {
- console.log('Cannot get active sieve script');
- },
- complete: function (data) {
- if (data.responseText == '{}') {
- $('#user_sieve_filter').text(lang.no_active_filter);
- } else {
- $('#user_sieve_filter').text(JSON.parse(data.responseText));
- }
- }
- })
- });
- $('#userFilterModal').on('hidden.bs.modal', function () {
- $('#user_sieve_filter').text(lang.loading);
- });
-
- // detect element visibility changes
- function onVisible(element, callback) {
- $(document).ready(function() {
- element_object = document.querySelector(element);
- if (element_object === null) return;
-
- new IntersectionObserver((entries, observer) => {
- entries.forEach(entry => {
- if(entry.intersectionRatio > 0) {
- callback(element_object);
- }
- });
- }).observe(element_object);
- });
- }
-
- // Load only if the tab is visible
- onVisible("[id^=tla_table]", () => draw_tla_table());
- onVisible("[id^=bl_policy_mailbox_table]", () => draw_bl_policy_mailbox_table());
- onVisible("[id^=wl_policy_mailbox_table]", () => draw_wl_policy_mailbox_table());
- onVisible("[id^=sync_job_table]", () => draw_sync_job_table());
- onVisible("[id^=app_passwd_table]", () => draw_app_passwd_table());
- last_logins('get');
-});
+// Base64 functions
+var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(r){var t,e,o,a,h,n,c,d="",C=0;for(r=Base64._utf8_encode(r);C<r.length;)a=(t=r.charCodeAt(C++))>>2,h=(3&t)<<4|(e=r.charCodeAt(C++))>>4,n=(15&e)<<2|(o=r.charCodeAt(C++))>>6,c=63&o,isNaN(e)?n=c=64:isNaN(o)&&(c=64),d=d+this._keyStr.charAt(a)+this._keyStr.charAt(h)+this._keyStr.charAt(n)+this._keyStr.charAt(c);return d},decode:function(r){var t,e,o,a,h,n,c="",d=0;for(r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");d<r.length;)t=this._keyStr.indexOf(r.charAt(d++))<<2|(a=this._keyStr.indexOf(r.charAt(d++)))>>4,e=(15&a)<<4|(h=this._keyStr.indexOf(r.charAt(d++)))>>2,o=(3&h)<<6|(n=this._keyStr.indexOf(r.charAt(d++))),c+=String.fromCharCode(t),64!=h&&(c+=String.fromCharCode(e)),64!=n&&(c+=String.fromCharCode(o));return c=Base64._utf8_decode(c)},_utf8_encode:function(r){r=r.replace(/\r\n/g,"\n");for(var t="",e=0;e<r.length;e++){var o=r.charCodeAt(e);o<128?t+=String.fromCharCode(o):o>127&&o<2048?(t+=String.fromCharCode(o>>6|192),t+=String.fromCharCode(63&o|128)):(t+=String.fromCharCode(o>>12|224),t+=String.fromCharCode(o>>6&63|128),t+=String.fromCharCode(63&o|128))}return t},_utf8_decode:function(r){for(var t="",e=0,o=c1=c2=0;e<r.length;)(o=r.charCodeAt(e))<128?(t+=String.fromCharCode(o),e++):o>191&&o<224?(c2=r.charCodeAt(e+1),t+=String.fromCharCode((31&o)<<6|63&c2),e+=2):(c2=r.charCodeAt(e+1),c3=r.charCodeAt(e+2),t+=String.fromCharCode((15&o)<<12|(63&c2)<<6|63&c3),e+=3);return t}};
+$(document).ready(function() {
+ // Spam score slider
+ var spam_slider = $('#spam_score')[0];
+ if (typeof spam_slider !== 'undefined') {
+ noUiSlider.create(spam_slider, {
+ start: user_spam_score,
+ connect: [true, true, true],
+ range: {
+ 'min': [0], //stepsize is 50.000
+ '50%': [10],
+ '70%': [20, 5],
+ '80%': [50, 10],
+ '90%': [100, 100],
+ '95%': [1000, 1000],
+ 'max': [5000]
+ },
+ });
+ var connect = spam_slider.querySelectorAll('.noUi-connect');
+ var classes = ['c-1-color', 'c-2-color', 'c-3-color'];
+ for (var i = 0; i < connect.length; i++) {
+ connect[i].classList.add(classes[i]);
+ }
+ spam_slider.noUiSlider.on('update', function (values, handle) {
+ $('.spam-ham-score').text('< ' + Math.round(values[0] * 10) / 10);
+ $('.spam-spam-score').text(Math.round(values[0] * 10) / 10 + ' - ' + Math.round(values[1] * 10) / 10);
+ $('.spam-reject-score').text('> ' + Math.round(values[1] * 10) / 10);
+ $('#spam_score_value').val((Math.round(values[0] * 10) / 10) + ',' + (Math.round(values[1] * 10) / 10));
+ });
+ }
+ // syncjobLogModal
+ $('#syncjobLogModal').on('show.bs.modal', function(e) {
+ var syncjob_id = $(e.relatedTarget).data('syncjob-id');
+ $.ajax({
+ url: '/inc/ajax/syncjob_logs.php',
+ data: { id: syncjob_id },
+ dataType: 'text',
+ success: function(data){
+ $(e.currentTarget).find('#logText').text(data);
+ },
+ error: function(xhr, status, error) {
+ $(e.currentTarget).find('#logText').text(xhr.responseText);
+ }
+ });
+ });
+ $(".arrow-toggle").on('click', function(e) { e.preventDefault(); $(this).find('.arrow').toggleClass("animation"); });
+ $("#pushover_delete").click(function() { return confirm(lang.delete_ays); });
+
+});
+jQuery(function($){
+ // http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
+ var entityMap = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '/': '/',
+ '`': '`',
+ '=': '='
+ };
+ function escapeHtml(string) {
+ return String(string).replace(/[&<>"'`=\/]/g, function (s) {
+ return entityMap[s];
+ });
+ }
+ // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
+ function validateEmail(email) {
+ var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
+ return re.test(email);
+ }
+ function unix_time_format(tm) {
+ var date = new Date(tm ? tm * 1000 : 0);
+ return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
+ }
+ acl_data = JSON.parse(acl);
+
+ $('.clear-last-logins').on('click', function () {if (confirm(lang.delete_ays)) {last_logins('reset');}})
+ $(".login-history").on('click', function(e) {e.preventDefault(); last_logins('get', $(this).data('days'));$(this).addClass('active').siblings().removeClass('active');});
+
+ function last_logins(action, days = 7) {
+ if (action == 'get') {
+ $('.last-login').html('<i class="bi bi-hourglass"></i>' + lang.waiting);
+ $.ajax({
+ dataType: 'json',
+ url: '/api/v1/get/last-login/' + encodeURIComponent(mailcow_cc_username) + '/' + days,
+ jsonp: false,
+ error: function () {
+ console.log('error reading last logins');
+ },
+ success: function (data) {
+ $('.last-login').html();
+ if (data.ui.time) {
+ $('.last-login').html('<i class="bi bi-person-fill"></i> ' + lang.last_ui_login + ': ' + unix_time_format(data.ui.time));
+ } else {
+ $('.last-login').text(lang.no_last_login);
+ }
+ if (data.sasl) {
+ $('.last-login').append('<ul class="list-group">');
+ $.each(data.sasl, function (i, item) {
+ var datetime = new Date(item.datetime.replace(/-/g, "/"));
+ var local_datetime = datetime.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
+ var service = '<div class="badge fs-6 bg-secondary">' + item.service.toUpperCase() + '</div>';
+ var app_password = item.app_password ? ' <a href="/edit/app-passwd/' + item.app_password + '"><i class="bi bi-app-indicator"></i> ' + escapeHtml(item.app_password_name || "App") + '</a>' : '';
+ var real_rip = item.real_rip.startsWith("Web") ? item.real_rip : '<a href="https://bgp.he.net/ip/' + item.real_rip + '" target="_blank">' + item.real_rip + "</a>";
+ var ip_location = item.location ? ' <span class="flag-icon flag-icon-' + item.location.toLowerCase() + '"></span>' : '';
+ var ip_data = real_rip + ip_location + app_password;
+ $(".last-login").append('<li class="list-group-item">' + local_datetime + " " + service + " " + lang.from + " " + ip_data + "</li>");
+ })
+ $('.last-login').append('</ul>');
+ }
+ }
+ })
+ } else if (action == 'reset') {
+ $.ajax({
+ dataType: 'json',
+ url: '/api/v1/get/reset-last-login/' + encodeURIComponent(mailcow_cc_username),
+ jsonp: false,
+ error: function () {
+ console.log('cannot reset last logins');
+ },
+ success: function (data) {
+ last_logins('get');
+ }
+ })
+ }
+ }
+
+ function draw_tla_table() {
+ // just recalc width if instance already exists
+ if ($.fn.DataTable.isDataTable('#tla_table') ) {
+ $('#tla_table').DataTable().columns.adjust().responsive.recalc();
+ return;
+ }
+
+ $('#tla_table').DataTable({
+ responsive: true,
+ processing: true,
+ serverSide: false,
+ stateSave: true,
+ pageLength: pagination_size,
+ dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
+ "tr" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ language: lang_datatables,
+ ajax: {
+ type: "GET",
+ url: "/api/v1/get/time_limited_aliases",
+ dataSrc: function(data){
+ console.log(data);
+ $.each(data, function (i, item) {
+ if (acl_data.spam_alias === 1) {
+ item.action = '<div class="btn-group">' +
+ '<a href="#" data-action="delete_selected" data-id="single-tla" data-api-url="delete/time_limited_alias" data-item="' + encodeURIComponent(item.address) + '" class="btn btn-xs btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
+ '</div>';
+ item.chkbox = '<input type="checkbox" data-id="tla" name="multi_select" value="' + encodeURIComponent(item.address) + '" />';
+ item.address = escapeHtml(item.address);
+ }
+ else {
+ item.chkbox = '<input type="checkbox" disabled />';
+ item.action = '<span>-</span>';
+ }
+ });
+
+ return data;
+ }
+ },
+ columns: [
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: lang.alias,
+ data: 'address',
+ defaultContent: ''
+ },
+ {
+ title: lang.alias_valid_until,
+ data: 'validity',
+ defaultContent: '',
+ render: function (data, type) {
+ var date = new Date(data ? data * 1000 : 0);
+ return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
+ }
+ },
+ {
+ title: lang.created_on,
+ data: 'created',
+ defaultContent: '',
+ render: function (data, type) {
+ var date = new Date(data.replace(/-/g, "/"));
+ return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
+ }
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'text-md-end dt-sm-head-hidden dt-body-right',
+ defaultContent: ''
+ }
+ ]
+ });
+ }
+ function draw_sync_job_table() {
+ // just recalc width if instance already exists
+ if ($.fn.DataTable.isDataTable('#sync_job_table') ) {
+ $('#sync_job_table').DataTable().columns.adjust().responsive.recalc();
+ return;
+ }
+
+ $('#sync_job_table').DataTable({
+ responsive: true,
+ processing: true,
+ serverSide: false,
+ stateSave: true,
+ pageLength: pagination_size,
+ dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
+ "tr" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ language: lang_datatables,
+ ajax: {
+ type: "GET",
+ url: '/api/v1/get/syncjobs/' + encodeURIComponent(mailcow_cc_username) + '/no_log',
+ dataSrc: function(data){
+ console.log(data);
+ $.each(data, function (i, item) {
+ item.user1 = escapeHtml(item.user1);
+ item.log = '<a href="#syncjobLogModal" data-bs-toggle="modal" data-syncjob-id="' + item.id + '">' + lang.open_logs + '</a>'
+ if (!item.exclude > 0) {
+ item.exclude = '-';
+ } else {
+ item.exclude = '<code>' + escapeHtml(item.exclude) + '</code>';
+ }
+ item.server_w_port = escapeHtml(item.user1 + '@' + item.host1 + ':' + item.port1);
+ if (acl_data.syncjobs === 1) {
+ item.action = '<div class="btn-group">' +
+ '<a href="/edit/syncjob/' + item.id + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
+ '<a href="#" data-action="delete_selected" data-id="single-syncjob" data-api-url="delete/syncjob" data-item="' + item.id + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
+ '</div>';
+ item.chkbox = '<input type="checkbox" data-id="syncjob" name="multi_select" value="' + item.id + '" />';
+ }
+ else {
+ item.action = '<span>-</span>';
+ item.chkbox = '<input type="checkbox" disabled />';
+ }
+ if (item.is_running == 1) {
+ item.is_running = '<span id="active-script" class="badge fs-6 bg-success">' + lang.running + '</span>';
+ } else {
+ item.is_running = '<span id="inactive-script" class="badge fs-6 bg-warning">' + lang.waiting + '</span>';
+ }
+ if (!item.last_run > 0) {
+ item.last_run = lang.waiting;
+ }
+ if (item.success == null) {
+ item.success = '-';
+ item.exit_status = '';
+ } else {
+ item.success = '<i class="text-' + (item.success == 1 ? 'success' : 'danger') + ' bi bi-' + (item.success == 1 ? 'check-lg' : 'x-lg') + '"></i>';
+ }
+ if (lang['syncjob_'+item.exit_status]) {
+ item.exit_status = lang['syncjob_'+item.exit_status];
+ } else if (item.success != '-') {
+ item.exit_status = lang.syncjob_check_log;
+ }
+ item.exit_status = item.success + ' ' + item.exit_status;
+ });
+
+ return data;
+ }
+ },
+ columns: [
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 1
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: '',
+ responsivePriority: 2
+ },
+ {
+ title: 'ID',
+ data: 'id',
+ defaultContent: '',
+ responsivePriority: 3
+ },
+ {
+ title: 'Server',
+ data: 'server_w_port',
+ defaultContent: ''
+ },
+ {
+ title: lang.username,
+ data: 'user1',
+ defaultContent: '',
+ responsivePriority: 3
+ },
+ {
+ title: lang.last_run,
+ data: 'last_run',
+ defaultContent: ''
+ },
+ {
+ title: lang.syncjob_last_run_result,
+ data: 'exit_status',
+ defaultContent: ''
+ },
+ {
+ title: 'Log',
+ data: 'log',
+ defaultContent: ''
+ },
+ {
+ title: lang.active,
+ data: 'active',
+ defaultContent: '',
+ render: function (data, type) {
+ return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>'
+ }
+ },
+ {
+ title: lang.status,
+ data: 'is_running',
+ defaultContent: '',
+ responsivePriority: 5
+ },
+ {
+ title: lang.encryption,
+ data: 'enc1',
+ defaultContent: ''
+ },
+ {
+ title: lang.excludes,
+ data: 'exclude',
+ defaultContent: ''
+ },
+ {
+ title: lang.interval + " (min)",
+ data: 'mins_interval',
+ defaultContent: ''
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'text-md-end dt-sm-head-hidden dt-body-right',
+ defaultContent: '',
+ responsivePriority: 5
+ }
+ ]
+ });
+ }
+ function draw_app_passwd_table() {
+ // just recalc width if instance already exists
+ if ($.fn.DataTable.isDataTable('#app_passwd_table') ) {
+ $('#app_passwd_table').DataTable().columns.adjust().responsive.recalc();
+ return;
+ }
+
+ $('#app_passwd_table').DataTable({
+ responsive: true,
+ processing: true,
+ serverSide: false,
+ stateSave: true,
+ pageLength: pagination_size,
+ dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
+ "tr" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ language: lang_datatables,
+ ajax: {
+ type: "GET",
+ url: '/api/v1/get/app-passwd/all',
+ dataSrc: function(data){
+ console.log(data);
+ $.each(data, function (i, item) {
+ item.name = escapeHtml(item.name)
+ item.protocols = []
+ if (item.imap_access == 1) { item.protocols.push("<code>IMAP</code>"); }
+ if (item.smtp_access == 1) { item.protocols.push("<code>SMTP</code>"); }
+ if (item.eas_access == 1) { item.protocols.push("<code>EAS/ActiveSync</code>"); }
+ if (item.dav_access == 1) { item.protocols.push("<code>DAV</code>"); }
+ if (item.pop3_access == 1) { item.protocols.push("<code>POP3</code>"); }
+ if (item.sieve_access == 1) { item.protocols.push("<code>Sieve</code>"); }
+ item.protocols = item.protocols.join(" ")
+ if (acl_data.app_passwds === 1) {
+ item.action = '<div class="btn-group">' +
+ '<a href="/edit/app-passwd/' + item.id + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
+ '<a href="#" data-action="delete_selected" data-id="single-apppasswd" data-api-url="delete/app-passwd" data-item="' + item.id + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
+ '</div>';
+ item.chkbox = '<input type="checkbox" data-id="apppasswd" name="multi_select" value="' + item.id + '" />';
+ }
+ else {
+ item.action = '<span>-</span>';
+ item.chkbox = '<input type="checkbox" disabled />';
+ }
+ });
+
+ return data;
+ }
+ },
+ columns: [
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: 'ID',
+ data: 'id',
+ defaultContent: ''
+ },
+ {
+ title: lang.app_name,
+ data: 'name',
+ defaultContent: ''
+ },
+ {
+ title: lang.allowed_protocols,
+ data: 'protocols',
+ defaultContent: ''
+ },
+ {
+ title: lang.active,
+ data: 'active',
+ defaultContent: '',
+ render: function (data, type) {
+ return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>'
+ }
+ },
+ {
+ title: lang.action,
+ data: 'action',
+ className: 'text-md-end dt-sm-head-hidden dt-body-right',
+ defaultContent: ''
+ }
+ ]
+ });
+ }
+ function draw_wl_policy_mailbox_table() {
+ // just recalc width if instance already exists
+ if ($.fn.DataTable.isDataTable('#wl_policy_mailbox_table') ) {
+ $('#wl_policy_mailbox_table').DataTable().columns.adjust().responsive.recalc();
+ return;
+ }
+
+ $('#wl_policy_mailbox_table').DataTable({
+ responsive: true,
+ processing: true,
+ serverSide: false,
+ stateSave: true,
+ pageLength: pagination_size,
+ dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
+ "tr" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ language: lang_datatables,
+ ajax: {
+ type: "GET",
+ url: '/api/v1/get/policy_wl_mailbox',
+ dataSrc: function(data){
+ console.log(data);
+ $.each(data, function (i, item) {
+ if (validateEmail(item.object)) {
+ item.chkbox = '<input type="checkbox" data-id="policy_wl_mailbox" name="multi_select" value="' + item.prefid + '" />';
+ }
+ else {
+ item.chkbox = '<input type="checkbox" disabled title="' + lang.spamfilter_table_domain_policy + '" />';
+ }
+ if (acl_data.spam_policy === 0) {
+ item.chkbox = '<input type="checkbox" disabled />';
+ }
+ });
+
+ return data;
+ }
+ },
+ columns: [
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: 'ID',
+ data: 'prefid',
+ defaultContent: ''
+ },
+ {
+ title: lang.spamfilter_table_rule,
+ data: 'value',
+ defaultContent: ''
+ },
+ {
+ title:'Scope',
+ data: 'object',
+ defaultContent: ''
+ }
+ ]
+ });
+ }
+ function draw_bl_policy_mailbox_table() {
+ // just recalc width if instance already exists
+ if ($.fn.DataTable.isDataTable('#bl_policy_mailbox_table') ) {
+ $('#bl_policy_mailbox_table').DataTable().columns.adjust().responsive.recalc();
+ return;
+ }
+
+ $('#bl_policy_mailbox_table').DataTable({
+ responsive: true,
+ processing: true,
+ serverSide: false,
+ stateSave: true,
+ pageLength: pagination_size,
+ dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
+ "tr" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ language: lang_datatables,
+ ajax: {
+ type: "GET",
+ url: '/api/v1/get/policy_bl_mailbox',
+ dataSrc: function(data){
+ console.log(data);
+ $.each(data, function (i, item) {
+ if (validateEmail(item.object)) {
+ item.chkbox = '<input type="checkbox" data-id="policy_bl_mailbox" name="multi_select" value="' + item.prefid + '" />';
+ }
+ else {
+ item.chkbox = '<input type="checkbox" disabled tooltip="' + lang.spamfilter_table_domain_policy + '" />';
+ }
+ if (acl_data.spam_policy === 0) {
+ item.chkbox = '<input type="checkbox" disabled />';
+ }
+ });
+
+ return data;
+ }
+ },
+ columns: [
+ {
+ // placeholder, so checkbox will not block child row toggle
+ title: '',
+ data: null,
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: '',
+ data: 'chkbox',
+ searchable: false,
+ orderable: false,
+ defaultContent: ''
+ },
+ {
+ title: 'ID',
+ data: 'prefid',
+ defaultContent: ''
+ },
+ {
+ title: lang.spamfilter_table_rule,
+ data: 'value',
+ defaultContent: ''
+ },
+ {
+ title:'Scope',
+ data: 'object',
+ defaultContent: ''
+ }
+ ]
+ });
+ }
+
+ // FIDO2 friendly name modal
+ $('#fido2ChangeFn').on('show.bs.modal', function (e) {
+ rename_link = $(e.relatedTarget)
+ if (rename_link != null) {
+ $('#fido2_cid').val(rename_link.data('cid'));
+ $('#fido2_subject_desc').text(Base64.decode(rename_link.data('subject')));
+ }
+ })
+
+ // Sieve data modal
+ $('#userFilterModal').on('show.bs.modal', function(e) {
+ $('#user_sieve_filter').text(lang.loading);
+ $.ajax({
+ dataType: 'json',
+ url: '/api/v1/get/active-user-sieve/' + encodeURIComponent(mailcow_cc_username),
+ jsonp: false,
+ error: function () {
+ console.log('Cannot get active sieve script');
+ },
+ complete: function (data) {
+ if (data.responseText == '{}') {
+ $('#user_sieve_filter').text(lang.no_active_filter);
+ } else {
+ $('#user_sieve_filter').text(JSON.parse(data.responseText));
+ }
+ }
+ })
+ });
+ $('#userFilterModal').on('hidden.bs.modal', function () {
+ $('#user_sieve_filter').text(lang.loading);
+ });
+
+ // detect element visibility changes
+ function onVisible(element, callback) {
+ $(document).ready(function() {
+ element_object = document.querySelector(element);
+ if (element_object === null) return;
+
+ new IntersectionObserver((entries, observer) => {
+ entries.forEach(entry => {
+ if(entry.intersectionRatio > 0) {
+ callback(element_object);
+ }
+ });
+ }).observe(element_object);
+ });
+ }
+
+ // Load only if the tab is visible
+ onVisible("[id^=tla_table]", () => draw_tla_table());
+ onVisible("[id^=bl_policy_mailbox_table]", () => draw_bl_policy_mailbox_table());
+ onVisible("[id^=wl_policy_mailbox_table]", () => draw_wl_policy_mailbox_table());
+ onVisible("[id^=sync_job_table]", () => draw_sync_job_table());
+ onVisible("[id^=app_passwd_table]", () => draw_app_passwd_table());
+ last_logins('get');
+});
diff --git a/data/web/templates/admin.twig b/data/web/templates/admin.twig
index 863f87e9..33f2422b 100644
--- a/data/web/templates/admin.twig
+++ b/data/web/templates/admin.twig
@@ -57,7 +57,7 @@
</div>
</div> <!-- /col-md-12 -->
</div> <!-- /row -->
-</div>
+</div>
{% include 'modals/admin.twig' %}
@@ -66,7 +66,7 @@ var lang = {{ lang_admin|raw }};
var lang_datatables = {{ lang_datatables|raw }};
var admin_username = '{{ mailcow_cc_username }}';
var csrf_token = '{{ csrf_token }}';
-var pagination_size = '{{ pagination_size }}';
-var log_pagination_size = '{{ log_pagination_size }}';
+var pagination_size = Math.trunc('{{ pagination_size }}');
+var log_pagination_size = Math.trunc('{{ log_pagination_size }}');
</script>
{% endblock %}
diff --git a/data/web/templates/debug.twig b/data/web/templates/debug.twig
index 1e011c8b..006703fb 100644
--- a/data/web/templates/debug.twig
+++ b/data/web/templates/debug.twig
@@ -41,7 +41,7 @@
</div>
<div class="col-sm-12 col-md-8">
<div class="table-responsive" style="margin-top: 10px;">
- <table class="table table-striped table-condensed">
+ <table class="table table-striped table-condensed w-100">
<tbody>
<tr>
<td>Hostname</td>
@@ -59,7 +59,7 @@
<span class="text">{{ lang.debug.show_ip }}</span>
<div class="spinner-border spinner-border-sm d-none" role="status">
<span class="visually-hidden">Loading...</span>
- </div>
+ </div>
</button>
{% else %}
<span class="d-block">{{ lang.admin.ip_check_disabled|raw }}</span>
@@ -71,7 +71,7 @@
<td class="text-break">
<div class="fw-bolder">
<p ><a href="#" id="maiclow_version">{{ mailcow_info.version_tag }}</a></p>
- <p id="mailcow_update"></p>
+ <p id="mailcow_update"></p>
</div>
</td>
</tr>
@@ -198,10 +198,10 @@
<i class="bi bi-caret-down-fill caret"></i>
</button>
</div>
- {% endif %}
+ {% endif %}
</div>
{% if containers["solr-mailcow"].State.Running == 1 %}
- <div class="collapse p-0 list-group-details container-details-collapse" id="solr-mailcowCollapse" data-id="{{ containers["solr-mailcow"].Id }}">
+ <div class="collapse p-0 list-group-details container-details-collapse" id="solr-mailcowCollapse" data-id="{{ containers["solr-mailcow"].Id }}">
<div class="row p-2 pt-4">
<div class="col-sm-3">
<p><img class="img-responsive" alt="Solr Logo" width="128px" src="data:image/png;base64,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" /></p>
@@ -238,10 +238,10 @@
<canvas class="d-none" id="solr-mailcow_NetIOChart" width="400" height="200"></canvas>
</div>
<div class="col-sm-12 d-flex" style="height: 40px">
- <a href data-bs-toggle="modal"
- data-container="solr-mailcow"
- data-bs-target="#RestartContainer"
- class="btn btn-sm btn-secondary d-flex align-items-center justify-content-center mb-2 ms-auto"
+ <a href data-bs-toggle="modal"
+ data-container="solr-mailcow"
+ data-bs-target="#RestartContainer"
+ class="btn btn-sm btn-secondary d-flex align-items-center justify-content-center mb-2 ms-auto"
style="height: 30px;">{{ lang.debug.restart_container }}
<i class="ms-1 bi
{% if containers["solr-mailcow"].State.Running == 1 %}
@@ -255,7 +255,7 @@
></i>
</a>
</div>
- </div>
+ </div>
</div>
{% endif %}
</div>
@@ -291,8 +291,8 @@
</button>
</div>
</div>
- <div class="collapse p-0 list-group-details container-details-collapse" id="{{ container }}Collapse" data-id="{{ container_info.Id }}">
- <div class="row p-2 pt-4">
+ <div class="collapse p-0 list-group-details container-details-collapse" id="{{ container }}Collapse" data-id="{{ container_info.Id }}">
+ <div class="row p-2 pt-4">
<div class="mt-4 col-sm-12 col-md-6 d-flex flex-column">
<h6>Disk I/O</h6>
<div class="spinner-border my-4 mx-auto" role="status">
@@ -306,12 +306,12 @@
<span class="visually-hidden">Loading...</span>
</div>
<canvas class="d-none" id="{{ container }}_NetIOChart" width="400" height="200"></canvas>
- </div>
- <div class="col-12 d-flex" style="height: 40px">
- <a href data-bs-toggle="modal"
- data-container="{{ container }}"
- data-bs-target="#RestartContainer"
- class="btn btn-sm btn-secondary d-flex align-items-center justify-content-center mb-2 ms-auto"
+ </div>
+ <div class="col-12 d-flex" style="height: 40px">
+ <a href data-bs-toggle="modal"
+ data-container="{{ container }}"
+ data-bs-target="#RestartContainer"
+ class="btn btn-sm btn-secondary d-flex align-items-center justify-content-center mb-2 ms-auto"
style="height: 30px;">{{ lang.debug.restart_container }}
<i class="ms-1 bi
{% if container_info.State.Running == 1 %}
@@ -340,7 +340,7 @@
<div class="debug-log-info">{{ lang.debug.log_info|format(log_lines+1)|raw }}</div>
<div class="card">
<div class="card-header d-flex align-items-center fs-5">
- <span class="mt-2 ms-2">Postfix</span>
+ <span class="mt-2 ms-2">Postfix</span>
<div class="btn-group ms-auto">
<button class="btn btn-sm btn-secondary refresh_table" data-draw="draw_postfix_logs" data-table="postfix_log">{{ lang.admin.refresh }}</button>
</div>
@@ -627,6 +627,6 @@
var lang_debug = {{ lang_debug|raw }};
var lang_datatables = {{ lang_datatables|raw }};
var csrf_token = '{{ csrf_token }}';
- var log_pagination_size = '{{ log_pagination_size }}';
+ var log_pagination_size = Math.trunc('{{ log_pagination_size }}');
</script>
{% endblock %}
diff --git a/data/web/templates/domainadmin.twig b/data/web/templates/domainadmin.twig
index 56f5e75f..070bf00c 100644
--- a/data/web/templates/domainadmin.twig
+++ b/data/web/templates/domainadmin.twig
@@ -46,7 +46,7 @@
<div class="col-sm-3 col-5 text-end">{{ lang.fido2.known_ids }}:</div>
<div class="col-sm-9 col-7">
<div class="table-responsive">
- <table class="table table-striped table-hover table-condensed" id="fido2_keys">
+ <table class="table table-striped table-hover table-condensed w-100" id="fido2_keys">
<tr>
<th>ID</th>
<th style="min-width:240px;text-align: right">{{ lang.admin.action }}</th>
diff --git a/data/web/templates/edit.twig b/data/web/templates/edit.twig
index 29f36435..af83a31d 100644
--- a/data/web/templates/edit.twig
+++ b/data/web/templates/edit.twig
@@ -26,7 +26,7 @@
var lang_user = {{ lang_user|raw }};
var lang_datatables = {{ lang_datatables|raw }};
var csrf_token = '{{ csrf_token }}';
- var pagination_size = '{{ pagination_size }}';
+ var pagination_size = Math.trunc('{{ pagination_size }}');
var table_for_domain = '{{ domain }}';
</script>
{% endblock %}
diff --git a/data/web/templates/mailbox.twig b/data/web/templates/mailbox.twig
index d1044288..1312441c 100644
--- a/data/web/templates/mailbox.twig
+++ b/data/web/templates/mailbox.twig
@@ -58,7 +58,7 @@
var lang_rl = {{ lang_rl|raw }};
var lang_datatables = {{ lang_datatables|raw }};
var csrf_token = '{{ csrf_token }}';
- var pagination_size = '{{ pagination_size }}';
+ var pagination_size = Math.trunc('{{ pagination_size }}');
var role = '{{ role }}';
var is_dual = {{ is_dual }};
var ALLOW_ADMIN_EMAIL_LOGIN = {{ allow_admin_email_login }};
diff --git a/data/web/templates/quarantine.twig b/data/web/templates/quarantine.twig
index 5ff7fe66..79b5ea16 100644
--- a/data/web/templates/quarantine.twig
+++ b/data/web/templates/quarantine.twig
@@ -37,7 +37,7 @@
</p>
{% endif %}
</p>
- <table id="quarantinetable" class="table table-striped"></table>
+ <table id="quarantinetable" class="table table-striped w-100"></table>
<div class="mass-actions-quarantine mt-4">
<div class="btn-group" data-acl="{{ acl.quarantine }}">
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="qitems" href="#"><i class="bi bi-check-all"></i> {{ lang.quarantine.toggle_all }}</a>
@@ -66,7 +66,7 @@ var acl = '{{ acl_json|raw }}';
var lang = {{ lang_quarantine|raw }};
var lang_datatables = {{ lang_datatables|raw }};
var csrf_token = '{{ csrf_token }}';
-var pagination_size = '{{ pagination_size }}';
+var pagination_size = Math.trunc('{{ pagination_size }}');
var role = '{{ role }}';
</script>
{% endblock %}
diff --git a/data/web/templates/queue.twig b/data/web/templates/queue.twig
index 1a5d4ff9..e843c18e 100644
--- a/data/web/templates/queue.twig
+++ b/data/web/templates/queue.twig
@@ -55,7 +55,7 @@
var lang = {{ lang_queue|raw }};
var lang_datatables = {{ lang_datatables|raw }};
var csrf_token = '{{ csrf_token }}';
- var pagination_size = '{{ pagination_size }}';
+ var pagination_size = Math.trunc('{{ pagination_size }}');
var table_for_domain = '{{ domain }}';
</script>
{% endblock %}
diff --git a/data/web/templates/user_domainadmin_common.twig b/data/web/templates/user_domainadmin_common.twig
index 8a7ace39..64a2205d 100644
--- a/data/web/templates/user_domainadmin_common.twig
+++ b/data/web/templates/user_domainadmin_common.twig
@@ -4,7 +4,7 @@
var acl = '{{ acl_json|raw }}';
var lang = {{ lang_user|raw }};
var csrf_token = '{{ csrf_token }}';
- var pagination_size = '{{ pagination_size }}';
+ var pagination_size = Math.trunc('{{ pagination_size }}');
var mailcow_cc_username = '{{ mailcow_cc_username }}';
var user_spam_score = [{{ user_spam_score }}];
var lang_datatables = {{ lang_datatables|raw }};