| @@ -381,11 +381,14 @@ class DockerUtils: | ||||
|       for container in self.docker_client.containers.list(filters={"id": container_id}): | ||||
|         sane_name = re.sub(r'\W+', '', request_json['maildir']) | ||||
|         vmail_name = request_json['maildir'].replace("'", "'\\''") | ||||
|         index_name = request_json['maildir'].split("/") | ||||
|         index_name = index_name[1].replace("'", "'\\''") + "@" + index_name[0].replace("'", "'\\''") | ||||
|         cmd_vmail = "if [[ -d '/var/vmail/" + vmail_name + "' ]]; then /bin/mv '/var/vmail/" + vmail_name + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "'; fi" | ||||
|         cmd_vmail_index = "if [[ -d '/var/vmail_index/" + index_name + "' ]]; then /bin/mv '/var/vmail_index/" + index_name + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "_index'; fi" | ||||
|         cmd = ["/bin/bash", "-c", cmd_vmail + " && " + cmd_vmail_index] | ||||
|         index_name = request_json['maildir'].split("/") | ||||
|         if len(index_name) > 1: | ||||
|           index_name = index_name[1].replace("'", "'\\''") + "@" + index_name[0].replace("'", "'\\''") | ||||
|           cmd_vmail_index = "if [[ -d '/var/vmail_index/" + index_name + "' ]]; then /bin/mv '/var/vmail_index/" + index_name + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "_index'; fi" | ||||
|           cmd = ["/bin/bash", "-c", cmd_vmail + " && " + cmd_vmail_index] | ||||
|         else: | ||||
|           cmd = ["/bin/bash", "-c", cmd_vmail] | ||||
|         maildir_cleanup = container.exec_run(cmd, user='vmail') | ||||
|         return exec_run_handler('generic', maildir_cleanup) | ||||
|   # api call: container_post - post_action: exec - cmd: rspamd - task: worker_password | ||||
|   | ||||
| @@ -342,6 +342,10 @@ div.dataTables_wrapper div.dt-row { | ||||
|   position: relative; | ||||
| } | ||||
|  | ||||
| div.dataTables_wrapper span.sorting-value { | ||||
|   display: none; | ||||
| } | ||||
|  | ||||
| div.dataTables_scrollHead table.dataTable { | ||||
|   margin-bottom: 0 !important; | ||||
| } | ||||
|   | ||||
| @@ -66,4 +66,6 @@ table tbody tr td input[type="checkbox"] { | ||||
|   padding: .2em .4em .3em !important; | ||||
|   background-color: #ececec!important; | ||||
| } | ||||
|  | ||||
| .badge.bg-info .bi { | ||||
|   font-size: inherit; | ||||
| } | ||||
|   | ||||
| @@ -20,6 +20,11 @@ legend { | ||||
|     background-color: #7a7a7a !important; | ||||
|     border-color: #5c5c5c !important; | ||||
| } | ||||
| .btn-dark { | ||||
|   color: #000 !important;; | ||||
|   background-color: #f6f6f6 !important;; | ||||
|   border-color: #ddd !important;; | ||||
| } | ||||
| .btn-check:checked+.btn-secondary, .btn-check:active+.btn-secondary, .btn-secondary:active, .btn-secondary.active, .show>.btn-secondary.dropdown-toggle { | ||||
|     border-color: #7a7a7a !important; | ||||
| } | ||||
| @@ -299,22 +304,22 @@ a:hover { | ||||
| } | ||||
|  | ||||
|  | ||||
| table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before:hover,  | ||||
| table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before:hover, | ||||
| table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before:hover { | ||||
|   background-color: #7a7a7a !important; | ||||
| } | ||||
| table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before,  | ||||
| table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before, | ||||
| table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before { | ||||
|   background-color: #7a7a7a !important; | ||||
|   border: 1.5px solid #5c5c5c !important; | ||||
|   color: #fff !important; | ||||
| } | ||||
| table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td.dtr-control:before,  | ||||
| table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td.dtr-control:before, | ||||
| table.dataTable.dtr-inline.collapsed>tbody>tr.parent>th.dtr-control:before { | ||||
|   background-color: #949494; | ||||
| } | ||||
| table.dataTable.dtr-inline.collapsed>tbody>tr>td.child,  | ||||
| table.dataTable.dtr-inline.collapsed>tbody>tr>th.child,  | ||||
| table.dataTable.dtr-inline.collapsed>tbody>tr>td.child, | ||||
| table.dataTable.dtr-inline.collapsed>tbody>tr>th.child, | ||||
| table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty { | ||||
|   background-color: #444444; | ||||
| } | ||||
| @@ -327,7 +332,7 @@ table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty { | ||||
| } | ||||
| .btn.btn-outline-secondary { | ||||
|   color: #fff !important; | ||||
|   border-color: #7a7a7a !important;   | ||||
|   border-color: #7a7a7a !important; | ||||
| } | ||||
| .btn-check:checked+.btn-outline-secondary, .btn-check:active+.btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show { | ||||
|     background-color: #9b9b9b !important; | ||||
|   | ||||
| @@ -1015,20 +1015,58 @@ function formatBytes($size, $precision = 2) { | ||||
|   } | ||||
|   return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)]; | ||||
| } | ||||
| function update_sogo_static_view() { | ||||
| function update_sogo_static_view($mailbox = null) { | ||||
|   if (getenv('SKIP_SOGO') == "y") { | ||||
|     return true; | ||||
|   } | ||||
|   global $pdo; | ||||
|   global $lang; | ||||
|   $stmt = $pdo->query("SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES | ||||
|     WHERE TABLE_NAME = 'sogo_view'"); | ||||
|   $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); | ||||
|   if ($num_results != 0) { | ||||
|     $stmt = $pdo->query("REPLACE INTO _sogo_static_view (`c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings`) | ||||
|       SELECT `c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings` from sogo_view"); | ||||
|     $stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');"); | ||||
|  | ||||
|   $mailbox_exists = false; | ||||
|   if ($mailbox !== null) { | ||||
|     // Check if the mailbox exists | ||||
|     $stmt = $pdo->prepare("SELECT username FROM mailbox WHERE username = :mailbox AND active = '1'"); | ||||
|     $stmt->execute(array(':mailbox' => $mailbox)); | ||||
|     $row = $stmt->fetch(PDO::FETCH_ASSOC);   | ||||
|     if ($row){ | ||||
|       $mailbox_exists = true; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   $query = "REPLACE INTO _sogo_static_view (`c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings`) | ||||
|             SELECT | ||||
|               mailbox.username, | ||||
|               mailbox.domain, | ||||
|               mailbox.username, | ||||
|               IF(JSON_UNQUOTE(JSON_VALUE(attributes, '$.force_pw_update')) = '0', | ||||
|                  IF(JSON_UNQUOTE(JSON_VALUE(attributes, '$.sogo_access')) = 1, password, '{SSHA256}A123A123A321A321A321B321B321B123B123B321B432F123E321123123321321'), | ||||
|                  '{SSHA256}A123A123A321A321A321B321B321B123B123B321B432F123E321123123321321'), | ||||
|               mailbox.name, | ||||
|               mailbox.username, | ||||
|               IFNULL(GROUP_CONCAT(ga.aliases ORDER BY ga.aliases SEPARATOR ' '), ''), | ||||
|               IFNULL(gda.ad_alias, ''), | ||||
|               IFNULL(external_acl.send_as_acl, ''), | ||||
|               mailbox.kind, | ||||
|               mailbox.multiple_bookings | ||||
|             FROM | ||||
|               mailbox | ||||
|               LEFT OUTER JOIN grouped_mail_aliases ga ON ga.username REGEXP CONCAT('(^|,)', mailbox.username, '($|,)') | ||||
|               LEFT OUTER JOIN grouped_domain_alias_address gda ON gda.username = mailbox.username | ||||
|               LEFT OUTER JOIN grouped_sender_acl_external external_acl ON external_acl.username = mailbox.username | ||||
|             WHERE | ||||
|               mailbox.active = '1'"; | ||||
|    | ||||
|   if ($mailbox_exists) { | ||||
|     $query .= " AND mailbox.username = :mailbox"; | ||||
|     $stmt = $pdo->prepare($query); | ||||
|     $stmt->execute(array(':mailbox' => $mailbox)); | ||||
|   } else { | ||||
|     $query .= " GROUP BY mailbox.username"; | ||||
|     $stmt = $pdo->query($query); | ||||
|   } | ||||
|    | ||||
|   $stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');"); | ||||
|    | ||||
|   flush_memcached(); | ||||
| } | ||||
| function edit_user_account($_data) { | ||||
|   | ||||
| @@ -1264,11 +1264,13 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { | ||||
|             )); | ||||
|           } | ||||
|  | ||||
|           update_sogo_static_view($username); | ||||
|           $_SESSION['return'][] = array( | ||||
|             'type' => 'success', | ||||
|             'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), | ||||
|             'msg' => array('mailbox_added', htmlspecialchars($username)) | ||||
|           ); | ||||
|           return true; | ||||
|         break; | ||||
|         case 'resource': | ||||
|           $domain             = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46); | ||||
| @@ -3130,7 +3132,10 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { | ||||
|               'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), | ||||
|               'msg' => array('mailbox_modified', $username) | ||||
|             ); | ||||
|  | ||||
|             update_sogo_static_view($username); | ||||
|           } | ||||
|           return true; | ||||
|         break; | ||||
|         case 'mailbox_templates': | ||||
|           if ($_SESSION['mailcow_cc_role'] != "admin") { | ||||
| @@ -5053,12 +5058,15 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { | ||||
|               ); | ||||
|               continue; | ||||
|             } | ||||
|              | ||||
|             update_sogo_static_view($username); | ||||
|             $_SESSION['return'][] = array( | ||||
|               'type' => 'success', | ||||
|               'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), | ||||
|               'msg' => array('mailbox_removed', htmlspecialchars($username)) | ||||
|             ); | ||||
|           } | ||||
|           return true; | ||||
|         break; | ||||
|         case 'mailbox_templates': | ||||
|           if ($_SESSION['mailcow_cc_role'] != "admin") { | ||||
| @@ -5264,7 +5272,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { | ||||
|       } | ||||
|     break; | ||||
|   } | ||||
|   if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'mailbox', 'resource')) && getenv('SKIP_SOGO') != "y") { | ||||
|   if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'resource')) && getenv('SKIP_SOGO') != "y") { | ||||
|     update_sogo_static_view(); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -117,8 +117,8 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>'; | ||||
|             else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -126,8 +126,8 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>'; | ||||
|             else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -260,8 +260,8 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>'; | ||||
|             else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -269,8 +269,8 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>'; | ||||
|             else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -337,7 +337,7 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             return 'yes'==data?'<i class="bi bi-x-lg"><span class="sorting-value">yes</span></i>':'no'==data&&'<i class="bi bi-check-lg"><span class="sorting-value">no</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -414,8 +414,8 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>'; | ||||
|             else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -492,8 +492,8 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>'; | ||||
|             else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|   | ||||
| @@ -607,7 +607,7 @@ jQuery(function($){ | ||||
|           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>':2==data&&'—'); | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'—'); | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -754,7 +754,7 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -762,7 +762,7 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -770,7 +770,7 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -778,7 +778,7 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -787,7 +787,7 @@ jQuery(function($){ | ||||
|           defaultContent: '', | ||||
|           responsivePriority: 4, | ||||
|           render: function (data, type) { | ||||
|             return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>'; | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -1093,7 +1093,7 @@ jQuery(function($){ | ||||
|           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&&'—'); | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'—'); | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -1164,13 +1164,13 @@ jQuery(function($){ | ||||
|  | ||||
|             item.attributes.quota = humanFileSize(item.attributes.quota); | ||||
|  | ||||
|             item.attributes.tls_enforce_in = '<i class="text-' + (item.attributes.tls_enforce_in == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"></i>'; | ||||
|             item.attributes.tls_enforce_out = '<i class="text-' + (item.attributes.tls_enforce_out == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"></i>'; | ||||
|             item.attributes.pop3_access = '<i class="text-' + (item.attributes.pop3_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.pop3_access == 1 ? 'check-lg' : 'x-lg') + '"></i>'; | ||||
|             item.attributes.imap_access = '<i class="text-' + (item.attributes.imap_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.imap_access == 1 ? 'check-lg' : 'x-lg') + '"></i>'; | ||||
|             item.attributes.smtp_access = '<i class="text-' + (item.attributes.smtp_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.smtp_access == 1 ? 'check-lg' : 'x-lg') + '"></i>'; | ||||
|             item.attributes.sieve_access = '<i class="text-' + (item.attributes.sieve_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sieve_access == 1 ? 'check-lg' : 'x-lg') + '"></i>'; | ||||
|             item.attributes.sogo_access = '<i class="text-' + (item.attributes.sogo_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sogo_access == 1 ? 'check-lg' : 'x-lg') + '"></i>'; | ||||
|             item.attributes.tls_enforce_in = '<i class="text-' + (item.attributes.tls_enforce_in == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"><span class="sorting-value">' + (item.attributes.tls_enforce_in == 1 ? '1' : '0') + '</span></i>'; | ||||
|             item.attributes.tls_enforce_out = '<i class="text-' + (item.attributes.tls_enforce_out == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"><span class="sorting-value">' + (item.attributes.tls_enforce_out == 1 ? '1' : '0') + '</span></i>'; | ||||
|             item.attributes.pop3_access = '<i class="text-' + (item.attributes.pop3_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.pop3_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.pop3_access == 1 ? '1' : '0') + '</span></i>'; | ||||
|             item.attributes.imap_access = '<i class="text-' + (item.attributes.imap_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.imap_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.imap_access == 1 ? '1' : '0') + '</span></i>'; | ||||
|             item.attributes.smtp_access = '<i class="text-' + (item.attributes.smtp_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.smtp_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.smtp_access == 1 ? '1' : '0') + '</span></i>'; | ||||
|             item.attributes.sieve_access = '<i class="text-' + (item.attributes.sieve_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sieve_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.sieve_access == 1 ? '1' : '0') + '</span></i>'; | ||||
|             item.attributes.sogo_access = '<i class="text-' + (item.attributes.sogo_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sogo_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.sogo_access == 1 ? '1' : '0') + '</span></i>'; | ||||
|             if (item.attributes.quarantine_notification === 'never') { | ||||
|               item.attributes.quarantine_notification = lang.never; | ||||
|             } else if (item.attributes.quarantine_notification === 'hourly') { | ||||
| @@ -1188,7 +1188,6 @@ 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>' + | ||||
| @@ -1329,7 +1328,7 @@ jQuery(function($){ | ||||
|           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&&'—'); | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'—'); | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -1440,7 +1439,7 @@ jQuery(function($){ | ||||
|           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&&'—'); | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'—'); | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -1578,7 +1577,7 @@ jQuery(function($){ | ||||
|           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&&'—'); | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'—'); | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -1675,7 +1674,7 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -1782,7 +1781,7 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -1917,7 +1916,7 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -1936,7 +1935,7 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -1952,6 +1951,10 @@ jQuery(function($){ | ||||
|     table.on('responsive-resize', function (e, datatable, columns){ | ||||
|       hideTableExpandCollapseBtn('#tab-mbox-aliases', '#alias_table'); | ||||
|     }); | ||||
|      | ||||
|     table.on( 'draw', function (){ | ||||
|         $('#alias_table [data-bs-toggle="tooltip"]').tooltip(); | ||||
|     }); | ||||
|   } | ||||
|   function draw_aliasdomain_table() { | ||||
|     // just recalc width if instance already exists | ||||
| @@ -2031,7 +2034,7 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
| @@ -2167,7 +2170,7 @@ jQuery(function($){ | ||||
|           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>'; | ||||
|             return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>'; | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|   | ||||
| @@ -105,7 +105,8 @@ | ||||
|         "timeout2": "Časový limit pro připojení k lokálnímu serveru", | ||||
|         "username": "Uživatelské jméno", | ||||
|         "validate": "Ověřit", | ||||
|         "validation_success": "Úspěšně ověřeno" | ||||
|         "validation_success": "Úspěšně ověřeno", | ||||
|         "tags": "Štítky" | ||||
|     }, | ||||
|     "admin": { | ||||
|         "access": "Přístupy", | ||||
| @@ -333,7 +334,11 @@ | ||||
|         "username": "Uživatelské jméno", | ||||
|         "validate_license_now": "Ověřit GUID na licenčním serveru", | ||||
|         "verify": "Ověřit", | ||||
|         "yes": "✓" | ||||
|         "yes": "✓", | ||||
|         "f2b_ban_time_increment": "Délka banu je prodlužována s každým dalším banem", | ||||
|         "f2b_max_ban_time": "Maximální délka banu (s)", | ||||
|         "ip_check": "Kontrola IP", | ||||
|         "ip_check_disabled": "Kontrola IP je vypnuta. Můžete ji zapnout v <br> <strong>System > Nastavení > Options > Přizpůsobení</strong>" | ||||
|     }, | ||||
|     "danger": { | ||||
|         "access_denied": "Přístup odepřen nebo jsou neplatná data ve formuláři", | ||||
|   | ||||
| @@ -60,7 +60,7 @@ elseif (isset($_GET['login'])) { | ||||
|           ':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR']) | ||||
|         )); | ||||
|         // redirect to sogo (sogo will get the correct credentials via nginx auth_request | ||||
|         header("Location: /SOGo/so/${login}"); | ||||
|         header("Location: /SOGo/so/{$login}"); | ||||
|         exit; | ||||
|       } | ||||
|     } | ||||
|   | ||||
| @@ -109,25 +109,25 @@ | ||||
|         <label class="control-label col-sm-2">{{ lang.user.quarantine_notification }}</label> | ||||
|         <div class="col-sm-10"> | ||||
|           <div class="btn-group" data-acl="{{ acl.quarantine_notification }}"> | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'never' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'never' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailbox }}" | ||||
|             data-id="quarantine_notification" | ||||
|             data-api-url='edit/quarantine_notification' | ||||
|             data-api-attr='{"quarantine_notification":"never"}'>{{ lang.user.never }}</button> | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'hourly' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'hourly' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailbox }}" | ||||
|             data-id="quarantine_notification" | ||||
|             data-api-url='edit/quarantine_notification' | ||||
|             data-api-attr='{"quarantine_notification":"hourly"}'>{{ lang.user.hourly }}</button> | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'daily' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'daily' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailbox }}" | ||||
|             data-id="quarantine_notification" | ||||
|             data-api-url='edit/quarantine_notification' | ||||
|             data-api-attr='{"quarantine_notification":"daily"}'>{{ lang.user.daily }}</button> | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'weekly' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'weekly' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailbox }}" | ||||
|             data-id="quarantine_notification" | ||||
| @@ -141,19 +141,19 @@ | ||||
|         <label class="control-label col-sm-2">{{ lang.user.quarantine_category }}</label> | ||||
|         <div class="col-sm-10"> | ||||
|           <div class="btn-group" data-acl="{{ acl.quarantine_category }}"> | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'reject' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'reject' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailbox }}" | ||||
|             data-id="quarantine_category" | ||||
|             data-api-url='edit/quarantine_category' | ||||
|             data-api-attr='{"quarantine_category":"reject"}'>{{ lang.user.q_reject }}</button> | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'add_header' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'add_header' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailbox }}" | ||||
|             data-id="quarantine_category" | ||||
|             data-api-url='edit/quarantine_category' | ||||
|             data-api-attr='{"quarantine_category":"add_header"}'>{{ lang.user.q_add_header }}</button> | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'all' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'all' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailbox }}" | ||||
|             data-id="quarantine_category" | ||||
| @@ -167,13 +167,13 @@ | ||||
|         <label class="control-label col-sm-2" for="sender_acl">{{ lang.user.tls_policy }}</label> | ||||
|         <div class="col-sm-10"> | ||||
|           <div class="btn-group" data-acl="{{ acl.tls_policy }}"> | ||||
|             <button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_in == '1' %} active"{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-light{% if get_tls_policy.tls_enforce_in == '1' %} btn-dark"{% endif %}" | ||||
|               data-action="edit_selected" | ||||
|               data-item="{{ mailbox }}" | ||||
|               data-id="tls_policy" | ||||
|               data-api-url='edit/tls_policy' | ||||
|               data-api-attr='{"tls_enforce_in": {% if get_tls_policy.tls_enforce_in == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_in }}</button> | ||||
|             <button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_out == '1' %} active"{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-light{% if get_tls_policy.tls_enforce_out == '1' %} btn-dark"{% endif %}" | ||||
|               data-action="edit_selected" | ||||
|               data-item="{{ mailbox }}" | ||||
|               data-id="tls_policy" | ||||
|   | ||||
| @@ -54,6 +54,7 @@ | ||||
|             <li class="dropdown-header">SMTP</li> | ||||
|             <li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":1}' href="#">{{ lang.mailbox.activate }}</a></li> | ||||
|             <li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li> | ||||
|             <li><hr class="dropdown-divider"></li> | ||||
|             <li class="dropdown-header">Sieve</li> | ||||
|             <li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":1}' href="#">{{ lang.mailbox.activate }}</a></li> | ||||
|             <li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li> | ||||
| @@ -61,7 +62,7 @@ | ||||
|           <a class="btn btn-sm btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addMailboxModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_mailbox }}</a> | ||||
|         </div> | ||||
|         <div class="btn-group d-none d-lg-flex"> | ||||
|           <a class="btn btn-sm btn-secondary" id="toggle_multi_select_all" data-id="mailbox" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>           | ||||
|           <a class="btn btn-sm btn-secondary" id="toggle_multi_select_all" data-id="mailbox" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a> | ||||
|           <a class="btn btn-sm btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a> | ||||
|           <ul class="dropdown-menu"> | ||||
|             <li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="mailbox_table">{{ lang.datatables.expand_all }}</a></li> | ||||
|   | ||||
| @@ -12,19 +12,19 @@ | ||||
|         <div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.tag_handling }}:</div> | ||||
|         <div class="col-sm-9 col-12"> | ||||
|           <div class="btn-group" data-acl="{{ acl.delimiter_action }}"> | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if get_tagging_options == 'subfolder' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if get_tagging_options == 'subfolder' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailcow_cc_username }}" | ||||
|             data-id="delimiter_action" | ||||
|             data-api-url='edit/delimiter_action' | ||||
|             data-api-attr='{"tagged_mail_handler":"subfolder"}'>{{ lang.user.tag_in_subfolder }}</button> | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if get_tagging_options == 'subject' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if get_tagging_options == 'subject' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailcow_cc_username }}" | ||||
|             data-id="delimiter_action" | ||||
|             data-api-url='edit/delimiter_action' | ||||
|             data-api-attr='{"tagged_mail_handler":"subject"}'>{{ lang.user.tag_in_subject }}</button> | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if get_tagging_options == 'none' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if get_tagging_options == 'none' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailcow_cc_username }}" | ||||
|             data-id="delimiter_action" | ||||
| @@ -40,13 +40,13 @@ | ||||
|         <div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.tls_policy }}:</div> | ||||
|         <div class="col-sm-9 col-12"> | ||||
|           <div class="btn-group" data-acl="{{ acl.tls_policy }}"> | ||||
|             <button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_in == '1' %} active"{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-light{% if get_tls_policy.tls_enforce_in == '1' %} btn-dark"{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailcow_cc_username }}" | ||||
|             data-id="tls_policy" | ||||
|             data-api-url='edit/tls_policy' | ||||
|             data-api-attr='{"tls_enforce_in": {% if get_tls_policy.tls_enforce_in == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_in }}</button> | ||||
|             <button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_out == '1' %} active"{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-light{% if get_tls_policy.tls_enforce_out == '1' %} btn-dark"{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailcow_cc_username }}" | ||||
|             data-id="tls_policy" | ||||
| @@ -61,25 +61,25 @@ | ||||
|         <div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.quarantine_notification }}:</div> | ||||
|         <div class="col-sm-9 col-12"> | ||||
|           <div class="btn-group" data-acl="{{ acl.quarantine_notification }}"> | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'never' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'never' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailcow_cc_username }}" | ||||
|             data-id="quarantine_notification" | ||||
|             data-api-url='edit/quarantine_notification' | ||||
|             data-api-attr='{"quarantine_notification":"never"}'>{{ lang.user.never }}</button> | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'hourly' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'hourly' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailcow_cc_username }}" | ||||
|             data-id="quarantine_notification" | ||||
|             data-api-url='edit/quarantine_notification' | ||||
|             data-api-attr='{"quarantine_notification":"hourly"}'>{{ lang.user.hourly }}</button> | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'daily' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'daily' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailcow_cc_username }}" | ||||
|             data-id="quarantine_notification" | ||||
|             data-api-url='edit/quarantine_notification' | ||||
|             data-api-attr='{"quarantine_notification":"daily"}'>{{ lang.user.daily }}</button> | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'weekly' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'weekly' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailcow_cc_username }}" | ||||
|             data-id="quarantine_notification" | ||||
| @@ -93,19 +93,19 @@ | ||||
|         <div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.quarantine_category }}:</div> | ||||
|         <div class="col-sm-9 col-12"> | ||||
|           <div class="btn-group" data-acl="{{ acl.quarantine_category }}"> | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'reject' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'reject' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailcow_cc_username }}" | ||||
|             data-id="quarantine_category" | ||||
|             data-api-url='edit/quarantine_category' | ||||
|             data-api-attr='{"quarantine_category":"reject"}'>{{ lang.user.q_reject }}</button> | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'add_header' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'add_header' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailcow_cc_username }}" | ||||
|             data-id="quarantine_category" | ||||
|             data-api-url='edit/quarantine_category' | ||||
|             data-api-attr='{"quarantine_category":"add_header"}'>{{ lang.user.q_add_header }}</button> | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'all' %} active{% endif %}" | ||||
|             <button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'all' %} btn-dark{% endif %}" | ||||
|             data-action="edit_selected" | ||||
|             data-item="{{ mailcow_cc_username }}" | ||||
|             data-id="quarantine_category" | ||||
|   | ||||
| @@ -76,7 +76,7 @@ services: | ||||
|             - clamd | ||||
|  | ||||
|     rspamd-mailcow: | ||||
|       image: mailcow/rspamd:1.93 | ||||
|       image: mailcow/rspamd:1.92 | ||||
|       stop_grace_period: 30s | ||||
|       depends_on: | ||||
|         - dovecot-mailcow | ||||
| @@ -169,7 +169,7 @@ services: | ||||
|             - phpfpm | ||||
|  | ||||
|     sogo-mailcow: | ||||
|       image: mailcow/sogo:1.116 | ||||
|       image: mailcow/sogo:1.117 | ||||
|       environment: | ||||
|         - DBNAME=${DBNAME} | ||||
|         - DBUSER=${DBUSER} | ||||
| @@ -510,7 +510,7 @@ services: | ||||
|             - watchdog | ||||
|  | ||||
|     dockerapi-mailcow: | ||||
|       image: mailcow/dockerapi:2.02 | ||||
|       image: mailcow/dockerapi:2.03 | ||||
|       security_opt: | ||||
|         - label=disable | ||||
|       restart: always | ||||
|   | ||||
| @@ -261,7 +261,7 @@ COMPOSE_PROJECT_NAME=mailcowdockerized | ||||
| # Switch here between native (compose plugin) and standalone | ||||
| # For more informations take a look at the mailcow docs regarding the configuration options. | ||||
| # Normally this should be untouched but if you decided to use either of those you can switch it manually here. | ||||
| # Please be aware that at least one of those variants should be installed on your maschine or mailcow will fail. | ||||
| # Please be aware that at least one of those variants should be installed on your machine or mailcow will fail. | ||||
|  | ||||
| DOCKER_COMPOSE_VERSION=${COMPOSE_VERSION} | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| #!/usr/bin/env bash | ||||
| # renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?<version>.*)$ | ||||
| NEXTCLOUD_VERSION=26.0.0 | ||||
| NEXTCLOUD_VERSION=26.0.1 | ||||
|  | ||||
| echo -ne "Checking prerequisites..." | ||||
| sleep 1 | ||||
| @@ -97,8 +97,8 @@ elif [[ ${NC_UPDATE} == "y" ]]; then | ||||
|     echo -e "\033[31mError: Nextcloud occ not found. Is Nextcloud installed?\033[0m" | ||||
|     exit 1 | ||||
|   fi | ||||
|   if grep -q 'This version of Nextcloud is not compatible with PHP>=8.2.' <<<$(docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "/web/nextcloud/occ --no-warnings status"); then | ||||
|     echo -e "\033[31mError: This version of Nextcloud is not compatible with PHP>=8.2, we'll fix it\033[0m" | ||||
|   if grep -Pq 'This version of Nextcloud is not compatible with (?:PHP)?(?>=?)(?:PHP)?(?>.+)' <<<$(docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "/web/nextcloud/occ --no-warnings status"); then | ||||
|     echo -e "\033[31mError: This version of Nextcloud is not compatible with the current PHP version of php-fpm-mailcow, we'll fix it\033[0m" | ||||
|     wget -q https://raw.githubusercontent.com/nextcloud/server/v26.0.0/lib/versioncheck.php -O ./data/web/nextcloud/lib/versioncheck.php | ||||
| 	echo -e "\e[33mPlease restart the update again.\e[0m" | ||||
|   elif ! grep -q 'installed: true' <<<$(docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "/web/nextcloud/occ --no-warnings status"); then | ||||
|   | ||||
		Reference in New Issue
	
	Block a user