[Web] Time limited aliases: show create date; create aliases with 1yr retention by default; create temp alias in alias domain; better random names; accept any validity time
[Web] Replace spam score slider by nouislider and rework table a bit
This commit is contained in:
		
							
								
								
									
										41
									
								
								data/web/css/build/004-bootstrap-slider.min.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										41
									
								
								data/web/css/build/004-bootstrap-slider.min.css
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								data/web/css/build/004-slider.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								data/web/css/build/004-slider.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| .noUi-target,.noUi-target *{-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;-ms-touch-action:none;touch-action:none;-ms-user-select:none;-moz-user-select:none;user-select:none;-moz-box-sizing:border-box;box-sizing:border-box}.noUi-target{position:relative}.noUi-base,.noUi-connects{width:100%;height:100%;position:relative;z-index:1}.noUi-connects{overflow:hidden;z-index:0}.noUi-connect,.noUi-origin{will-change:transform;position:absolute;z-index:1;top:0;right:0;-ms-transform-origin:0 0;-webkit-transform-origin:0 0;-webkit-transform-style:preserve-3d;transform-origin:0 0;transform-style:flat}.noUi-connect{height:100%;width:100%}.noUi-origin{height:10%;width:10%}.noUi-txt-dir-rtl.noUi-horizontal .noUi-origin{left:0;right:auto}.noUi-vertical .noUi-origin{width:0}.noUi-horizontal .noUi-origin{height:0}.noUi-handle{-webkit-backface-visibility:hidden;backface-visibility:hidden;position:absolute}.noUi-touch-area{height:100%;width:100%}.noUi-state-tap .noUi-connect,.noUi-state-tap .noUi-origin{-webkit-transition:transform .3s;transition:transform .3s}.noUi-state-drag *{cursor:inherit!important}.noUi-horizontal{height:18px}.noUi-horizontal .noUi-handle{width:34px;height:28px;right:-17px;top:-6px}.noUi-vertical{width:18px}.noUi-vertical .noUi-handle{width:28px;height:34px;right:-6px;top:-17px}.noUi-txt-dir-rtl.noUi-horizontal .noUi-handle{left:-17px;right:auto}.noUi-target{background:#FAFAFA;border-radius:4px;border:1px solid #D3D3D3;box-shadow:inset 0 1px 1px #F0F0F0,0 3px 6px -5px #BBB}.noUi-connects{border-radius:3px}.noUi-connect{background:#3FB8AF}.noUi-draggable{cursor:ew-resize}.noUi-vertical .noUi-draggable{cursor:ns-resize}.noUi-handle{border:1px solid #D9D9D9;border-radius:3px;background:#FFF;cursor:default;box-shadow:inset 0 0 1px #FFF,inset 0 1px 7px #EBEBEB,0 3px 6px -3px #BBB}.noUi-active{box-shadow:inset 0 0 1px #FFF,inset 0 1px 7px #DDD,0 3px 6px -3px #BBB}.noUi-handle:after,.noUi-handle:before{content:"";display:block;position:absolute;height:14px;width:1px;background:#E8E7E6;left:14px;top:6px}.noUi-handle:after{left:17px}.noUi-vertical .noUi-handle:after,.noUi-vertical .noUi-handle:before{width:14px;height:1px;left:6px;top:14px}.noUi-vertical .noUi-handle:after{top:17px}[disabled] .noUi-connect{background:#B8B8B8}[disabled] .noUi-handle,[disabled].noUi-handle,[disabled].noUi-target{cursor:not-allowed}.noUi-pips,.noUi-pips *{-moz-box-sizing:border-box;box-sizing:border-box}.noUi-pips{position:absolute;color:#999}.noUi-value{position:absolute;white-space:nowrap;text-align:center}.noUi-value-sub{color:#ccc;font-size:10px}.noUi-marker{position:absolute;background:#CCC}.noUi-marker-sub{background:#AAA}.noUi-marker-large{background:#AAA}.noUi-pips-horizontal{padding:10px 0;height:80px;top:100%;left:0;width:100%}.noUi-value-horizontal{-webkit-transform:translate(-50%,50%);transform:translate(-50%,50%)}.noUi-rtl .noUi-value-horizontal{-webkit-transform:translate(50%,50%);transform:translate(50%,50%)}.noUi-marker-horizontal.noUi-marker{margin-left:-1px;width:2px;height:5px}.noUi-marker-horizontal.noUi-marker-sub{height:10px}.noUi-marker-horizontal.noUi-marker-large{height:15px}.noUi-pips-vertical{padding:0 10px;height:100%;top:0;left:100%}.noUi-value-vertical{-webkit-transform:translate(0,-50%);transform:translate(0,-50%);padding-left:25px}.noUi-rtl .noUi-value-vertical{-webkit-transform:translate(0,50%);transform:translate(0,50%)}.noUi-marker-vertical.noUi-marker{width:5px;height:2px;margin-top:-1px}.noUi-marker-vertical.noUi-marker-sub{width:10px}.noUi-marker-vertical.noUi-marker-large{width:15px}.noUi-tooltip{display:block;position:absolute;border:1px solid #D9D9D9;border-radius:3px;background:#fff;color:#000;padding:5px;text-align:center;white-space:nowrap}.noUi-horizontal .noUi-tooltip{-webkit-transform:translate(-50%,0);transform:translate(-50%,0);left:50%;bottom:120%}.noUi-vertical .noUi-tooltip{-webkit-transform:translate(0,-50%);transform:translate(0,-50%);top:50%;right:120%}.noUi-horizontal .noUi-origin>.noUi-tooltip{-webkit-transform:translate(50%,0);transform:translate(50%,0);left:auto;bottom:10px}.noUi-vertical .noUi-origin>.noUi-tooltip{-webkit-transform:translate(0,-18px);transform:translate(0,-18px);top:auto;right:28px} | ||||
| @@ -67,3 +67,58 @@ table tbody tr td input[type="checkbox"] { | ||||
|   font-weight:bold; | ||||
|   color:white !important; | ||||
| } | ||||
| svg { | ||||
|   display: inline-block; | ||||
|   vertical-align: middle; | ||||
| } | ||||
| .c-1-color, | ||||
| .label-ham { | ||||
|   background: #28b62c; | ||||
| } | ||||
| .c-2-color, | ||||
| .label-spam { | ||||
|   background: #fff233; color: #333; | ||||
| } | ||||
| .c-3-color, | ||||
| .label-reject { | ||||
|   background: #ff4136; | ||||
| } | ||||
| #spam_score { | ||||
|   margin-bottom: 10px; | ||||
| } | ||||
| .noUi-handle { | ||||
|   border: 1px solid #e2e2e2; | ||||
|   border-radius: 0px; | ||||
|   background: #eee; | ||||
|   cursor: default; | ||||
|   box-shadow: none; | ||||
|   border-top-width: 0px; | ||||
|   border-right-width: 1px; | ||||
|   border-bottom-width: 4px; | ||||
|   border-left-width: 1px; | ||||
| } | ||||
| .noUi-handle:hover { | ||||
|   background-color: #eee; | ||||
|   border-color: #e2e2e2; | ||||
|   margin-top: 1px; | ||||
| border-bottom-width: 3px; | ||||
| } | ||||
| .noUi-handle::after, .noUi-handle::before { | ||||
|   background: #555; | ||||
| } | ||||
| .noUi-target { | ||||
|   background: transparent; | ||||
|   border-radius: 0px; | ||||
|   border: 1px solid #D3D3D3; | ||||
|   box-shadow: none; | ||||
| } | ||||
| .noUi-connects { | ||||
|   border-radius: 0px; | ||||
| } | ||||
| .label-ham, | ||||
| .label-spam, | ||||
| .label-reject { | ||||
|   padding: .1em .5em .1em; | ||||
|   font-size: inherit; | ||||
|   font-weight: 400; | ||||
| } | ||||
| @@ -262,6 +262,7 @@ if (isset($_SESSION['mailcow_cc_role'])) { | ||||
|             <li class="active"><a data-toggle="tab" href="#dedit"><?=$lang['edit']['domain'];?></a></li> | ||||
|             <li><a data-toggle="tab" href="#dratelimit"><?=$lang['edit']['ratelimit'];?></a></li> | ||||
|             <li><a data-toggle="tab" href="#dspamfilter"><?=$lang['edit']['spam_filter'];?></a></li> | ||||
|             <li><a data-toggle="tab" href="#dqwbcc"><?=$lang['edit']['quota_warning_bcc'];?></a></li> | ||||
|           </ul> | ||||
|           <hr> | ||||
|           <div class="tab-content"> | ||||
|   | ||||
| @@ -13,6 +13,17 @@ function isset_has_content($var) { | ||||
|     return false; | ||||
|   } | ||||
| } | ||||
| function readable_random_string($length = 8) { | ||||
|   $string = ''; | ||||
|   $vowels = array('a', 'e', 'i', 'o', 'u'); | ||||
|   $consonants = array('b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'); | ||||
|   $max = $length / 2; | ||||
|   for ($i = 1; $i <= $max; $i++) { | ||||
|     $string .= $consonants[rand(0,19)]; | ||||
|     $string .= $vowels[rand(0,4)]; | ||||
|   } | ||||
|   return $string; | ||||
| } | ||||
| // Validates ips and cidrs | ||||
| function valid_network($network) { | ||||
|   if (filter_var($network, FILTER_VALIDATE_IP)) { | ||||
| @@ -951,7 +962,6 @@ function user_get_alias_details($username) { | ||||
|   $run = $stmt->fetchAll(PDO::FETCH_ASSOC); | ||||
|   while ($row = array_shift($run)) { | ||||
|     $data['shared_aliases'][$row['shared_aliases']]['public_comment'] = htmlspecialchars($row['public_comment']); | ||||
|  | ||||
|     //$data['shared_aliases'][] = $row['shared_aliases']; | ||||
|   } | ||||
|  | ||||
| @@ -978,6 +988,7 @@ function user_get_alias_details($username) { | ||||
|       continue; | ||||
|     } | ||||
|     $data['direct_aliases'][$row['ad_alias']]['public_comment'] = '↪ ' . $row['alias_domain']; | ||||
|     $data['alias_domains'][] = $row['alias_domain']; | ||||
|   } | ||||
|   $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`send_as` SEPARATOR ', '), '✘') AS `send_as` FROM `sender_acl` WHERE `logged_in_as` = :username AND `send_as` NOT LIKE '@%';"); | ||||
|   $stmt->execute(array(':username' => $username)); | ||||
|   | ||||
| @@ -35,7 +35,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { | ||||
|           else { | ||||
|             $username = $_SESSION['mailcow_cc_username']; | ||||
|           } | ||||
|           if (!is_numeric($_data["validity"]) || $_data["validity"] > 672) { | ||||
|           if (isset($_data["validity"]) && !filter_var($_data["validity"], FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 87600)))) { | ||||
|             $_SESSION['return'][] = array( | ||||
|               'type' => 'danger', | ||||
|               'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), | ||||
| @@ -43,8 +43,17 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { | ||||
|             ); | ||||
|             return false; | ||||
|           } | ||||
|           $domain = mailbox('get', 'mailbox_details', $username)['domain']; | ||||
|           if (!is_valid_domain_name($domain)) { | ||||
|           else { | ||||
|             // Default to 1 yr | ||||
|             $_data["validity"] = 8760; | ||||
|           } | ||||
|           $domain = $_data['domain']; | ||||
|           $valid_domains[] = mailbox('get', 'mailbox_details', $username)['domain']; | ||||
|           $valid_alias_domains = user_get_alias_details($username)['alias_domains']; | ||||
|           if (!empty($valid_alias_domains)) { | ||||
|             $valid_domains = array_merge($valid_domains, $valid_alias_domains); | ||||
|           } | ||||
|           if (!in_array($domain, $valid_domains)) { | ||||
|             $_SESSION['return'][] = array( | ||||
|               'type' => 'danger', | ||||
|               'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), | ||||
| @@ -52,13 +61,11 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { | ||||
|             ); | ||||
|             return false; | ||||
|           } | ||||
|           $validity = strtotime("+".$_data["validity"]." hour"); | ||||
|           $letters = 'abcefghijklmnopqrstuvwxyz1234567890'; | ||||
|           $random_name = substr(str_shuffle($letters), 0, 24); | ||||
|           $validity = strtotime("+" . $_data["validity"] . " hour"); | ||||
|           $stmt = $pdo->prepare("INSERT INTO `spamalias` (`address`, `goto`, `validity`) VALUES | ||||
|             (:address, :goto, :validity)"); | ||||
|           $stmt->execute(array( | ||||
|             ':address' => $random_name . '@' . $domain, | ||||
|             ':address' => readable_random_string(rand(rand(3, 9), rand(3, 9))) . '.' . readable_random_string(rand(rand(3, 9), rand(3, 9))) . '@' . $domain, | ||||
|             ':goto' => $username, | ||||
|             ':validity' => $validity | ||||
|           )); | ||||
| @@ -3147,7 +3154,9 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { | ||||
|           } | ||||
|           $stmt = $pdo->prepare("SELECT `address`, | ||||
|             `goto`, | ||||
|             `validity` | ||||
|             `validity`, | ||||
|             `created`, | ||||
|             `modified` | ||||
|               FROM `spamalias` | ||||
|                 WHERE `goto` = :username | ||||
|                   AND `validity` >= :unixnow"); | ||||
|   | ||||
| @@ -65,3 +65,76 @@ function quota_notification($_action, $_data = null) { | ||||
|     break; | ||||
|   } | ||||
| } | ||||
| function quota_notification_bcc($_action, $_data = null) { | ||||
| 	global $redis; | ||||
| 	$_data_log = $_data; | ||||
|   if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") { | ||||
|     $_SESSION['return'][] = array( | ||||
|       'type' => 'danger', | ||||
|       'log' => array(__FUNCTION__, $_action, $_data_log), | ||||
|       'msg' => 'access_denied' | ||||
|     ); | ||||
|     return false; | ||||
|   } | ||||
|   switch ($_action) { | ||||
|     case 'edit': | ||||
|       $domain = $_data['domain']; | ||||
|       if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { | ||||
|         $_SESSION['return'][] = array( | ||||
|           'type' => 'danger', | ||||
|           'log' => array(__FUNCTION__, $_action, $_data_log), | ||||
|           'msg' => 'access_denied' | ||||
|         ); | ||||
|         return false; | ||||
|       } | ||||
|       $active = intval($_data['active']); | ||||
|       $bcc_rcpt = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $_data['bcc_rcpt']); | ||||
|       if (filter_var($bcc_rcpt, FILTER_VALIDATE_EMAIL) === false) { | ||||
|         $_SESSION['return'][] = array( | ||||
|           'type' => 'danger', | ||||
|           'log' => array(__FUNCTION__, $_action, $_data_log), | ||||
|           'msg' => 'access_denied' | ||||
|         ); | ||||
|         return false; | ||||
|       } | ||||
|       try { | ||||
|         $redis->hSet('QW_BCC', $domain, json_encode(array('bcc_rcpt' => $bcc_rcpt, 'active' => $active))); | ||||
|       } | ||||
|       catch (RedisException $e) { | ||||
|         $_SESSION['return'][] = array( | ||||
|           'type' => 'danger', | ||||
|           'log' => array(__FUNCTION__, $_action, $_data_log), | ||||
|           'msg' => array('redis_error', $e) | ||||
|         ); | ||||
|         return false; | ||||
|       } | ||||
|       $_SESSION['return'][] = array( | ||||
|         'type' => 'success', | ||||
|         'log' => array(__FUNCTION__, $_action, $_data_log), | ||||
|         'msg' => 'saved_settings' | ||||
|       ); | ||||
|     break; | ||||
|     case 'get': | ||||
|       $domain = $_data['domain']; | ||||
|       if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { | ||||
|         $_SESSION['return'][] = array( | ||||
|           'type' => 'danger', | ||||
|           'log' => array(__FUNCTION__, $_action, $_data_log), | ||||
|           'msg' => 'access_denied' | ||||
|         ); | ||||
|         return false; | ||||
|       } | ||||
|       try { | ||||
|         return json_decode($redis->hGet('QW_BCC', $domain), true); | ||||
|       } | ||||
|       catch (RedisException $e) { | ||||
|         $_SESSION['return'][] = array( | ||||
|           'type' => 'danger', | ||||
|           'log' => array(__FUNCTION__, $_action, $_data_log), | ||||
|           'msg' => array('redis_error', $e) | ||||
|         ); | ||||
|         return false; | ||||
|       } | ||||
|     break; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -3,7 +3,7 @@ function init_db_schema() { | ||||
|   try { | ||||
|     global $pdo; | ||||
|  | ||||
|     $db_version = "09032021_1000"; | ||||
|     $db_version = "21052021_0900"; | ||||
|  | ||||
|     $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); | ||||
|     $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); | ||||
| @@ -445,7 +445,9 @@ function init_db_schema() { | ||||
|         "cols" => array( | ||||
|           "address" => "VARCHAR(255) NOT NULL", | ||||
|           "goto" => "TEXT NOT NULL", | ||||
|           "validity" => "INT(11) NOT NULL" | ||||
|           "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", | ||||
|           "modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP", | ||||
|           "validity" => "INT(11)" | ||||
|         ), | ||||
|         "keys" => array( | ||||
|           "primary" => array( | ||||
|   | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								data/web/js/build/003-slider.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								data/web/js/build/003-slider.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -195,7 +195,7 @@ $(document).ready(function() { | ||||
|     } else if ($(this).hasClass('btn')) { | ||||
|       $(this).attr("disabled", true); | ||||
|     } else if ($(this).attr('data-provide') == 'slider') { | ||||
|       $(this).slider("disable"); | ||||
|       $(this).attr('disabled', true); | ||||
|     } else if ($(this).is(':checkbox')) { | ||||
|       $(this).attr("disabled", true); | ||||
|     } | ||||
|   | ||||
| @@ -1,4 +1,31 @@ | ||||
| $(document).ready(function() { | ||||
|   // Spam score slider | ||||
|   var spam_slider = $('#spam_score')[0]; | ||||
|   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({ | ||||
| @@ -50,8 +77,9 @@ jQuery(function($){ | ||||
|     ft_tla_table = FooTable.init('#tla_table', { | ||||
|       "columns": [ | ||||
|         {"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px","text-align":"center"},"filterable": false,"sortable": false,"type":"html"}, | ||||
|         {"sorted": true,"name":"address","title":lang.alias}, | ||||
|         {"name":"address","title":lang.alias}, | ||||
|         {"name":"validity","formatter":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"});},"title":lang.alias_valid_until,"style":{"width":"170px"}}, | ||||
|         {"sorted": true,"sortValue": function(value){res = new Date(value);return res.getTime();},"direction":"DESC","name":"created","formatter":function date_format(datetime) { var date = new Date(datetime); 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,"style":{"width":"170px"}}, | ||||
|         {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} | ||||
|       ], | ||||
|       "empty": lang.empty, | ||||
|   | ||||
| @@ -740,9 +740,9 @@ | ||||
|         "owner": "Besitzer", | ||||
|         "private_comment": "Privater Kommentar", | ||||
|         "public_comment": "Öffentlicher Kommentar", | ||||
|         "q_add_header": "Junk-Ordner", | ||||
|         "q_all": "Alle Kategorien", | ||||
|         "q_reject": "Abgelehnt", | ||||
|         "q_add_header": "bei Mail in Junk-Ordner", | ||||
|         "q_all": "bei Reject und Mail in Junk-Ordner", | ||||
|         "q_reject": "bei Reject", | ||||
|         "quarantine_notification": "Quarantäne-Benachrichtigung", | ||||
|         "quarantine_category": "Quarantäne-Benachrichtigungskategorie", | ||||
|         "quick_actions": "Aktionen", | ||||
| @@ -1009,6 +1009,7 @@ | ||||
|         "client_configuration": "Konfigurationsanleitungen für E-Mail-Programme und Smartphones anzeigen", | ||||
|         "create_app_passwd": "Erstelle App-Passwort", | ||||
|         "create_syncjob": "Neuen Sync-Job erstellen", | ||||
|         "created_on": "Erstellt am", | ||||
|         "daily": "Täglich", | ||||
|         "day": "Tag", | ||||
|         "delete_ays": "Soll der Löschvorgang wirklich ausgeführt werden?", | ||||
| @@ -1036,6 +1037,8 @@ | ||||
|         "loading": "Lade...", | ||||
|         "mailbox_details": "Mailbox-Details", | ||||
|         "messages": "Nachrichten", | ||||
|         "month": "Monat", | ||||
|         "months": "Monate", | ||||
|         "never": "Niemals", | ||||
|         "new_password": "Neues Passwort", | ||||
|         "new_password_repeat": "Neues Passwort (Wiederholung)", | ||||
| @@ -1111,7 +1114,9 @@ | ||||
|         "waiting": "Warte auf Ausführung", | ||||
|         "week": "Woche", | ||||
|         "weekly": "Wöchentlich", | ||||
|         "weeks": "Wochen" | ||||
|         "weeks": "Wochen", | ||||
|         "year": "Jahr", | ||||
|         "years": "Jahren" | ||||
|     }, | ||||
|     "warning": { | ||||
|         "cannot_delete_self": "Kann derzeit eingeloggten Benutzer nicht entfernen", | ||||
|   | ||||
| @@ -738,9 +738,9 @@ | ||||
|         "owner": "Owner", | ||||
|         "private_comment": "Private comment", | ||||
|         "public_comment": "Public comment", | ||||
|         "q_add_header": "Junk folder", | ||||
|         "q_all": "All categories", | ||||
|         "q_reject": "Rejected", | ||||
|         "q_add_header": "when moved to Junk folder", | ||||
|         "q_all": " when moved to Junk folder and on reject", | ||||
|         "q_reject": "on reject", | ||||
|         "quarantine_notification": "Quarantine notifications", | ||||
|         "quarantine_category": "Quarantine notification category", | ||||
|         "quick_actions": "Actions", | ||||
| @@ -1007,6 +1007,7 @@ | ||||
|         "client_configuration": "Show configuration guides for email clients and smartphones", | ||||
|         "create_app_passwd": "Create app password", | ||||
|         "create_syncjob": "Create new sync job", | ||||
|         "created_on": "Created on", | ||||
|         "daily": "Daily", | ||||
|         "day": "day", | ||||
|         "delete_ays": "Please confirm the deletion process.", | ||||
| @@ -1034,6 +1035,8 @@ | ||||
|         "loading": "Loading...", | ||||
|         "mailbox_details": "Mailbox details", | ||||
|         "messages": "messages", | ||||
|         "month": "month", | ||||
|         "months": "months", | ||||
|         "never": "Never", | ||||
|         "new_password": "New password", | ||||
|         "new_password_repeat": "Confirmation password (repeat)", | ||||
| @@ -1109,7 +1112,9 @@ | ||||
|         "waiting": "Waiting", | ||||
|         "week": "week", | ||||
|         "weekly": "Weekly", | ||||
|         "weeks": "weeks" | ||||
|         "weeks": "weeks", | ||||
|         "year": "year", | ||||
|         "years": "years" | ||||
|     }, | ||||
|     "warning": { | ||||
|         "cannot_delete_self": "Cannot delete logged in user", | ||||
|   | ||||
| @@ -283,6 +283,42 @@ if (!isset($_SESSION['mailcow_cc_role'])) { | ||||
|     </div> | ||||
|   </div> | ||||
| </div><!-- pw change modal --> | ||||
| <!-- pw change modal --> | ||||
| <div class="modal fade" id="tempAliasModal" tabindex="-1" role="dialog" aria-labelledby="tempAliasModalLabel"> | ||||
|   <div class="modal-dialog" role="document"> | ||||
|     <div class="modal-content"> | ||||
|       <div class="modal-body"> | ||||
|         <form class="form-horizontal" data-cached-form="false" data-id="pwchange" role="form" method="post" autocomplete="off"> | ||||
|           <div class="form-group"> | ||||
|             <label class="control-label col-sm-3" for="user_new_pass"><?=$lang['user']['new_password'];?> (<a href="#" class="generate_password"><?=$lang['user']['generate'];?></a>)</label> | ||||
|             <div class="col-sm-5"> | ||||
|             <input type="password" data-pwgen-field="true" data-hibp="true" class="form-control" name="user_new_pass" autocomplete="new-password" required> | ||||
|             </div> | ||||
|           </div> | ||||
|           <div class="form-group"> | ||||
|             <label class="control-label col-sm-3" for="user_new_pass2"><?=$lang['user']['new_password_repeat'];?></label> | ||||
|             <div class="col-sm-5"> | ||||
|             <input type="password" data-pwgen-field="true" class="form-control" name="user_new_pass2" autocomplete="new-password" required> | ||||
|             <p class="help-block"><?=$lang['user']['new_password_description'];?></p> | ||||
|             </div> | ||||
|           </div> | ||||
|           <hr> | ||||
|           <div class="form-group"> | ||||
|             <label class="control-label col-sm-3" for="user_old_pass"><?=$lang['user']['password_now'];?></label> | ||||
|             <div class="col-sm-5"> | ||||
|             <input type="password" class="form-control" name="user_old_pass" autocomplete="off" required> | ||||
|             </div> | ||||
|           </div> | ||||
|           <div class="form-group"> | ||||
|             <div class="col-sm-offset-3 col-sm-9"> | ||||
|               <button class="btn btn-default" data-action="edit_selected" data-id="pwchange" data-item="null" data-api-url='edit/self' data-api-attr='{}' href="#"><?=$lang['user']['change_password'];?></button> | ||||
|             </div> | ||||
|           </div> | ||||
|         </form> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </div><!-- pw change modal --> | ||||
| <!-- sieve filter modal --> | ||||
| <div class="modal fade" id="userFilterModal" tabindex="-1" role="dialog"> | ||||
|   <div class="modal-dialog" role="document"> | ||||
|   | ||||
| @@ -222,6 +222,11 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == ' | ||||
|         <hr> | ||||
|         <?php // Get user information about aliases | ||||
|         $user_get_alias_details = user_get_alias_details($username); | ||||
|         $user_domains[] = mailbox('get', 'mailbox_details', $username)['domain']; | ||||
|         $user_alias_domains = $user_get_alias_details['alias_domains']; | ||||
|         if (!empty($user_alias_domains)) { | ||||
|           $user_domains = array_merge($user_domains, $user_alias_domains); | ||||
|         } | ||||
|         ?> | ||||
|         <div class="row"> | ||||
|           <div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['direct_aliases'];?>: | ||||
| @@ -448,22 +453,29 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == ' | ||||
|           <a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a> | ||||
|           <ul class="dropdown-menu"> | ||||
|             <li><a data-action="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{"validity":"1"}' href="#"><?=$lang['user']['expire_in'];?> 1 <?=$lang['user']['hour'];?></a></li> | ||||
|             <li><a data-action="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{"validity":"6"}' href="#"><?=$lang['user']['expire_in'];?> 6 <?=$lang['user']['hours'];?></a></li> | ||||
|             <li><a data-action="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{"validity":"24"}' href="#"><?=$lang['user']['expire_in'];?> 1 <?=$lang['user']['day'];?></a></li> | ||||
|             <li><a data-action="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{"validity":"168"}' href="#"><?=$lang['user']['expire_in'];?> 1 <?=$lang['user']['week'];?></a></li> | ||||
|             <li><a data-action="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{"validity":"672"}' href="#"><?=$lang['user']['expire_in'];?> 4 <?=$lang['user']['weeks'];?></a></li> | ||||
|             <li><a data-action="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{"validity":"744"}' href="#"><?=$lang['user']['expire_in'];?> 1 <?=$lang['user']['month'];?></a></li> | ||||
|             <li><a data-action="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{"validity":"8760"}' href="#"><?=$lang['user']['expire_in'];?> 1 <?=$lang['user']['year'];?></a></li> | ||||
|             <li><a data-action="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{"validity":"87600"}' href="#"><?=$lang['user']['expire_in'];?> 10 <?=$lang['user']['years'];?></a></li> | ||||
|             <li role="separator" class="divider"></li> | ||||
|             <li><a data-action="delete_selected" data-id="tla" data-api-url='delete/time_limited_alias' href="#"><?=$lang['mailbox']['remove'];?></a></li> | ||||
|           </ul> | ||||
|         </div> | ||||
|         <div class="btn-group"> | ||||
|           <a class="btn btn-sm btn-success dropdown-toggle" data-toggle="dropdown" href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['user']['alias_create_random'];?> <span class="caret"></span></a> | ||||
|           <a class="btn btn-sm btn-success dropdown-toggle" data-toggle="dropdown" href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['user']['alias_create_random'];?>, 1 <?=$lang['user']['year'];?> <span class="caret"></span></a> | ||||
|           <ul class="dropdown-menu"> | ||||
|             <li><a data-action="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"validity":"1"}' href="#">1 <?=$lang['user']['hour'];?></a></li> | ||||
|             <li><a data-action="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"validity":"6"}' href="#">6 <?=$lang['user']['hours'];?></a></li> | ||||
|             <li><a data-action="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"validity":"24"}' href="#">1 <?=$lang['user']['day'];?></a></li> | ||||
|             <li><a data-action="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"validity":"168"}' href="#">1 <?=$lang['user']['week'];?></a></li> | ||||
|             <li><a data-action="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"validity":"672"}' href="#">4 <?=$lang['user']['weeks'];?></a></li> | ||||
|           <?php | ||||
|           foreach($user_domains as $domain) { | ||||
|           ?> | ||||
|             <li> | ||||
|               <a data-action="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"domain":"<?=$domain;?>"}' href="#"> | ||||
|                 @ <?=$domain;?> | ||||
|               </a> | ||||
|             </li> | ||||
|           <?php | ||||
|           } | ||||
|           ?> | ||||
|           </ul> | ||||
|         </div> | ||||
|       </div> | ||||
| @@ -474,43 +486,28 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == ' | ||||
| 		<h4><?=$lang['user']['spamfilter_behavior'];?></h4> | ||||
| 		<form class="form-horizontal" role="form" data-id="spam_score" method="post"> | ||||
| 			<div class="form-group"> | ||||
| 				<div class="col-lg-6 col-sm-12"> | ||||
| 					<input data-acl="<?=$_SESSION['acl']['spam_score'];?>" name="spam_score" id="spam_score" type="text" style="width: 100%;" | ||||
| 						data-provide="slider" | ||||
| 						data-slider-min="1" | ||||
| 						data-slider-max="2000" | ||||
|             data-slider-scale='logarithmic' | ||||
| 						data-slider-step="0.5" | ||||
| 						data-slider-range="true" | ||||
| 						data-slider-tooltip='always' | ||||
| 						data-slider-id="slider1" | ||||
| 						data-slider-value="[<?=mailbox('get', 'spam_score', $username);?>]" | ||||
| 						data-slider-step="1" /> | ||||
| 					<br /><br /> | ||||
| 					<ul> | ||||
| 						<li><?=$lang['user']['spamfilter_green'];?></li> | ||||
| 						<li><?=$lang['user']['spamfilter_yellow'];?></li> | ||||
| 						<li><?=$lang['user']['spamfilter_red'];?></li> | ||||
| 				<div class="col-lg-8 col-sm-12"> | ||||
|           <div id="spam_score" data-provide="slider" data-acl="<?=$_SESSION['acl']['spam_score'];?>"></div> | ||||
| 					<input id="spam_score_value" name="spam_score" type="hidden" value="<?=mailbox('get', 'spam_score', $username);?>"> | ||||
| 					<ul class="list-group list-group-flush"> | ||||
| 						<li class="list-group-item"><span class="label label-ham spam-ham-score"></span> <?=$lang['user']['spamfilter_green'];?></li> | ||||
| 						<li class="list-group-item"><span class="label label-spam spam-spam-score"></span> <?=$lang['user']['spamfilter_yellow'];?></li> | ||||
| 						<li class="list-group-item"><span class="label label-reject spam-reject-score"></span> <?=$lang['user']['spamfilter_red'];?></li> | ||||
| 					</ul> | ||||
| 					<p><?=$lang['user']['spamfilter_hint'];?></p> | ||||
| 				</div> | ||||
| 			</div> | ||||
|       <div class="form-group"> | ||||
| 				<div class="col-sm-10"> | ||||
| 				</div> | ||||
|         <div class="btn-group" data-acl="<?=$_SESSION['acl']['spam_policy'];?>"> | ||||
|           <a type="button" class="btn btn-sm btn-success" data-action="edit_selected" | ||||
|             data-item="<?= htmlentities($username); ?>" | ||||
|             data-id="spam_score" | ||||
|             data-api-url='edit/spam-score' | ||||
|             data-api-attr='{}'><?=$lang['user']['save_changes'];?></a> | ||||
|           <a type="button" class="btn btn-sm btn-default" data-action="edit_selected" | ||||
|             data-item="<?= htmlentities($username); ?>" | ||||
|             data-id="spam_score_reset" | ||||
|             data-api-url='edit/spam-score' | ||||
|             data-api-attr='{"spam_score":"default"}'><?=$lang['user']['spam_score_reset'];?></a> | ||||
|         </div> | ||||
| 			</div> | ||||
|       <div class="btn-group" data-acl="<?=$_SESSION['acl']['spam_policy'];?>"> | ||||
|         <a type="button" class="btn btn-sm btn-success" data-action="edit_selected" | ||||
|           data-item="<?= htmlentities($username); ?>" | ||||
|           data-id="spam_score" | ||||
|           data-api-url='edit/spam-score' | ||||
|           data-api-attr='{}'><?=$lang['user']['save_changes'];?></a> | ||||
|         <a type="button" class="btn btn-sm btn-default" data-action="edit_selected" | ||||
|           data-item="<?= htmlentities($username); ?>" | ||||
|           data-id="spam_score_reset" | ||||
|           data-api-url='edit/spam-score' | ||||
|           data-api-attr='{"spam_score":"default"}'><?=$lang['user']['spam_score_reset'];?></a> | ||||
|       </div> | ||||
| 		</form> | ||||
| 		<hr> | ||||
| 		<div class="row"> | ||||
| @@ -690,11 +687,12 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/modals/user.php'; | ||||
| <script type='text/javascript'> | ||||
| <?php | ||||
| $lang_user = json_encode($lang['user']); | ||||
| echo "var lang = ". $lang_user . ";\n"; | ||||
| echo "var acl = '". json_encode($_SESSION['acl']) . "';\n"; | ||||
| echo "var csrf_token = '". $_SESSION['CSRF']['TOKEN'] . "';\n"; | ||||
| echo "var mailcow_cc_username = '". $_SESSION['mailcow_cc_username'] . "';\n"; | ||||
| echo "var pagination_size = '". $PAGINATION_SIZE . "';\n"; | ||||
| echo "var lang = " . $lang_user . ";\n"; | ||||
| echo "var user_spam_score = [" . mailbox('get', 'spam_score', $username) . "];\n"; | ||||
| echo "var acl = '" . json_encode($_SESSION['acl']) . "';\n"; | ||||
| echo "var csrf_token = '" . $_SESSION['CSRF']['TOKEN'] . "';\n"; | ||||
| echo "var mailcow_cc_username = '" . $_SESSION['mailcow_cc_username'] . "';\n"; | ||||
| echo "var pagination_size = '" . $PAGINATION_SIZE . "';\n"; | ||||
| ?> | ||||
| </script> | ||||
| <?php | ||||
|   | ||||
		Reference in New Issue
	
	Block a user