2017-11-04 03:37:24 +08:00
// 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 } } ;
2017-05-12 05:10:32 +08:00
jQuery ( function ( $ ) {
2017-06-16 05:03:21 +08:00
// http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
2017-11-04 03:37:24 +08:00
var entityMap = { "&" : "&" , "<" : "<" , ">" : ">" , '"' : """ , "'" : "'" , "/" : "/" , "`" : "`" , "=" : "=" } ;
2019-10-29 15:39:57 +08:00
function jq ( myid ) { return "#" + myid . replace ( /(:|\.|\[|\]|,|=|@)/g , "\\$1" ) ; }
2017-11-04 03:37:24 +08:00
function escapeHtml ( n ) { return String ( n ) . replace ( /[&<>"'`=\/]/g , function ( n ) { return entityMap [ n ] } ) }
2019-10-30 04:56:35 +08:00
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 } }
2017-11-04 03:37:24 +08:00
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 ] }
2018-12-20 18:23:35 +08:00
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 }
2018-06-24 05:50:22 +08:00
$ ( "#rspamd_preset_1" ) . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
[Docker API] Use TLS encryption for communication with "on-the-fly" created key paris (non-exposed)
[Docker API] Create pipe to pass Rspamd UI worker password
[Dovecot] Pull Spamassassin ruleset to be read by Rspamd (MANY THANKS to Peer Heinlein!)
[Dovecot] Garbage collector for deleted maildirs (set keep time via MAILDIR_GC_TIME which defaults to 1440 minutes)
[Web] Flush memcached after mailbox item changes, fixes #1808
[Web] Fix duplicate IDs, fixes #1792
[Compose] Use SQL sockets
[PHP-FPM] Update APCu and Redis libs
[Dovecot] Encrypt maildir with global key pair in crypt-vol-1 (BACKUP!), also fixes #1791
[Web] Fix deletion of spam aliases
[Helper] Add "crypt" to backup script
[Helper] Override file for external SQL socket (not supported!)
[Compose] New images for Rspamd, PHP-FPM, SOGo, Dovecot, Docker API, Watchdog, ACME, Postfix
2018-09-30 04:01:23 +08:00
$ ( "form[data-id=rsetting]" ) . find ( "#adminRspamdSettingsDesc" ) . val ( lang . rsettings _preset _1 ) ;
2018-12-16 04:24:39 +08:00
$ ( "form[data-id=rsetting]" ) . find ( "#adminRspamdSettingsContent" ) . val ( 'priority = 10;\nauthenticated = yes;\napply "default" {\n symbols_enabled = ["DKIM_SIGNED", "RATELIMITED", "RATELIMIT_UPDATE", "RATELIMIT_CHECK", "DYN_RL_CHECK", "HISTORY_SAVE", "MILTER_HEADERS", "ARC_SIGNED"];\n}' ) ;
2018-06-24 05:50:22 +08:00
} ) ;
$ ( "#rspamd_preset_2" ) . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
[Docker API] Use TLS encryption for communication with "on-the-fly" created key paris (non-exposed)
[Docker API] Create pipe to pass Rspamd UI worker password
[Dovecot] Pull Spamassassin ruleset to be read by Rspamd (MANY THANKS to Peer Heinlein!)
[Dovecot] Garbage collector for deleted maildirs (set keep time via MAILDIR_GC_TIME which defaults to 1440 minutes)
[Web] Flush memcached after mailbox item changes, fixes #1808
[Web] Fix duplicate IDs, fixes #1792
[Compose] Use SQL sockets
[PHP-FPM] Update APCu and Redis libs
[Dovecot] Encrypt maildir with global key pair in crypt-vol-1 (BACKUP!), also fixes #1791
[Web] Fix deletion of spam aliases
[Helper] Add "crypt" to backup script
[Helper] Override file for external SQL socket (not supported!)
[Compose] New images for Rspamd, PHP-FPM, SOGo, Dovecot, Docker API, Watchdog, ACME, Postfix
2018-09-30 04:01:23 +08:00
$ ( "form[data-id=rsetting]" ) . find ( "#adminRspamdSettingsDesc" ) . val ( lang . rsettings _preset _2 ) ;
$ ( "form[data-id=rsetting]" ) . find ( "#adminRspamdSettingsContent" ) . val ( 'priority = 10;\nrcpt = "/postmaster@.*/";\nwant_spam = yes;' ) ;
2018-06-24 05:50:22 +08:00
} ) ;
2018-08-21 23:41:04 +08:00
$ ( "#dkim_missing_keys" ) . on ( 'click' , function ( e ) {
e . preventDefault ( ) ;
var domains = [ ] ;
$ ( '.dkim_missing' ) . each ( function ( ) {
domains . push ( $ ( this ) . val ( ) ) ;
} ) ;
$ ( '#dkim_add_domains' ) . val ( domains ) ;
} ) ;
2019-02-05 17:37:28 +08:00
$ ( ".arrow-toggle" ) . on ( 'click' , function ( e ) { e . preventDefault ( ) ; $ ( this ) . find ( '.arrow' ) . toggleClass ( "animation" ) ; } ) ;
2018-10-24 03:14:57 +08:00
$ ( "#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 ) ; } ) ;
2019-10-29 15:39:57 +08:00
$ ( ".validate_rspamd_regex" ) . click ( function ( event ) {
event . preventDefault ( ) ;
var regex _map _id = $ ( this ) . data ( 'regex-map' ) ;
2019-10-30 04:56:35 +08:00
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 } ) ;
}
2019-10-29 15:39:57 +08:00
} ) ;
$ ( '.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 ( "hidden" ) ;
} ) ;
2018-10-24 03:14:57 +08:00
$ ( "#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 ) . find ( "tr.footable-empty" ) . remove ( ) ;
draw _table = $ ( this ) . data ( 'draw' ) ;
eval ( draw _table + '()' ) ;
2018-10-11 17:59:23 +08:00
} ) ;
2018-10-24 03:14:57 +08:00
if ( localStorage . getItem ( "current_page" ) === null ) {
var current _page = { } ;
} else {
var current _page = JSON . parse ( localStorage . getItem ( 'current_page' ) ) ;
}
function table _admin _ready ( ft , name ) {
2019-10-11 14:51:40 +08:00
heading = ft . $el . parents ( '.panel' ) . find ( '.panel-heading' )
2018-10-24 03:14:57 +08:00
var ft _paging = ft . use ( FooTable . Paging )
$ ( heading ) . children ( '.table-lines' ) . text ( function ( ) {
return ft _paging . totalRows ;
} )
}
2017-05-12 05:10:32 +08:00
function draw _domain _admins ( ) {
ft _domainadmins = FooTable . init ( '#domainadminstable' , {
"columns" : [
2019-01-29 07:20:39 +08:00
{ "name" : "chkbox" , "title" : "" , "style" : { "maxWidth" : "60px" , "width" : "60px" } , "filterable" : false , "sortable" : false , "type" : "html" } ,
2017-05-12 05:10:32 +08:00
{ "sorted" : true , "name" : "username" , "title" : lang . username , "style" : { "width" : "250px" } } ,
{ "name" : "selected_domains" , "title" : lang . admin _domains , "breakpoints" : "xs sm" } ,
{ "name" : "tfa_active" , "title" : "TFA" , "filterable" : false , "style" : { "maxWidth" : "80px" , "width" : "80px" } } ,
{ "name" : "active" , "filterable" : false , "style" : { "maxWidth" : "80px" , "width" : "80px" } , "title" : lang . active } ,
2018-08-15 06:05:18 +08:00
{ "name" : "action" , "filterable" : false , "sortable" : false , "style" : { "text-align" : "right" , "maxWidth" : "250px" , "width" : "250px" } , "type" : "html" , "title" : lang . action , "breakpoints" : "xs sm" }
2017-05-12 05:10:32 +08:00
] ,
"rows" : $ . ajax ( {
dataType : 'json' ,
url : '/api/v1/get/domain-admin/all' ,
jsonp : false ,
error : function ( ) {
console . log ( 'Cannot draw domain admin table' ) ;
} ,
success : function ( data ) {
2017-11-04 03:37:24 +08:00
return process _table _data ( data , 'domainadminstable' ) ;
2017-05-12 05:10:32 +08:00
}
} ) ,
"empty" : lang . empty ,
2017-11-04 03:37:24 +08:00
"paging" : { "enabled" : true , "limit" : 5 , "size" : log _pagination _size } ,
2019-01-19 15:25:05 +08:00
"state" : { "enabled" : true } ,
2019-09-22 21:10:56 +08:00
"filtering" : { "enabled" : true , "delay" : 1200 , "position" : "left" , "connectors" : false , "placeholder" : lang . filter _table } ,
2019-08-31 00:54:38 +08:00
"sorting" : { "enabled" : true } ,
"toggleSelector" : "table tbody span.footable-toggle"
2017-05-12 05:10:32 +08:00
} ) ;
}
2019-10-03 01:00:36 +08:00
function draw _oauth2 _clients ( ) {
ft _oauth2clientstable = FooTable . init ( '#oauth2clientstable' , {
"columns" : [
{ "name" : "chkbox" , "title" : "" , "style" : { "maxWidth" : "40px" , "width" : "40px" } , "filterable" : false , "sortable" : false , "type" : "html" } ,
{ "name" : "id" , "type" : "text" , "title" : "ID" , "style" : { "width" : "50px" } } ,
{ "name" : "client_id" , "type" : "text" , "title" : lang . oauth2 _client _id , "style" : { "width" : "200px" } } ,
{ "name" : "client_secret" , "title" : lang . oauth2 _client _secret , "breakpoints" : "xs sm md" , "style" : { "width" : "200px" } } ,
{ "name" : "redirect_uri" , "title" : lang . oauth2 _redirect _uri , "type" : "text" } ,
{ "name" : "action" , "filterable" : false , "sortable" : false , "style" : { "text-align" : "right" , "maxWidth" : "180px" , "width" : "180px" } , "type" : "html" , "title" : lang . action , "breakpoints" : "xs sm" }
] ,
"rows" : $ . ajax ( {
dataType : 'json' ,
url : '/api/v1/get/oauth2-client/all' ,
jsonp : false ,
error : function ( ) {
console . log ( 'Cannot draw oauth2 clients table' ) ;
} ,
success : function ( data ) {
return process _table _data ( data , 'oauth2clientstable' ) ;
}
} ) ,
"empty" : lang . empty ,
"paging" : { "enabled" : true , "limit" : 5 , "size" : log _pagination _size } ,
"sorting" : { "enabled" : true } ,
"toggleSelector" : "table tbody span.footable-toggle"
} ) ;
}
2018-10-11 17:59:23 +08:00
function draw _admins ( ) {
ft _admins = FooTable . init ( '#adminstable' , {
"columns" : [
2019-01-29 07:20:39 +08:00
{ "name" : "chkbox" , "title" : "" , "style" : { "maxWidth" : "60px" , "width" : "60px" } , "filterable" : false , "sortable" : false , "type" : "html" } ,
2018-10-11 17:59:23 +08:00
{ "sorted" : true , "name" : "usr" , "title" : lang . username , "style" : { "width" : "250px" } } ,
{ "name" : "tfa_active" , "title" : "TFA" , "filterable" : false , "style" : { "maxWidth" : "80px" , "width" : "80px" } } ,
{ "name" : "active" , "filterable" : false , "style" : { "maxWidth" : "80px" , "width" : "80px" } , "title" : lang . active } ,
{ "name" : "action" , "filterable" : false , "sortable" : false , "style" : { "text-align" : "right" , "maxWidth" : "250px" , "width" : "250px" } , "type" : "html" , "title" : lang . action , "breakpoints" : "xs sm" }
] ,
"rows" : $ . ajax ( {
dataType : 'json' ,
url : '/api/v1/get/admin/all' ,
jsonp : false ,
error : function ( ) {
console . log ( 'Cannot draw admin table' ) ;
} ,
success : function ( data ) {
return process _table _data ( data , 'adminstable' ) ;
}
} ) ,
"empty" : lang . empty ,
"paging" : { "enabled" : true , "limit" : 5 , "size" : log _pagination _size } ,
"filtering" : { "enabled" : false } ,
2019-01-19 15:25:05 +08:00
"state" : { "enabled" : true } ,
2019-08-31 00:54:38 +08:00
"sorting" : { "enabled" : true } ,
"toggleSelector" : "table tbody span.footable-toggle"
2018-10-11 17:59:23 +08:00
} ) ;
}
2017-05-12 05:10:32 +08:00
function draw _fwd _hosts ( ) {
2017-05-24 04:23:46 +08:00
ft _forwardinghoststable = FooTable . init ( '#forwardinghoststable' , {
2017-05-12 05:10:32 +08:00
"columns" : [
2019-01-29 07:20:39 +08:00
{ "name" : "chkbox" , "title" : "" , "style" : { "maxWidth" : "60px" , "width" : "60px" } , "filterable" : false , "sortable" : false , "type" : "html" } ,
2017-05-12 05:10:32 +08:00
{ "name" : "host" , "type" : "text" , "title" : lang . host , "style" : { "width" : "250px" } } ,
{ "name" : "source" , "title" : lang . source , "breakpoints" : "xs sm" } ,
{ "name" : "keep_spam" , "title" : lang . spamfilter , "type" : "text" , "style" : { "maxWidth" : "80px" , "width" : "80px" } } ,
2017-05-30 03:51:06 +08:00
{ "name" : "action" , "filterable" : false , "sortable" : false , "style" : { "text-align" : "right" , "maxWidth" : "180px" , "width" : "180px" } , "type" : "html" , "title" : lang . action , "breakpoints" : "xs sm" }
2017-05-12 05:10:32 +08:00
] ,
"rows" : $ . ajax ( {
dataType : 'json' ,
url : '/api/v1/get/fwdhost/all' ,
jsonp : false ,
error : function ( ) {
console . log ( 'Cannot draw forwarding hosts table' ) ;
} ,
success : function ( data ) {
2017-11-04 03:37:24 +08:00
return process _table _data ( data , 'forwardinghoststable' ) ;
2017-05-07 05:52:40 +08:00
}
2017-05-12 05:10:32 +08:00
} ) ,
"empty" : lang . empty ,
2017-11-04 03:37:24 +08:00
"paging" : { "enabled" : true , "limit" : 5 , "size" : log _pagination _size } ,
2019-08-31 00:54:38 +08:00
"sorting" : { "enabled" : true } ,
"toggleSelector" : "table tbody span.footable-toggle"
2017-05-12 05:10:32 +08:00
} ) ;
}
2017-07-23 02:39:54 +08:00
function draw _relayhosts ( ) {
2017-11-04 03:37:24 +08:00
ft _relayhoststable = FooTable . init ( '#relayhoststable' , {
2017-07-23 02:39:54 +08:00
"columns" : [
2019-01-29 07:20:39 +08:00
{ "name" : "chkbox" , "title" : "" , "style" : { "maxWidth" : "60px" , "width" : "60px" } , "filterable" : false , "sortable" : false , "type" : "html" } ,
2017-07-23 02:39:54 +08:00
{ "name" : "id" , "type" : "text" , "title" : "ID" , "style" : { "width" : "50px" } } ,
{ "name" : "hostname" , "type" : "text" , "title" : lang . host , "style" : { "width" : "250px" } } ,
{ "name" : "username" , "title" : lang . username , "breakpoints" : "xs sm" } ,
2018-07-13 17:02:46 +08:00
{ "name" : "used_by_domains" , "title" : lang . in _use _by , "style" : { "width" : "110px" } , "type" : "text" , "breakpoints" : "xs sm" } ,
2017-07-23 02:39:54 +08:00
{ "name" : "active" , "filterable" : false , "style" : { "maxWidth" : "80px" , "width" : "80px" } , "title" : lang . active } ,
2018-12-20 18:23:35 +08:00
{ "name" : "action" , "filterable" : false , "sortable" : false , "style" : { "text-align" : "right" , "maxWidth" : "220px" , "width" : "220px" } , "type" : "html" , "title" : lang . action , "breakpoints" : "xs sm md" }
2017-07-23 02:39:54 +08:00
] ,
"rows" : $ . ajax ( {
dataType : 'json' ,
url : '/api/v1/get/relayhost/all' ,
jsonp : false ,
error : function ( ) {
console . log ( 'Cannot draw forwarding hosts table' ) ;
} ,
success : function ( data ) {
2017-11-04 03:37:24 +08:00
return process _table _data ( data , 'relayhoststable' ) ;
2017-07-23 02:39:54 +08:00
}
} ) ,
"empty" : lang . empty ,
2017-11-04 03:37:24 +08:00
"paging" : { "enabled" : true , "limit" : 5 , "size" : log _pagination _size } ,
2019-08-31 00:54:38 +08:00
"sorting" : { "enabled" : true } ,
"toggleSelector" : "table tbody span.footable-toggle"
2017-07-23 02:39:54 +08:00
} ) ;
}
2018-12-20 18:23:35 +08:00
function draw _transport _maps ( ) {
ft _relayhoststable = FooTable . init ( '#transportstable' , {
"columns" : [
2019-01-29 07:20:39 +08:00
{ "name" : "chkbox" , "title" : "" , "style" : { "maxWidth" : "60px" , "width" : "60px" } , "filterable" : false , "sortable" : false , "type" : "html" } ,
2018-12-20 18:23:35 +08:00
{ "name" : "id" , "type" : "text" , "title" : "ID" , "style" : { "width" : "50px" } } ,
{ "name" : "destination" , "type" : "text" , "title" : lang . destination , "style" : { "width" : "250px" } } ,
{ "name" : "nexthop" , "type" : "text" , "title" : lang . nexthop , "style" : { "width" : "250px" } } ,
{ "name" : "username" , "title" : lang . username , "breakpoints" : "xs sm" } ,
{ "name" : "active" , "filterable" : false , "style" : { "maxWidth" : "80px" , "width" : "80px" } , "title" : lang . active } ,
{ "name" : "action" , "filterable" : false , "sortable" : false , "style" : { "text-align" : "right" , "maxWidth" : "220px" , "width" : "220px" } , "type" : "html" , "title" : lang . action , "breakpoints" : "xs sm md" }
] ,
"rows" : $ . ajax ( {
dataType : 'json' ,
url : '/api/v1/get/transport/all' ,
jsonp : false ,
error : function ( ) {
console . log ( 'Cannot draw transports table' ) ;
} ,
success : function ( data ) {
return process _table _data ( data , 'transportstable' ) ;
}
} ) ,
"empty" : lang . empty ,
"paging" : { "enabled" : true , "limit" : 5 , "size" : log _pagination _size } ,
2019-08-31 00:54:38 +08:00
"sorting" : { "enabled" : true } ,
"toggleSelector" : "table tbody span.footable-toggle"
2018-12-20 18:23:35 +08:00
} ) ;
}
2018-10-24 03:14:57 +08:00
function draw _queue ( ) {
ft _queuetable = FooTable . init ( '#queuetable' , {
"columns" : [
2019-01-29 07:20:39 +08:00
{ "name" : "chkbox" , "title" : "" , "style" : { "maxWidth" : "60px" , "width" : "60px" } , "filterable" : false , "sortable" : false , "type" : "html" } ,
2018-10-24 03:14:57 +08:00
{ "name" : "queue_id" , "type" : "text" , "title" : "QID" , "style" : { "width" : "50px" } } ,
{ "name" : "queue_name" , "type" : "text" , "title" : "Queue" , "style" : { "width" : "120px" } } ,
2018-10-26 04:42:20 +08:00
{ "name" : "arrival_time" , "sorted" : true , "direction" : "DESC" , "formatter" : function unix _time _format ( tm ) { var date = new Date ( tm ? tm * 1000 : 0 ) ; return date . toLocaleString ( ) ; } , "title" : lang . arrival _time , "style" : { "width" : "170px" } } ,
2018-10-24 03:14:57 +08:00
{ "name" : "message_size" , "style" : { "whiteSpace" : "nowrap" } , "title" : lang . message _size , "formatter" : function ( value ) {
return humanFileSize ( value ) ;
} } ,
{ "name" : "sender" , "title" : lang . sender , "type" : "text" , "breakpoints" : "xs sm" } ,
2018-10-26 04:42:20 +08:00
{ "name" : "recipients" , "title" : lang . recipients , "type" : "text" , "style" : { "word-break" : "break-all" , "min-width" : "300px" } , "breakpoints" : "xs sm md" } ,
2018-10-24 03:14:57 +08:00
] ,
"rows" : $ . ajax ( {
dataType : 'json' ,
2018-10-26 04:42:20 +08:00
url : '/api/v1/get/mailq/all' ,
2018-10-24 03:14:57 +08:00
jsonp : false ,
error : function ( ) {
console . log ( 'Cannot draw forwarding hosts table' ) ;
} ,
success : function ( data ) {
return process _table _data ( data , 'queuetable' ) ;
}
} ) ,
"empty" : lang . empty ,
"paging" : { "enabled" : true , "limit" : 5 , "size" : log _pagination _size } ,
"sorting" : { "enabled" : true } ,
2019-08-31 00:54:38 +08:00
"toggleSelector" : "table tbody span.footable-toggle" ,
2018-10-24 03:14:57 +08:00
"on" : {
"ready.ft.table" : function ( e , ft ) {
table _admin _ready ( ft , 'queuetable' ) ;
}
}
} ) ;
}
2017-11-04 03:37:24 +08:00
function process _table _data ( data , table ) {
2017-12-09 20:17:15 +08:00
if ( table == 'relayhoststable' ) {
2017-11-04 03:37:24 +08:00
$ . each ( data , function ( i , item ) {
item . action = '<div class="btn-group">' +
2018-12-20 18:23:35 +08:00
'<a href="#" data-toggle="modal" data-target="#testTransportModal" data-transport-id="' + encodeURI ( item . id ) + '" data-transport-type="sender-dependent" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-triangle-right"></span> Test</a>' +
2018-10-04 20:38:12 +08:00
'<a href="/edit/relayhost/' + encodeURI ( item . id ) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang . edit + '</a>' +
2018-12-20 18:23:35 +08:00
'<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-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang . remove + '</a>' +
2017-11-04 03:37:24 +08:00
'</div>' ;
item . chkbox = '<input type="checkbox" data-id="rlyhosts" name="multi_select" value="' + item . id + '" />' ;
} ) ;
2018-12-20 18:23:35 +08:00
} else if ( table == 'transportstable' ) {
$ . each ( data , function ( i , item ) {
if ( item . username ) {
item . username = '<span style="border-left:3px solid #' + intToRGB ( hashCode ( item . nexthop ) ) + ';padding-left:5px;">' + item . username + '</span>' ;
}
item . action = '<div class="btn-group">' +
'<a href="#" data-toggle="modal" data-target="#testTransportModal" data-transport-id="' + encodeURI ( item . id ) + '" data-transport-type="transport-map" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-triangle-right"></span> Test</a>' +
'<a href="/edit/transport/' + encodeURI ( item . id ) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + 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-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang . remove + '</a>' +
'</div>' ;
item . chkbox = '<input type="checkbox" data-id="transports" name="multi_select" value="' + item . id + '" />' ;
} ) ;
2018-10-24 03:14:57 +08:00
} else if ( table == 'queuetable' ) {
$ . each ( data , function ( i , item ) {
item . chkbox = '<input type="checkbox" data-id="mailqitems" name="multi_select" value="' + item . queue _id + '" />' ;
2018-10-26 04:42:20 +08:00
rcpts = $ . map ( item . recipients , function ( i ) {
return escapeHtml ( i ) ;
} ) ;
item . recipients = rcpts . join ( '<hr style="margin:1px!important">' ) ;
2018-10-24 03:14:57 +08:00
} ) ;
2017-11-04 03:37:24 +08:00
} else if ( table == 'forwardinghoststable' ) {
$ . each ( data , function ( i , item ) {
item . action = '<div class="btn-group">' +
[Docker API] Use TLS encryption for communication with "on-the-fly" created key paris (non-exposed)
[Docker API] Create pipe to pass Rspamd UI worker password
[Dovecot] Pull Spamassassin ruleset to be read by Rspamd (MANY THANKS to Peer Heinlein!)
[Dovecot] Garbage collector for deleted maildirs (set keep time via MAILDIR_GC_TIME which defaults to 1440 minutes)
[Web] Flush memcached after mailbox item changes, fixes #1808
[Web] Fix duplicate IDs, fixes #1792
[Compose] Use SQL sockets
[PHP-FPM] Update APCu and Redis libs
[Dovecot] Encrypt maildir with global key pair in crypt-vol-1 (BACKUP!), also fixes #1791
[Web] Fix deletion of spam aliases
[Helper] Add "crypt" to backup script
[Helper] Override file for external SQL socket (not supported!)
[Compose] New images for Rspamd, PHP-FPM, SOGo, Dovecot, Docker API, Watchdog, ACME, Postfix
2018-09-30 04:01:23 +08:00
'<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"><span class="glyphicon glyphicon-trash"></span> ' + lang . remove + '</a>' +
2017-11-04 03:37:24 +08:00
'</div>' ;
if ( item . keep _spam == "yes" ) {
item . keep _spam = lang . no ;
}
else {
item . keep _spam = lang . yes ;
}
item . chkbox = '<input type="checkbox" data-id="fwdhosts" name="multi_select" value="' + item . host + '" />' ;
} ) ;
2019-10-03 01:00:36 +08:00
} 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-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang . edit + '</a>' +
2019-10-17 17:17:29 +08:00
'<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-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang . remove + '</a>' +
2019-10-03 01:00:36 +08:00
'</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 + '" />' ;
} ) ;
2017-11-04 03:37:24 +08:00
} else if ( table == 'domainadminstable' ) {
$ . each ( data , function ( i , item ) {
2018-10-11 17:59:23 +08:00
item . selected _domains = escapeHtml ( item . selected _domains ) ;
item . selected _domains = item . selected _domains . toString ( ) . replace ( /,/g , "<br>" ) ;
2017-11-04 03:37:24 +08:00
item . chkbox = '<input type="checkbox" data-id="domain_admins" name="multi_select" value="' + item . username + '" />' ;
item . action = '<div class="btn-group">' +
2018-10-04 20:38:12 +08:00
'<a href="/edit/domainadmin/' + encodeURI ( item . username ) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang . edit + '</a>' +
[Docker API] Use TLS encryption for communication with "on-the-fly" created key paris (non-exposed)
[Docker API] Create pipe to pass Rspamd UI worker password
[Dovecot] Pull Spamassassin ruleset to be read by Rspamd (MANY THANKS to Peer Heinlein!)
[Dovecot] Garbage collector for deleted maildirs (set keep time via MAILDIR_GC_TIME which defaults to 1440 minutes)
[Web] Flush memcached after mailbox item changes, fixes #1808
[Web] Fix duplicate IDs, fixes #1792
[Compose] Use SQL sockets
[PHP-FPM] Update APCu and Redis libs
[Dovecot] Encrypt maildir with global key pair in crypt-vol-1 (BACKUP!), also fixes #1791
[Web] Fix deletion of spam aliases
[Helper] Add "crypt" to backup script
[Helper] Override file for external SQL socket (not supported!)
[Compose] New images for Rspamd, PHP-FPM, SOGo, Dovecot, Docker API, Watchdog, ACME, Postfix
2018-09-30 04:01:23 +08:00
'<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-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang . remove + '</a>' +
2018-08-15 06:05:18 +08:00
'<a href="/index.php?duallogin=' + encodeURIComponent ( item . username ) + '" class="btn btn-xs btn-success"><span class="glyphicon glyphicon-user"></span> Login</a>' +
2017-11-04 03:37:24 +08:00
'</div>' ;
} ) ;
2018-10-11 17:59:23 +08:00
} else if ( table == 'adminstable' ) {
$ . each ( data , function ( i , item ) {
2019-09-06 01:08:41 +08:00
if ( admin _username . toLowerCase ( ) == item . username . toLowerCase ( ) ) {
2018-10-11 17:59:23 +08:00
item . usr = '→ ' + 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-default"><span class="glyphicon glyphicon-pencil"></span> ' + 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-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang . remove + '</a>' +
'</div>' ;
} ) ;
2017-11-04 03:37:24 +08:00
}
return data
} ;
// Initial table drawings
2017-05-12 05:10:32 +08:00
draw _domain _admins ( ) ;
2018-10-11 17:59:23 +08:00
draw _admins ( ) ;
2017-05-12 05:10:32 +08:00
draw _fwd _hosts ( ) ;
2017-07-23 02:39:54 +08:00
draw _relayhosts ( ) ;
2019-10-03 01:00:36 +08:00
draw _oauth2 _clients ( ) ;
2018-12-20 18:23:35 +08:00
draw _transport _maps ( ) ;
2018-10-24 03:14:57 +08:00
draw _queue ( ) ;
2017-11-04 03:37:24 +08:00
// Relayhost
2017-07-27 05:11:43 +08:00
$ ( '#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 ( '<span class="glyphicon glyphicon-refresh glyphicon-spin"></span> ' ) ;
$ . ajax ( {
type : 'GET' ,
2017-11-11 02:58:17 +08:00
url : 'inc/ajax/relay_check.php' ,
2017-07-27 05:11:43 +08:00
dataType : 'text' ,
data : $ ( '#test_relayhost_form' ) . serialize ( ) ,
complete : function ( data ) {
2018-10-24 03:14:57 +08:00
$ ( '#test_relayhost_result' ) . html ( data . responseText ) ;
$ ( '#test_relayhost' ) . prop ( "disabled" , false ) ;
$ ( '#test_relayhost' ) . text ( prev ) ;
2017-07-27 05:11:43 +08:00
}
} ) ;
} )
2018-12-20 18:23:35 +08:00
// 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 ( '<span class="glyphicon glyphicon-refresh glyphicon-spin"></span> ' ) ;
$ . 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 ) ;
}
} ) ;
} )
2017-11-04 03:37:24 +08:00
// 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 ) ;
}
} )
// App links
2017-10-21 16:07:06 +08:00
function add _table _row ( table _id ) {
var row = $ ( '<tr />' ) ;
cols = '<td><input class="input-sm form-control" data-id="app_links" type="text" name="app" required></td>' ;
cols += '<td><input class="input-sm form-control" data-id="app_links" type="text" name="href" required></td>' ;
cols += '<td><a href="#" role="button" class="btn btn-xs btn-default" type="button">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 ( ) ;
} ) ;
$ ( '#add_app_link_row' ) . click ( function ( ) {
add _table _row ( $ ( '#app_link_table' ) ) ;
} ) ;
2017-07-23 02:39:54 +08:00
} ) ;
$ ( window ) . load ( function ( ) {
2017-07-29 16:32:17 +08:00
initial _width = $ ( "#sidebar-admin" ) . width ( ) ;
$ ( "#scrollbox" ) . css ( "width" , initial _width ) ;
2018-06-24 05:50:22 +08:00
if ( sessionStorage . scrollTop > 70 ) {
$ ( '#scrollbox' ) . addClass ( 'scrollboxFixed' ) ;
}
2017-07-23 02:39:54 +08:00
$ ( window ) . bind ( 'scroll' , function ( ) {
if ( $ ( window ) . scrollTop ( ) > 70 ) {
$ ( '#scrollbox' ) . addClass ( 'scrollboxFixed' ) ;
} else {
$ ( '#scrollbox' ) . removeClass ( 'scrollboxFixed' ) ;
}
} ) ;
2017-07-29 16:32:17 +08:00
} ) ;
2017-09-10 22:11:55 +08:00
function resizeScrollbox ( ) {
2017-07-29 16:32:17 +08:00
on _resize _width = $ ( "#sidebar-admin" ) . width ( ) ;
$ ( "#scrollbox" ) . removeAttr ( "style" ) ;
$ ( "#scrollbox" ) . css ( "width" , on _resize _width ) ;
2017-09-10 22:11:55 +08:00
}
$ ( window ) . on ( 'resize' , resizeScrollbox ) ;
$ ( 'a[data-toggle="tab"]' ) . on ( 'shown.bs.tab' , resizeScrollbox ) ;