Compare commits
6 Commits
feat/backu
...
feat/f2b-b
Author | SHA1 | Date | |
---|---|---|---|
|
db2759b7d1 | ||
|
3c3b9575a2 | ||
|
987cfd5dae | ||
|
1537fb39c0 | ||
|
65cbc478b8 | ||
|
e2e8fbe313 |
1
.github/workflows/rebuild_backup_image.yml
vendored
1
.github/workflows/rebuild_backup_image.yml
vendored
@@ -29,7 +29,6 @@ jobs:
|
|||||||
uses: docker/build-push-action@v4
|
uses: docker/build-push-action@v4
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
file: data/Dockerfiles/backup/Dockerfile
|
file: data/Dockerfiles/backup/Dockerfile
|
||||||
push: true
|
push: true
|
||||||
tags: mailcow/backup:latest
|
tags: mailcow/backup:latest
|
||||||
|
@@ -16,6 +16,7 @@ import json
|
|||||||
import iptc
|
import iptc
|
||||||
import dns.resolver
|
import dns.resolver
|
||||||
import dns.exception
|
import dns.exception
|
||||||
|
import uuid
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
@@ -94,6 +95,8 @@ def verifyF2boptions(f2boptions):
|
|||||||
verifyF2boption(f2boptions,'retry_window', 600)
|
verifyF2boption(f2boptions,'retry_window', 600)
|
||||||
verifyF2boption(f2boptions,'netban_ipv4', 32)
|
verifyF2boption(f2boptions,'netban_ipv4', 32)
|
||||||
verifyF2boption(f2boptions,'netban_ipv6', 128)
|
verifyF2boption(f2boptions,'netban_ipv6', 128)
|
||||||
|
verifyF2boption(f2boptions,'banlist_id', str(uuid.uuid4()))
|
||||||
|
verifyF2boption(f2boptions,'manage_external', 0)
|
||||||
|
|
||||||
def verifyF2boption(f2boptions, f2boption, f2bdefault):
|
def verifyF2boption(f2boptions, f2boption, f2bdefault):
|
||||||
f2boptions[f2boption] = f2boptions[f2boption] if f2boption in f2boptions and f2boptions[f2boption] is not None else f2bdefault
|
f2boptions[f2boption] = f2boptions[f2boption] if f2boption in f2boptions and f2boptions[f2boption] is not None else f2bdefault
|
||||||
@@ -156,6 +159,7 @@ def mailcowChainOrder():
|
|||||||
exit_code = 2
|
exit_code = 2
|
||||||
|
|
||||||
def ban(address):
|
def ban(address):
|
||||||
|
global f2boptions
|
||||||
global lock
|
global lock
|
||||||
refreshF2boptions()
|
refreshF2boptions()
|
||||||
BAN_TIME = int(f2boptions['ban_time'])
|
BAN_TIME = int(f2boptions['ban_time'])
|
||||||
@@ -197,7 +201,7 @@ def ban(address):
|
|||||||
cur_time = int(round(time.time()))
|
cur_time = int(round(time.time()))
|
||||||
NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter']
|
NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter']
|
||||||
logCrit('Banning %s for %d minutes' % (net, NET_BAN_TIME / 60 ))
|
logCrit('Banning %s for %d minutes' % (net, NET_BAN_TIME / 60 ))
|
||||||
if type(ip) is ipaddress.IPv4Address:
|
if type(ip) is ipaddress.IPv4Address and int(f2boptions['manage_external']) != 1:
|
||||||
with lock:
|
with lock:
|
||||||
chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), 'MAILCOW')
|
chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), 'MAILCOW')
|
||||||
rule = iptc.Rule()
|
rule = iptc.Rule()
|
||||||
@@ -206,7 +210,7 @@ def ban(address):
|
|||||||
rule.target = target
|
rule.target = target
|
||||||
if rule not in chain.rules:
|
if rule not in chain.rules:
|
||||||
chain.insert_rule(rule)
|
chain.insert_rule(rule)
|
||||||
else:
|
elif int(f2boptions['manage_external']) != 1:
|
||||||
with lock:
|
with lock:
|
||||||
chain = iptc.Chain(iptc.Table6(iptc.Table6.FILTER), 'MAILCOW')
|
chain = iptc.Chain(iptc.Table6(iptc.Table6.FILTER), 'MAILCOW')
|
||||||
rule = iptc.Rule6()
|
rule = iptc.Rule6()
|
||||||
@@ -251,6 +255,7 @@ def unban(net):
|
|||||||
bans[net]['ban_counter'] += 1
|
bans[net]['ban_counter'] += 1
|
||||||
|
|
||||||
def permBan(net, unban=False):
|
def permBan(net, unban=False):
|
||||||
|
global f2boptions
|
||||||
global lock
|
global lock
|
||||||
if type(ipaddress.ip_network(net, strict=False)) is ipaddress.IPv4Network:
|
if type(ipaddress.ip_network(net, strict=False)) is ipaddress.IPv4Network:
|
||||||
with lock:
|
with lock:
|
||||||
@@ -259,7 +264,7 @@ def permBan(net, unban=False):
|
|||||||
rule.src = net
|
rule.src = net
|
||||||
target = iptc.Target(rule, "REJECT")
|
target = iptc.Target(rule, "REJECT")
|
||||||
rule.target = target
|
rule.target = target
|
||||||
if rule not in chain.rules and not unban:
|
if rule not in chain.rules and not unban and int(f2boptions['manage_external']) != 1:
|
||||||
logCrit('Add host/network %s to blacklist' % net)
|
logCrit('Add host/network %s to blacklist' % net)
|
||||||
chain.insert_rule(rule)
|
chain.insert_rule(rule)
|
||||||
r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time())))
|
r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time())))
|
||||||
@@ -274,7 +279,7 @@ def permBan(net, unban=False):
|
|||||||
rule.src = net
|
rule.src = net
|
||||||
target = iptc.Target(rule, "REJECT")
|
target = iptc.Target(rule, "REJECT")
|
||||||
rule.target = target
|
rule.target = target
|
||||||
if rule not in chain.rules and not unban:
|
if rule not in chain.rules and not unban and int(f2boptions['manage_external']) != 1:
|
||||||
logCrit('Add host/network %s to blacklist' % net)
|
logCrit('Add host/network %s to blacklist' % net)
|
||||||
chain.insert_rule(rule)
|
chain.insert_rule(rule)
|
||||||
r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time())))
|
r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time())))
|
||||||
@@ -553,7 +558,7 @@ def initChain():
|
|||||||
chain.insert_rule(rule)
|
chain.insert_rule(rule)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
refreshF2boptions()
|
||||||
# In case a previous session was killed without cleanup
|
# In case a previous session was killed without cleanup
|
||||||
clear()
|
clear()
|
||||||
# Reinit MAILCOW chain
|
# Reinit MAILCOW chain
|
||||||
|
@@ -68,39 +68,3 @@ WL_FWD_HOST {
|
|||||||
ENCRYPTED_CHAT {
|
ENCRYPTED_CHAT {
|
||||||
expression = "CHAT_VERSION_HEADER & ENCRYPTED_PGP";
|
expression = "CHAT_VERSION_HEADER & ENCRYPTED_PGP";
|
||||||
}
|
}
|
||||||
|
|
||||||
CLAMD_SPAM_FOUND {
|
|
||||||
expression = "CLAM_SECI_SPAM & !MAILCOW_WHITE";
|
|
||||||
description = "Probably Spam, Securite Spam Flag set through ClamAV";
|
|
||||||
score = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLAMD_BAD_PDF {
|
|
||||||
expression = "CLAM_SECI_PDF & !MAILCOW_WHITE";
|
|
||||||
description = "Bad PDF Found, Securite bad PDF Flag set through ClamAV";
|
|
||||||
score = 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLAMD_BAD_JPG {
|
|
||||||
expression = "CLAM_SECI_JPG & !MAILCOW_WHITE";
|
|
||||||
description = "Bad JPG Found, Securite bad JPG Flag set through ClamAV";
|
|
||||||
score = 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLAMD_ASCII_MALWARE {
|
|
||||||
expression = "CLAM_SECI_ASCII & !MAILCOW_WHITE";
|
|
||||||
description = "ASCII malware found, Securite ASCII malware Flag set through ClamAV";
|
|
||||||
score = 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLAMD_HTML_MALWARE {
|
|
||||||
expression = "CLAM_SECI_HTML & !MAILCOW_WHITE";
|
|
||||||
description = "HTML malware found, Securite HTML malware Flag set through ClamAV";
|
|
||||||
score = 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLAMD_JS_MALWARE {
|
|
||||||
expression = "CLAM_SECI_JS & !MAILCOW_WHITE";
|
|
||||||
description = "JS malware found, Securite JS malware Flag set through ClamAV";
|
|
||||||
score = 8;
|
|
||||||
}
|
|
@@ -85,6 +85,8 @@ $cors_settings = cors('get');
|
|||||||
$cors_settings['allowed_origins'] = str_replace(", ", "\n", $cors_settings['allowed_origins']);
|
$cors_settings['allowed_origins'] = str_replace(", ", "\n", $cors_settings['allowed_origins']);
|
||||||
$cors_settings['allowed_methods'] = explode(", ", $cors_settings['allowed_methods']);
|
$cors_settings['allowed_methods'] = explode(", ", $cors_settings['allowed_methods']);
|
||||||
|
|
||||||
|
$f2b_data = fail2ban('get');
|
||||||
|
|
||||||
$template = 'admin.twig';
|
$template = 'admin.twig';
|
||||||
$template_data = [
|
$template_data = [
|
||||||
'tfa_data' => $tfa_data,
|
'tfa_data' => $tfa_data,
|
||||||
@@ -101,7 +103,8 @@ $template_data = [
|
|||||||
'domains' => $domains,
|
'domains' => $domains,
|
||||||
'all_domains' => $all_domains,
|
'all_domains' => $all_domains,
|
||||||
'mailboxes' => $mailboxes,
|
'mailboxes' => $mailboxes,
|
||||||
'f2b_data' => fail2ban('get'),
|
'f2b_data' => $f2b_data,
|
||||||
|
'f2b_banlist_url' => getBaseUrl() . "/api/v1/get/fail2ban/banlist/" . $f2b_data['banlist_id'],
|
||||||
'q_data' => quarantine('settings'),
|
'q_data' => quarantine('settings'),
|
||||||
'qn_data' => quota_notification('get'),
|
'qn_data' => quota_notification('get'),
|
||||||
'rsettings_map' => file_get_contents('http://nginx:8081/settings.php'),
|
'rsettings_map' => file_get_contents('http://nginx:8081/settings.php'),
|
||||||
@@ -112,6 +115,7 @@ $template_data = [
|
|||||||
'password_complexity' => password_complexity('get'),
|
'password_complexity' => password_complexity('get'),
|
||||||
'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'],
|
'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'],
|
||||||
'cors_settings' => $cors_settings,
|
'cors_settings' => $cors_settings,
|
||||||
|
'is_https' => isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on',
|
||||||
'lang_admin' => json_encode($lang['admin']),
|
'lang_admin' => json_encode($lang['admin']),
|
||||||
'lang_datatables' => json_encode($lang['datatables'])
|
'lang_datatables' => json_encode($lang['datatables'])
|
||||||
];
|
];
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
function fail2ban($_action, $_data = null) {
|
function fail2ban($_action, $_data = null, $_extra = null) {
|
||||||
global $redis;
|
global $redis;
|
||||||
$_data_log = $_data;
|
$_data_log = $_data;
|
||||||
switch ($_action) {
|
switch ($_action) {
|
||||||
@@ -247,6 +247,7 @@ function fail2ban($_action, $_data = null) {
|
|||||||
$netban_ipv6 = intval((isset($_data['netban_ipv6'])) ? $_data['netban_ipv6'] : $is_now['netban_ipv6']);
|
$netban_ipv6 = intval((isset($_data['netban_ipv6'])) ? $_data['netban_ipv6'] : $is_now['netban_ipv6']);
|
||||||
$wl = (isset($_data['whitelist'])) ? $_data['whitelist'] : $is_now['whitelist'];
|
$wl = (isset($_data['whitelist'])) ? $_data['whitelist'] : $is_now['whitelist'];
|
||||||
$bl = (isset($_data['blacklist'])) ? $_data['blacklist'] : $is_now['blacklist'];
|
$bl = (isset($_data['blacklist'])) ? $_data['blacklist'] : $is_now['blacklist'];
|
||||||
|
$manage_external = (isset($_data['manage_external'])) ? intval($_data['manage_external']) : 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
@@ -266,6 +267,8 @@ function fail2ban($_action, $_data = null) {
|
|||||||
$f2b_options['netban_ipv6'] = ($netban_ipv6 > 128) ? 128 : $netban_ipv6;
|
$f2b_options['netban_ipv6'] = ($netban_ipv6 > 128) ? 128 : $netban_ipv6;
|
||||||
$f2b_options['max_attempts'] = ($max_attempts < 1) ? 1 : $max_attempts;
|
$f2b_options['max_attempts'] = ($max_attempts < 1) ? 1 : $max_attempts;
|
||||||
$f2b_options['retry_window'] = ($retry_window < 1) ? 1 : $retry_window;
|
$f2b_options['retry_window'] = ($retry_window < 1) ? 1 : $retry_window;
|
||||||
|
$f2b_options['banlist_id'] = $is_now['banlist_id'];
|
||||||
|
$f2b_options['manage_external'] = ($manage_external > 0) ? 1 : 0;
|
||||||
try {
|
try {
|
||||||
$redis->Set('F2B_OPTIONS', json_encode($f2b_options));
|
$redis->Set('F2B_OPTIONS', json_encode($f2b_options));
|
||||||
$redis->Del('F2B_WHITELIST');
|
$redis->Del('F2B_WHITELIST');
|
||||||
@@ -329,5 +332,71 @@ function fail2ban($_action, $_data = null) {
|
|||||||
'msg' => 'f2b_modified'
|
'msg' => 'f2b_modified'
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case 'banlist':
|
||||||
|
try {
|
||||||
|
$f2b_options = json_decode($redis->Get('F2B_OPTIONS'), true);
|
||||||
|
}
|
||||||
|
catch (RedisException $e) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log, $_extra),
|
||||||
|
'msg' => array('redis_error', $e)
|
||||||
|
);
|
||||||
|
http_response_code(500);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (is_array($_extra)) {
|
||||||
|
$_extra = $_extra[0];
|
||||||
|
}
|
||||||
|
if ($_extra != $f2b_options['banlist_id']){
|
||||||
|
http_response_code(404);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($_data) {
|
||||||
|
case 'get':
|
||||||
|
try {
|
||||||
|
$bl = $redis->hKeys('F2B_BLACKLIST');
|
||||||
|
$active_bans = $redis->hKeys('F2B_ACTIVE_BANS');
|
||||||
|
}
|
||||||
|
catch (RedisException $e) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log, $_extra),
|
||||||
|
'msg' => array('redis_error', $e)
|
||||||
|
);
|
||||||
|
http_response_code(500);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$banlist = implode("\n", array_merge($bl, $active_bans));
|
||||||
|
return $banlist;
|
||||||
|
break;
|
||||||
|
case 'refresh':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$f2b_options['banlist_id'] = uuid4();
|
||||||
|
try {
|
||||||
|
$redis->Set('F2B_OPTIONS', json_encode($f2b_options));
|
||||||
|
}
|
||||||
|
catch (RedisException $e) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log, $_extra),
|
||||||
|
'msg' => array('redis_error', $e)
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log, $_extra),
|
||||||
|
'msg' => 'f2b_banlist_refreshed'
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2246,6 +2246,21 @@ function cors($action, $data = null) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function getBaseURL() {
|
||||||
|
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
|
||||||
|
$host = $_SERVER['HTTP_HOST'];
|
||||||
|
$base_url = $protocol . '://' . $host;
|
||||||
|
|
||||||
|
return $base_url;
|
||||||
|
}
|
||||||
|
function uuid4() {
|
||||||
|
$data = openssl_random_pseudo_bytes(16);
|
||||||
|
|
||||||
|
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
|
||||||
|
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
|
||||||
|
|
||||||
|
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
|
||||||
|
}
|
||||||
|
|
||||||
function get_logs($application, $lines = false) {
|
function get_logs($application, $lines = false) {
|
||||||
if ($lines === false) {
|
if ($lines === false) {
|
||||||
|
@@ -70,6 +70,8 @@ try {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception $e) {
|
catch (Exception $e) {
|
||||||
|
// Stop when redis is not available
|
||||||
|
http_response_code(500);
|
||||||
?>
|
?>
|
||||||
<center style='font-family:sans-serif;'>Connection to Redis failed.<br /><br />The following error was reported:<br/><?=$e->getMessage();?></center>
|
<center style='font-family:sans-serif;'>Connection to Redis failed.<br /><br />The following error was reported:<br/><?=$e->getMessage();?></center>
|
||||||
<?php
|
<?php
|
||||||
@@ -98,6 +100,7 @@ try {
|
|||||||
}
|
}
|
||||||
catch (PDOException $e) {
|
catch (PDOException $e) {
|
||||||
// Stop when SQL connection fails
|
// Stop when SQL connection fails
|
||||||
|
http_response_code(500);
|
||||||
?>
|
?>
|
||||||
<center style='font-family:sans-serif;'>Connection to database failed.<br /><br />The following error was reported:<br/> <?=$e->getMessage();?></center>
|
<center style='font-family:sans-serif;'>Connection to database failed.<br /><br />The following error was reported:<br/> <?=$e->getMessage();?></center>
|
||||||
<?php
|
<?php
|
||||||
@@ -105,6 +108,7 @@ exit;
|
|||||||
}
|
}
|
||||||
// Stop when dockerapi is not available
|
// Stop when dockerapi is not available
|
||||||
if (fsockopen("tcp://dockerapi", 443, $errno, $errstr) === false) {
|
if (fsockopen("tcp://dockerapi", 443, $errno, $errstr) === false) {
|
||||||
|
http_response_code(500);
|
||||||
?>
|
?>
|
||||||
<center style='font-family:sans-serif;'>Connection to dockerapi container failed.<br /><br />The following error was reported:<br/><?=$errno;?> - <?=$errstr;?></center>
|
<center style='font-family:sans-serif;'>Connection to dockerapi container failed.<br /><br />The following error was reported:<br/><?=$errno;?> - <?=$errstr;?></center>
|
||||||
<?php
|
<?php
|
||||||
|
@@ -371,3 +371,11 @@ function addTag(tagAddElem, tag = null){
|
|||||||
$(tagValuesElem).val(JSON.stringify(value_tags));
|
$(tagValuesElem).val(JSON.stringify(value_tags));
|
||||||
$(tagInputElem).val('');
|
$(tagInputElem).val('');
|
||||||
}
|
}
|
||||||
|
function copyToClipboard(id) {
|
||||||
|
var copyText = document.getElementById(id);
|
||||||
|
copyText.select();
|
||||||
|
copyText.setSelectionRange(0, 99999);
|
||||||
|
// only works with https connections
|
||||||
|
navigator.clipboard.writeText(copyText.value);
|
||||||
|
mailcow_alert_box(lang.copy_to_clipboard, "success");
|
||||||
|
}
|
@@ -503,6 +503,16 @@ if (isset($_GET['query'])) {
|
|||||||
print(json_encode($getArgs));
|
print(json_encode($getArgs));
|
||||||
$_SESSION['challenge'] = $WebAuthn->getChallenge();
|
$_SESSION['challenge'] = $WebAuthn->getChallenge();
|
||||||
return;
|
return;
|
||||||
|
break;
|
||||||
|
case "fail2ban":
|
||||||
|
if (!isset($_SESSION['mailcow_cc_role'])){
|
||||||
|
switch ($object) {
|
||||||
|
case 'banlist':
|
||||||
|
header('Content-Type: text/plain');
|
||||||
|
echo fail2ban('banlist', 'get', $extra);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isset($_SESSION['mailcow_cc_role'])) {
|
if (isset($_SESSION['mailcow_cc_role'])) {
|
||||||
@@ -1324,6 +1334,10 @@ if (isset($_GET['query'])) {
|
|||||||
break;
|
break;
|
||||||
case "fail2ban":
|
case "fail2ban":
|
||||||
switch ($object) {
|
switch ($object) {
|
||||||
|
case 'banlist':
|
||||||
|
header('Content-Type: text/plain');
|
||||||
|
echo fail2ban('banlist', 'get', $extra);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
$data = fail2ban('get');
|
$data = fail2ban('get');
|
||||||
process_get_return($data);
|
process_get_return($data);
|
||||||
@@ -1930,7 +1944,14 @@ if (isset($_GET['query'])) {
|
|||||||
process_edit_return(fwdhost('edit', array_merge(array('fwdhost' => $items), $attr)));
|
process_edit_return(fwdhost('edit', array_merge(array('fwdhost' => $items), $attr)));
|
||||||
break;
|
break;
|
||||||
case "fail2ban":
|
case "fail2ban":
|
||||||
process_edit_return(fail2ban('edit', array_merge(array('network' => $items), $attr)));
|
switch ($object) {
|
||||||
|
case 'banlist':
|
||||||
|
process_edit_return(fail2ban('banlist', 'refresh', $items));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
process_edit_return(fail2ban('edit', array_merge(array('network' => $items), $attr)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "ui_texts":
|
case "ui_texts":
|
||||||
process_edit_return(customize('edit', 'ui_texts', $attr));
|
process_edit_return(customize('edit', 'ui_texts', $attr));
|
||||||
|
@@ -147,6 +147,7 @@
|
|||||||
"change_logo": "Logo ändern",
|
"change_logo": "Logo ändern",
|
||||||
"configuration": "Konfiguration",
|
"configuration": "Konfiguration",
|
||||||
"convert_html_to_text": "Konvertiere HTML zu reinem Text",
|
"convert_html_to_text": "Konvertiere HTML zu reinem Text",
|
||||||
|
"copy_to_clipboard": "Text wurde in die Zwischenablage kopiert!",
|
||||||
"cors_settings": "CORS Einstellungen",
|
"cors_settings": "CORS Einstellungen",
|
||||||
"credentials_transport_warning": "<b>Warnung</b>: Das Hinzufügen einer neuen Regel bewirkt die Aktualisierung der Authentifizierungsdaten aller vorhandenen Einträge mit identischem Next Hop.",
|
"credentials_transport_warning": "<b>Warnung</b>: Das Hinzufügen einer neuen Regel bewirkt die Aktualisierung der Authentifizierungsdaten aller vorhandenen Einträge mit identischem Next Hop.",
|
||||||
"customer_id": "Kunde",
|
"customer_id": "Kunde",
|
||||||
@@ -180,6 +181,8 @@
|
|||||||
"f2b_blacklist": "Blacklist für Netzwerke und Hosts",
|
"f2b_blacklist": "Blacklist für Netzwerke und Hosts",
|
||||||
"f2b_filter": "Regex-Filter",
|
"f2b_filter": "Regex-Filter",
|
||||||
"f2b_list_info": "Ein Host oder Netzwerk auf der Blacklist wird immer eine Whitelist-Einheit überwiegen. <b>Die Aktualisierung der Liste dauert einige Sekunden.</b>",
|
"f2b_list_info": "Ein Host oder Netzwerk auf der Blacklist wird immer eine Whitelist-Einheit überwiegen. <b>Die Aktualisierung der Liste dauert einige Sekunden.</b>",
|
||||||
|
"f2b_manage_external": "Fail2Ban extern verwalten",
|
||||||
|
"f2b_manage_external_info": "Fail2ban wird die Banlist weiterhin pflegen, jedoch werden keine aktiven Regeln zum blockieren gesetzt. Die unten generierte Banlist, kann verwendet werden, um den Datenverkehr extern zu blockieren.",
|
||||||
"f2b_max_attempts": "Max. Versuche",
|
"f2b_max_attempts": "Max. Versuche",
|
||||||
"f2b_max_ban_time": "Maximale Bannzeit in Sekunden",
|
"f2b_max_ban_time": "Maximale Bannzeit in Sekunden",
|
||||||
"f2b_netban_ipv4": "Netzbereich für IPv4-Banns (8-32)",
|
"f2b_netban_ipv4": "Netzbereich für IPv4-Banns (8-32)",
|
||||||
@@ -1019,6 +1022,7 @@
|
|||||||
"domain_removed": "Domain %s wurde entfernt",
|
"domain_removed": "Domain %s wurde entfernt",
|
||||||
"dovecot_restart_success": "Dovecot wurde erfolgreich neu gestartet",
|
"dovecot_restart_success": "Dovecot wurde erfolgreich neu gestartet",
|
||||||
"eas_reset": "ActiveSync Gerät des Benutzers %s wurde zurückgesetzt",
|
"eas_reset": "ActiveSync Gerät des Benutzers %s wurde zurückgesetzt",
|
||||||
|
"f2b_banlist_refreshed": "Banlist ID wurde erfolgreich erneuert.",
|
||||||
"f2b_modified": "Änderungen an Fail2ban-Parametern wurden gespeichert",
|
"f2b_modified": "Änderungen an Fail2ban-Parametern wurden gespeichert",
|
||||||
"forwarding_host_added": "Weiterleitungs-Host %s wurde hinzugefügt",
|
"forwarding_host_added": "Weiterleitungs-Host %s wurde hinzugefügt",
|
||||||
"forwarding_host_removed": "Weiterleitungs-Host %s wurde entfernt",
|
"forwarding_host_removed": "Weiterleitungs-Host %s wurde entfernt",
|
||||||
|
@@ -151,6 +151,7 @@
|
|||||||
"change_logo": "Change logo",
|
"change_logo": "Change logo",
|
||||||
"configuration": "Configuration",
|
"configuration": "Configuration",
|
||||||
"convert_html_to_text": "Convert HTML to plain text",
|
"convert_html_to_text": "Convert HTML to plain text",
|
||||||
|
"copy_to_clipboard": "Text copied to clipboard!",
|
||||||
"cors_settings": "CORS Settings",
|
"cors_settings": "CORS Settings",
|
||||||
"credentials_transport_warning": "<b>Warning</b>: Adding a new transport map entry will update the credentials for all entries with a matching next hop column.",
|
"credentials_transport_warning": "<b>Warning</b>: Adding a new transport map entry will update the credentials for all entries with a matching next hop column.",
|
||||||
"customer_id": "Customer ID",
|
"customer_id": "Customer ID",
|
||||||
@@ -184,6 +185,8 @@
|
|||||||
"f2b_blacklist": "Blacklisted networks/hosts",
|
"f2b_blacklist": "Blacklisted networks/hosts",
|
||||||
"f2b_filter": "Regex filters",
|
"f2b_filter": "Regex filters",
|
||||||
"f2b_list_info": "A blacklisted host or network will always outweigh a whitelist entity. <b>List updates will take a few seconds to be applied.</b>",
|
"f2b_list_info": "A blacklisted host or network will always outweigh a whitelist entity. <b>List updates will take a few seconds to be applied.</b>",
|
||||||
|
"f2b_manage_external": "Manage Fail2Ban externally",
|
||||||
|
"f2b_manage_external_info": "Fail2ban will still maintain the banlist, but it will not actively set rules to block traffic. Use the generated banlist below to externally block the traffic.",
|
||||||
"f2b_max_attempts": "Max. attempts",
|
"f2b_max_attempts": "Max. attempts",
|
||||||
"f2b_max_ban_time": "Max. ban time (s)",
|
"f2b_max_ban_time": "Max. ban time (s)",
|
||||||
"f2b_netban_ipv4": "IPv4 subnet size to apply ban on (8-32)",
|
"f2b_netban_ipv4": "IPv4 subnet size to apply ban on (8-32)",
|
||||||
@@ -1028,6 +1031,7 @@
|
|||||||
"domain_removed": "Domain %s has been removed",
|
"domain_removed": "Domain %s has been removed",
|
||||||
"dovecot_restart_success": "Dovecot was restarted successfully",
|
"dovecot_restart_success": "Dovecot was restarted successfully",
|
||||||
"eas_reset": "ActiveSync devices for user %s were reset",
|
"eas_reset": "ActiveSync devices for user %s were reset",
|
||||||
|
"f2b_banlist_refreshed": "Banlist ID has been successfully refreshed.",
|
||||||
"f2b_modified": "Changes to Fail2ban parameters have been saved",
|
"f2b_modified": "Changes to Fail2ban parameters have been saved",
|
||||||
"forwarding_host_added": "Forwarding host %s has been added",
|
"forwarding_host_added": "Forwarding host %s has been added",
|
||||||
"forwarding_host_removed": "Forwarding host %s has been removed",
|
"forwarding_host_removed": "Forwarding host %s has been removed",
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div class="tab-pane fade show active" id="tab-config-admins" role="tabpanel" aria-labelledby="tab-config-admins">
|
<div role="tabpanel" class="tab-pane fade show active" id="tab-config-admins" role="tabpanel" aria-labelledby="tab-config-admins">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header bg-danger text-white d-flex fs-5">
|
<div class="card-header bg-danger text-white d-flex fs-5">
|
||||||
<button class="btn d-md-none text-white flex-grow-1 text-start" data-bs-target="#collapse-tab-config-admins" data-bs-toggle="collapse" aria-controls="collapse-tab-config-admins">
|
<button class="btn d-md-none text-white flex-grow-1 text-start" data-bs-target="#collapse-tab-config-admins" data-bs-toggle="collapse" aria-controls="collapse-tab-config-admins">
|
||||||
@@ -227,7 +227,7 @@
|
|||||||
|
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-dadmins" data-bs-toggle="collapse" aria-controls="collapse-tab-config-dadmins">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-dadmins" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-dadmins">
|
||||||
{{ lang.admin.domain_admins }}
|
{{ lang.admin.domain_admins }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.domain_admins }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.domain_admins }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane fade" id="tab-config-customize" role="tabpanel" aria-labelledby="tab-config-customize">
|
<div role="tabpanel" class="tab-pane fade" id="tab-config-customize" role="tabpanel" aria-labelledby="tab-config-customize">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-customize" data-bs-toggle="collapse" aria-controls="collapse-tab-config-customize">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-customize" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-customize">
|
||||||
{{ lang.admin.customize }}
|
{{ lang.admin.customize }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.customize }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.customize }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane fade" id="tab-config-dkim" role="tabpanel" aria-labelledby="tab-config-dkim">
|
<div role="tabpanel" class="tab-pane fade" id="tab-config-dkim" role="tabpanel" aria-labelledby="tab-config-dkim">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-dkim" data-bs-toggle="collapse" aria-controls="collapse-tab-config-dkim">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-dkim" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-dkim">
|
||||||
{{ lang.admin.dkim_keys }}
|
{{ lang.admin.dkim_keys }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.dkim_keys }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.dkim_keys }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane fade" id="tab-config-f2b" role="tabpanel" aria-labelledby="tab-config-f2b">
|
<div role="tabpanel" class="tab-pane fade" id="tab-config-f2b" role="tabpanel" aria-labelledby="tab-config-f2b">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-f2b" data-bs-toggle="collapse" aria-controls="collapse-tab-config-f2b">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-f2b" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-f2b">
|
||||||
{{ lang.admin.f2b_parameters }}
|
{{ lang.admin.f2b_parameters }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.f2b_parameters }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.f2b_parameters }}</span>
|
||||||
@@ -42,6 +42,13 @@
|
|||||||
<input type="number" class="form-control" id="f2b_netban_ipv6" name="netban_ipv6" value="{{ f2b_data.netban_ipv6 }}" required>
|
<input type="number" class="form-control" id="f2b_netban_ipv6" name="netban_ipv6" value="{{ f2b_data.netban_ipv6 }}" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mb-4">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" id="f2b_manage_external" value="1" name="manage_external" {% if f2b_data.manage_external == 1 %}checked{% endif %}>
|
||||||
|
<label class="form-check-label" for="f2b_manage_external">{{ lang.admin.f2b_manage_external }}</label>
|
||||||
|
</div>
|
||||||
|
<p class="text-muted">{{ lang.admin.f2b_manage_external_info }}</p>
|
||||||
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<p class="text-muted">{{ lang.admin.f2b_list_info|raw }}</p>
|
<p class="text-muted">{{ lang.admin.f2b_list_info|raw }}</p>
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
@@ -90,6 +97,15 @@
|
|||||||
{% if not f2b_data.active_bans and not f2b_data.perm_bans %}
|
{% if not f2b_data.active_bans and not f2b_data.perm_bans %}
|
||||||
<i>{{ lang.admin.no_active_bans }}</i>
|
<i>{{ lang.admin.no_active_bans }}</i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<form class="form-inline" data-id="f2b_banlist" role="form" method="post">
|
||||||
|
<div class="input-group mb-3">
|
||||||
|
<input type="text" class="form-control" aria-label="Banlist url" value="{{ f2b_banlist_url}}" id="banlist_url">
|
||||||
|
{% if is_https %}
|
||||||
|
<button class="btn btn-secondary" type="button" onclick="copyToClipboard('banlist_url')"><i class="bi bi-clipboard"></i></button>
|
||||||
|
{% endif %}
|
||||||
|
<button class="btn btn-secondary" type="button" data-action="edit_selected" data-item="{{ f2b_data.banlist_id }}" data-id="f2b_banlist" data-api-url='edit/fail2ban/banlist' data-api-attr='{}'><i class="bi bi-arrow-clockwise"></i></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
{% for active_ban in f2b_data.active_bans %}
|
{% for active_ban in f2b_data.active_bans %}
|
||||||
<p>
|
<p>
|
||||||
<span class="badge fs-5 bg-info" style="padding:4px;font-size:85%;">
|
<span class="badge fs-5 bg-info" style="padding:4px;font-size:85%;">
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane fade" id="tab-config-fwdhosts" role="tabpanel" aria-labelledby="tab-config-fwdhosts">
|
<div role="tabpanel" class="tab-pane fade" id="tab-config-fwdhosts" role="tabpanel" aria-labelledby="tab-config-fwdhosts">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-fwdhosts" data-bs-toggle="collapse" aria-controls="collapse-tab-config-fwdhosts">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-fwdhosts" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-fwdhosts">
|
||||||
{{ lang.admin.forwarding_hosts }}
|
{{ lang.admin.forwarding_hosts }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.forwarding_hosts }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.forwarding_hosts }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane fade" id="tab-config-oauth2" role="tabpanel" aria-labelledby="tab-config-oauth2">
|
<div role="tabpanel" class="tab-pane fade" id="tab-config-oauth2" role="tabpanel" aria-labelledby="tab-config-oauth2">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-oauth2" data-bs-toggle="collapse" aria-controls="collapse-tab-config-oauth2">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-oauth2" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-oauth2">
|
||||||
{{ lang.admin.oauth2_apps }}
|
{{ lang.admin.oauth2_apps }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.oauth2_apps }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.oauth2_apps }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane fade" id="tab-config-password-policy" role="tabpanel" aria-labelledby="tab-config-password-policy">
|
<div role="tabpanel" class="tab-pane fade" id="tab-config-password-policy" role="tabpanel" aria-labelledby="tab-config-password-policy">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-password-policy" data-bs-toggle="collapse" aria-controls="collapse-tab-config-password-policy">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-password-policy" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-password-policy">
|
||||||
{{ lang.admin.password_policy }}
|
{{ lang.admin.password_policy }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.password_policy }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.password_policy }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane fade" id="tab-config-quarantine" role="tabpanel" aria-labelledby="tab-config-quarantine">
|
<div role="tabpanel" class="tab-pane fade" id="tab-config-quarantine" role="tabpanel" aria-labelledby="tab-config-quarantine">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-quarantine" data-bs-toggle="collapse" aria-controls="collapse-tab-config-quarantine">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-quarantine" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-quarantine">
|
||||||
{{ lang.admin.quarantine }}
|
{{ lang.admin.quarantine }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.quarantine }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.quarantine }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane fade" id="tab-config-quota" role="tabpanel" aria-labelledby="tab-config-quota">
|
<div role="tabpanel" class="tab-pane fade" id="tab-config-quota" role="tabpanel" aria-labelledby="tab-config-quota">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-quota" data-bs-toggle="collapse" aria-controls="collapse-tab-config-quota">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-quota" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-quota">
|
||||||
{{ lang.admin.quota_notifications }}
|
{{ lang.admin.quota_notifications }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.quota_notifications }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.quota_notifications }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane fade" id="tab-config-rsettings" role="tabpanel" aria-labelledby="tab-config-rsettings">
|
<div role="tabpanel" class="tab-pane fade" id="tab-config-rsettings" role="tabpanel" aria-labelledby="tab-config-rsettings">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-rsettings" data-bs-toggle="collapse" aria-controls="collapse-tab-config-rsettings">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-rsettings" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-rsettings">
|
||||||
{{ lang.admin.rspamd_settings_map }}
|
{{ lang.admin.rspamd_settings_map }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.rspamd_settings_map }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.rspamd_settings_map }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane fade" id="tab-config-rspamd" role="tabpanel" aria-labelledby="tab-config-rspamd">
|
<div role="tabpanel" class="tab-pane fade" id="tab-config-rspamd" role="tabpanel" aria-labelledby="tab-config-rspamd">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-rspamd" data-bs-toggle="collapse" aria-controls="collapse-tab-config-rspamd">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-rspamd" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-rspamd">
|
||||||
Rspamd UI
|
Rspamd UI
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">Rspamd UI</span>
|
<span class="d-none d-md-block">Rspamd UI</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane fade" id="tab-globalfilter-regex" role="tabpanel" aria-labelledby="tab-globalfilter-regex">
|
<div role="tabpanel" class="tab-pane fade" id="tab-globalfilter-regex" role="tabpanel" aria-labelledby="tab-globalfilter-regex">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-regex" data-bs-toggle="collapse" aria-controls="collapse-tab-config-regex">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-regex" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-regex">
|
||||||
{{ lang.admin.rspamd_global_filters }}
|
{{ lang.admin.rspamd_global_filters }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.rspamd_global_filters }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.rspamd_global_filters }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane fade" id="tab-config-ldap-admins" role="tabpanel" aria-labelledby="tab-config-ldap-admins">
|
<div role="tabpanel" class="tab-pane fade" id="tab-config-ldap-admins" role="tabpanel" aria-labelledby="tab-config-ldap-admins">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-ldap-admins" data-bs-toggle="collapse" aria-controls="collapse-tab-config-ldap-admins">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-ldap-admins" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-ldap-admins">
|
||||||
{{ lang.admin.admins_ldap }}
|
{{ lang.admin.admins_ldap }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.admins_ldap }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.admins_ldap }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane fade" id="tab-routing" role="tabpanel" aria-labelledby="tab-routing">
|
<div role="tabpanel" class="tab-pane fade" id="tab-routing" role="tabpanel" aria-labelledby="tab-routing">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-routing" data-bs-toggle="collapse" aria-controls="collapse-tab-routing">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-routing" data-bs-toggle="collapse" aria-controls="ollapse-tab-routing">
|
||||||
{{ lang.admin.relayhosts }}
|
{{ lang.admin.relayhosts }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.relayhosts }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.relayhosts }}</span>
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex">
|
<div class="card-header d-flex">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-maps" data-bs-toggle="collapse" aria-controls="collapse-tab-maps">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-maps" data-bs-toggle="collapse" aria-controls="ollapse-tab-maps">
|
||||||
{{ lang.admin.transport_maps }}
|
{{ lang.admin.transport_maps }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.transport_maps }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.transport_maps }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane fade" id="tab-sys-mails" role="tabpanel" aria-labelledby="tab-sys-mails">
|
<div role="tabpanel" class="tab-pane fade" id="tab-sys-mails" role="tabpanel" aria-labelledby="tab-sys-mails">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-sys-mails" data-bs-toggle="collapse" aria-controls="collapse-tab-sys-mails">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-sys-mails" data-bs-toggle="collapse" aria-controls="ollapse-tab-sys-mails">
|
||||||
{{ lang.admin.sys_mails }}
|
{{ lang.admin.sys_mails }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.sys_mails }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.sys_mails }}</span>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div class="tab-pane fade" id="tab-bcc" role="tabpanel" aria-labelledby="tab-bcc">
|
<div role="tabpanel" class="tab-pane fade" id="tab-bcc" role="tabpanel" aria-labelledby="tab-bcc">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-bcc" data-bs-toggle="collapse" aria-controls="collapse-tab-bcc">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-bcc" data-bs-toggle="collapse" aria-controls="collapse-tab-bcc">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div class="tab-pane fade" id="tab-domain-aliases" role="tabpanel" aria-labelledby="tab-domain-aliases">
|
<div role="tabpanel" class="tab-pane fade" id="tab-domain-aliases" role="tabpanel" aria-labelledby="tab-domain-aliases">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-domain-aliases" data-bs-toggle="collapse" aria-controls="collapse-tab-domain-aliases">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-domain-aliases" data-bs-toggle="collapse" aria-controls="collapse-tab-domain-aliases">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div class="tab-pane fade show active" id="tab-domains" role="tabpanel" aria-labelledby="tab-domains">
|
<div role="tabpanel" class="tab-pane fade show active" id="tab-domains" role="tabpanel" aria-labelledby="tab-domains">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-sm-block d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-domains" data-bs-toggle="collapse" aria-controls="collapse-tab-domains">
|
<button class="btn d-sm-block d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-domains" data-bs-toggle="collapse" aria-controls="collapse-tab-domains">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div class="tab-pane fade" id="tab-filters" role="tabpanel" aria-labelledby="tab-filters">
|
<div role="tabpanel" class="tab-pane fade" id="tab-filters" role="tabpanel" aria-labelledby="tab-filters">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-filters" data-bs-toggle="collapse" aria-controls="collapse-tab-filters">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-filters" data-bs-toggle="collapse" aria-controls="collapse-tab-filters">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div class="tab-pane fade" id="tab-mailboxes" role="tabpanel" aria-labelledby="tab-mailboxes">
|
<div role="tabpanel" class="tab-pane fade" id="tab-mailboxes" role="tabpanel" aria-labelledby="tab-mailboxes">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-mailboxes" data-bs-toggle="collapse" aria-controls="collapse-tab-mailboxes">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-mailboxes" data-bs-toggle="collapse" aria-controls="collapse-tab-mailboxes">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div class="tab-pane fade" id="tab-mbox-aliases" role="tabpanel" aria-labelledby="tab-mbox-aliases">
|
<div role="tabpanel" class="tab-pane fade" id="tab-mbox-aliases" role="tabpanel" aria-labelledby="tab-mbox-aliases">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-mbox-aliases" data-bs-toggle="collapse" aria-controls="collapse-tab-mbox-aliases">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-mbox-aliases" data-bs-toggle="collapse" aria-controls="collapse-tab-mbox-aliases">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div class="tab-pane fade" id="tab-resources" role="tabpanel" aria-labelledby="tab-resources">
|
<div role="tabpanel" class="tab-pane fade" id="tab-resources" role="tabpanel" aria-labelledby="tab-resources">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-resources" data-bs-toggle="collapse" aria-controls="collapse-tab-resources">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-resources" data-bs-toggle="collapse" aria-controls="collapse-tab-resources">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div class="tab-pane fade" id="tab-syncjobs" role="tabpanel" aria-labelledby="tab-syncjobs">
|
<div role="tabpanel" class="tab-pane fade" id="tab-syncjobs" role="tabpanel" aria-labelledby="tab-syncjobs">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-syncjobs" data-bs-toggle="collapse" aria-controls="collapse-tab-syncjobs">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-syncjobs" data-bs-toggle="collapse" aria-controls="collapse-tab-syncjobs">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div class="tab-pane fade show" id="tab-templates-domains" role="tabpanel" aria-labelledby="tab-templates-domains">
|
<div role="tabpanel" class="tab-pane fade show" id="tab-templates-domains" role="tabpanel" aria-labelledby="tab-templates-domains">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-sm-block d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-templates-domains" data-bs-toggle="collapse" aria-controls="collapse-tab-templates-domains">
|
<button class="btn d-sm-block d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-templates-domains" data-bs-toggle="collapse" aria-controls="collapse-tab-templates-domains">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div class="tab-pane fade show" id="tab-templates-mbox" role="tabpanel" aria-labelledby="tab-templates-mbox">
|
<div role="tabpanel" class="tab-pane fade show" id="tab-templates-mbox" role="tabpanel" aria-labelledby="tab-templates-mbox">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-sm-block d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-templates-mbox" data-bs-toggle="collapse" aria-controls="collapse-tab-templates-mbox">
|
<button class="btn d-sm-block d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-templates-mbox" data-bs-toggle="collapse" aria-controls="collapse-tab-templates-mbox">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div class="tab-pane fade{% if mailcow_cc_role != 'admin' %} d-none{% endif %}" id="tab-tls-policy" role="tabpanel" aria-labelledby="tab-tls-policy">
|
<div role="tabpanel" class="tab-pane fade{% if mailcow_cc_role != 'admin' %} d-none{% endif %}" id="tab-tls-policy" role="tabpanel" aria-labelledby="tab-tls-policy">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-tls-policy" data-bs-toggle="collapse" aria-controls="collapse-tab-tls-policy">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-tls-policy" data-bs-toggle="collapse" aria-controls="collapse-tab-tls-policy">
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div class="tab-pane fade" id="AppPasswds" role="tabpanel" aria-labelledby="AppPasswds">
|
<div role="tabpanel" class="tab-pane fade" id="AppPasswds" role="tabpanel" aria-labelledby="AppPasswds">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-AppPasswds" data-bs-toggle="collapse" aria-controls="collapse-tab-AppPasswds">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-AppPasswds" data-bs-toggle="collapse" aria-controls="collapse-tab-AppPasswds">
|
||||||
{{ lang.user.app_passwds }}
|
{{ lang.user.app_passwds }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.user.app_passwds }}</span>
|
<span class="d-none d-md-block">{{ lang.user.app_passwds }}
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-AppPasswds" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-AppPasswds" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
<div class="mass-actions-user mb-4">
|
<div class="mass-actions-user mb-4">
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div class="tab-pane fade" id="Pushover" role="tabpanel" aria-labelledby="Pushover">
|
<div role="tabpanel" class="tab-pane fade" id="Pushover" role="tabpanel" aria-labelledby="Pushover">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-Pushover" data-bs-toggle="collapse" aria-controls="collapse-tab-Pushover">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-Pushover" data-bs-toggle="collapse" aria-controls="collapse-tab-Pushover">
|
||||||
Pushover API
|
Pushover API
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">Pushover API</span>
|
<span class="d-none d-md-block">Pushover API
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-Pushover" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-Pushover" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
<form data-id="pushover" class="form well" method="post">
|
<form data-id="pushover" class="form well" method="post">
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div class="tab-pane fade" id="SpamAliases" role="tabpanel" aria-labelledby="SpamAliases">
|
<div role="tabpanel" class="tab-pane fade" id="SpamAliases" role="tabpanel" aria-labelledby="SpamAliases">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-SpamAliases" data-bs-toggle="collapse" aria-controls="collapse-tab-SpamAliases">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-SpamAliases" data-bs-toggle="collapse" aria-controls="collapse-tab-SpamAliases">
|
||||||
{{ lang.user.spam_aliases }}
|
{{ lang.user.spam_aliases }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.user.spam_aliases }}</span>
|
<span class="d-none d-md-block">{{ lang.user.spam_aliases }}
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-SpamAliases" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-SpamAliases" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div class="tab-pane fade" id="Spamfilter" role="tabpanel" aria-labelledby="Spamfilter">
|
<div role="tabpanel" class="tab-pane fade" id="Spamfilter" role="tabpanel" aria-labelledby="Spamfilter">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-Spamfilter" data-bs-toggle="collapse" aria-controls="collapse-tab-Spamfilter">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-Spamfilter" data-bs-toggle="collapse" aria-controls="collapse-tab-Spamfilter">
|
||||||
{{ lang.user.spamfilter }}
|
{{ lang.user.spamfilter }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.user.spamfilter }}</span>
|
<span class="d-none d-md-block">{{ lang.user.spamfilter }}
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-Spamfilter" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-Spamfilter" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
<h4>{{ lang.user.spamfilter_behavior }}</h4>
|
<h4>{{ lang.user.spamfilter_behavior }}</h4>
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div class="tab-pane fade" id="Syncjobs" role="tabpanel" aria-labelledby="Syncjobs">
|
<div role="tabpanel" class="tab-pane fade" id="Syncjobs" role="tabpanel" aria-labelledby="Syncjobs">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-Syncjobs" data-bs-toggle="collapse" aria-controls="collapse-tab-Syncjobs">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-Syncjobs" data-bs-toggle="collapse" aria-controls="collapse-tab-Syncjobs">
|
||||||
{{ lang.user.sync_jobs }}
|
{{ lang.user.sync_jobs }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.user.sync_jobs }}</span>
|
<span class="d-none d-md-block">{{ lang.user.sync_jobs }}
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-Syncjobs" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-Syncjobs" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
<div class="mass-actions-user mb-4">
|
<div class="mass-actions-user mb-4">
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div class="tab-pane fade in active show" id="tab-user-auth" role="tabpanel" aria-labelledby="tab-user-auth">
|
<div role="tabpanel" class="tab-pane fade in active show" id="tab-user-auth" role="tabpanel" aria-labelledby="tab-user-auth">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-user-auth" data-bs-toggle="collapse" aria-controls="collapse-tab-user-auth">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-user-auth" data-bs-toggle="collapse" aria-controls="collapse-tab-user-auth">
|
||||||
{{ lang.user.mailbox_general }}
|
{{ lang.user.mailbox_general }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.user.mailbox_general }}</span>
|
<span class="d-none d-md-block">{{ lang.user.mailbox_general }}
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-user-auth" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-user-auth" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
{% if mailboxdata.attributes.force_pw_update == '1' %}
|
{% if mailboxdata.attributes.force_pw_update == '1' %}
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div class="tab-pane fade" id="tab-user-details" role="tabpanel" aria-labelledby="tab-user-details">
|
<div role="tabpanel" class="tab-pane fade" id="tab-user-details" role="tabpanel" aria-labelledby="tab-user-details">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-user-details" data-bs-toggle="collapse" aria-controls="collapse-tab-user-details">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-user-details" data-bs-toggle="collapse" aria-controls="collapse-tab-user-details">
|
||||||
{{ lang.user.mailbox_details }}
|
{{ lang.user.mailbox_details }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.user.mailbox_details }}</span>
|
<span class="d-none d-md-block">{{ lang.user.mailbox_details }}
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-user-details" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-user-details" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div class="tab-pane fade" id="tab-user-settings" role="tabpanel" aria-labelledby="tab-user-settings">
|
<div role="tabpanel" class="tab-pane fade" id="tab-user-settings" role="tabpanel" aria-labelledby="tab-user-settings">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-user-settings" data-bs-toggle="collapse" aria-controls="collapse-tab-user-settings">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-user-settings" data-bs-toggle="collapse" aria-controls="collapse-tab-user-settings">
|
||||||
{{ lang.user.mailbox_settings }}
|
{{ lang.user.mailbox_settings }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.user.mailbox_settings }}</span>
|
<span class="d-none d-md-block">{{ lang.user.mailbox_settings }}
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-user-settings" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-user-settings" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
{# Show tagging options #}
|
{# Show tagging options #}
|
||||||
|
@@ -426,7 +426,7 @@ services:
|
|||||||
- acme
|
- acme
|
||||||
|
|
||||||
netfilter-mailcow:
|
netfilter-mailcow:
|
||||||
image: mailcow/netfilter:1.52
|
image: mailcow/netfilter:1.53
|
||||||
stop_grace_period: 30s
|
stop_grace_period: 30s
|
||||||
depends_on:
|
depends_on:
|
||||||
- dovecot-mailcow
|
- dovecot-mailcow
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?<version>.*)$
|
# renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?<version>.*)$
|
||||||
NEXTCLOUD_VERSION=27.0.1
|
NEXTCLOUD_VERSION=27.0.0
|
||||||
|
|
||||||
echo -ne "Checking prerequisites..."
|
echo -ne "Checking prerequisites..."
|
||||||
sleep 1
|
sleep 1
|
||||||
|
Reference in New Issue
Block a user