diff --git a/data/Dockerfiles/dockerapi/dockerapi.py b/data/Dockerfiles/dockerapi/dockerapi.py
index 03ed5ef0..304c1781 100644
--- a/data/Dockerfiles/dockerapi/dockerapi.py
+++ b/data/Dockerfiles/dockerapi/dockerapi.py
@@ -499,6 +499,7 @@ class DockerUtils:
async with rspamd_password_exec.start(detach=False) as stream:
rspamd_password_return = await stream.read_out()
+ matched = False
if "OK" in rspamd_password_return.data.decode('utf-8'):
matched = True
await container.restart()
diff --git a/data/web/edit.php b/data/web/edit.php
index ff1ccc44..09db796d 100644
--- a/data/web/edit.php
+++ b/data/web/edit.php
@@ -38,24 +38,46 @@ if (isset($_SESSION['mailcow_cc_role'])) {
$template = 'edit/admin.twig';
$template_data = ['admin' => $admin];
}
- elseif (isset($_GET['domain']) &&
- is_valid_domain_name($_GET["domain"]) &&
- !empty($_GET["domain"])) {
- $domain = $_GET["domain"];
- $result = mailbox('get', 'domain_details', $domain);
- $quota_notification_bcc = quota_notification_bcc('get', $domain);
- $rl = ratelimit('get', 'domain', $domain);
- $rlyhosts = relayhost('get');
- $template = 'edit/domain.twig';
+ elseif (isset($_GET['domain'])) {
+ if (is_valid_domain_name($_GET["domain"]) &&
+ !empty($_GET["domain"])) {
+ // edit domain
+ $domain = $_GET["domain"];
+ $result = mailbox('get', 'domain_details', $domain);
+ $quota_notification_bcc = quota_notification_bcc('get', $domain);
+ $rl = ratelimit('get', 'domain', $domain);
+ $rlyhosts = relayhost('get');
+ $template = 'edit/domain.twig';
+ $template_data = [
+ 'acl' => $_SESSION['acl'],
+ 'domain' => $domain,
+ 'quota_notification_bcc' => $quota_notification_bcc,
+ 'rl' => $rl,
+ 'rlyhosts' => $rlyhosts,
+ 'dkim' => dkim('details', $domain),
+ 'domain_details' => $result,
+ ];
+ }
+ }
+ elseif (isset($_GET["template"])){
+ $domain_template = mailbox('get', 'domain_templates', $_GET["template"]);
+ if ($domain_template){
$template_data = [
- 'acl' => $_SESSION['acl'],
- 'domain' => $domain,
- 'quota_notification_bcc' => $quota_notification_bcc,
- 'rl' => $rl,
- 'rlyhosts' => $rlyhosts,
- 'dkim' => dkim('details', $domain),
- 'domain_details' => $result,
+ 'template' => $domain_template
];
+ $template = 'edit/domain-templates.twig';
+ $result = true;
+ }
+ else {
+ $mailbox_template = mailbox('get', 'mailbox_templates', $_GET["template"]);
+ if ($mailbox_template){
+ $template_data = [
+ 'template' => $mailbox_template
+ ];
+ $template = 'edit/mailbox-templates.twig';
+ $result = true;
+ }
+ }
}
elseif (isset($_GET['oauth2client']) &&
is_numeric($_GET["oauth2client"]) &&
@@ -79,29 +101,32 @@ if (isset($_SESSION['mailcow_cc_role'])) {
'dkim' => dkim('details', $alias_domain),
];
}
- elseif (isset($_GET['mailbox']) && filter_var(html_entity_decode(rawurldecode($_GET["mailbox"])), FILTER_VALIDATE_EMAIL) && !empty($_GET["mailbox"])) {
- $mailbox = html_entity_decode(rawurldecode($_GET["mailbox"]));
- $result = mailbox('get', 'mailbox_details', $mailbox);
- $rl = ratelimit('get', 'mailbox', $mailbox);
- $pushover_data = pushover('get', $mailbox);
- $quarantine_notification = mailbox('get', 'quarantine_notification', $mailbox);
- $quarantine_category = mailbox('get', 'quarantine_category', $mailbox);
- $get_tls_policy = mailbox('get', 'tls_policy', $mailbox);
- $rlyhosts = relayhost('get');
- $template = 'edit/mailbox.twig';
- $template_data = [
- 'acl' => $_SESSION['acl'],
- 'mailbox' => $mailbox,
- 'rl' => $rl,
- 'pushover_data' => $pushover_data,
- 'quarantine_notification' => $quarantine_notification,
- 'quarantine_category' => $quarantine_category,
- 'get_tls_policy' => $get_tls_policy,
- 'rlyhosts' => $rlyhosts,
- 'sender_acl_handles' => mailbox('get', 'sender_acl_handles', $mailbox),
- 'user_acls' => acl('get', 'user', $mailbox),
- 'mailbox_details' => $result
- ];
+ elseif (isset($_GET['mailbox'])){
+ if(filter_var(html_entity_decode(rawurldecode($_GET["mailbox"])), FILTER_VALIDATE_EMAIL) && !empty($_GET["mailbox"])) {
+ // edit mailbox
+ $mailbox = html_entity_decode(rawurldecode($_GET["mailbox"]));
+ $result = mailbox('get', 'mailbox_details', $mailbox);
+ $rl = ratelimit('get', 'mailbox', $mailbox);
+ $pushover_data = pushover('get', $mailbox);
+ $quarantine_notification = mailbox('get', 'quarantine_notification', $mailbox);
+ $quarantine_category = mailbox('get', 'quarantine_category', $mailbox);
+ $get_tls_policy = mailbox('get', 'tls_policy', $mailbox);
+ $rlyhosts = relayhost('get');
+ $template = 'edit/mailbox.twig';
+ $template_data = [
+ 'acl' => $_SESSION['acl'],
+ 'mailbox' => $mailbox,
+ 'rl' => $rl,
+ 'pushover_data' => $pushover_data,
+ 'quarantine_notification' => $quarantine_notification,
+ 'quarantine_category' => $quarantine_category,
+ 'get_tls_policy' => $get_tls_policy,
+ 'rlyhosts' => $rlyhosts,
+ 'sender_acl_handles' => mailbox('get', 'sender_acl_handles', $mailbox),
+ 'user_acls' => acl('get', 'user', $mailbox),
+ 'mailbox_details' => $result
+ ];
+ }
}
elseif (isset($_GET['relayhost']) && is_numeric($_GET["relayhost"]) && !empty($_GET["relayhost"])) {
$relayhost = intval($_GET["relayhost"]);
diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php
index 2cf9f6c6..55c8d6bc 100644
--- a/data/web/inc/functions.mailbox.inc.php
+++ b/data/web/inc/functions.mailbox.inc.php
@@ -1020,6 +1020,13 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
if (empty($name)) {
$name = $local_part;
}
+ if (isset($_data['protocol_access'])) {
+ $_data['protocol_access'] = (array)$_data['protocol_access'];
+ $_data['imap_access'] = (in_array('imap', $_data['protocol_access'])) ? 1 : 0;
+ $_data['pop3_access'] = (in_array('pop3', $_data['protocol_access'])) ? 1 : 0;
+ $_data['smtp_access'] = (in_array('smtp', $_data['protocol_access'])) ? 1 : 0;
+ $_data['sieve_access'] = (in_array('sieve', $_data['protocol_access'])) ? 1 : 0;
+ }
$active = intval($_data['active']);
$force_pw_update = (isset($_data['force_pw_update'])) ? intval($_data['force_pw_update']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update']);
$tls_enforce_in = (isset($_data['tls_enforce_in'])) ? intval($_data['tls_enforce_in']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_in']);
@@ -1200,10 +1207,63 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
':domain' => $domain,
':active' => $active
));
- $stmt = $pdo->prepare("INSERT INTO `user_acl` (`username`) VALUES (:username)");
- $stmt->execute(array(
- ':username' => $username
- ));
+
+
+ if (isset($_data['acl'])) {
+ $_data['acl'] = (array)$_data['acl'];
+ $_data['spam_alias'] = (in_array('spam_alias', $_data['acl'])) ? 1 : 0;
+ $_data['tls_policy'] = (in_array('tls_policy', $_data['acl'])) ? 1 : 0;
+ $_data['spam_score'] = (in_array('spam_score', $_data['acl'])) ? 1 : 0;
+ $_data['spam_policy'] = (in_array('spam_policy', $_data['acl'])) ? 1 : 0;
+ $_data['delimiter_action'] = (in_array('delimiter_action', $_data['acl'])) ? 1 : 0;
+ $_data['syncjobs'] = (in_array('syncjobs', $_data['acl'])) ? 1 : 0;
+ $_data['eas_reset'] = (in_array('eas_reset', $_data['acl'])) ? 1 : 0;
+ $_data['sogo_profile_reset'] = (in_array('sogo_profile_reset', $_data['acl'])) ? 1 : 0;
+ $_data['pushover'] = (in_array('pushover', $_data['acl'])) ? 1 : 0;
+ $_data['quarantine'] = (in_array('quarantine', $_data['acl'])) ? 1 : 0;
+ $_data['quarantine_attachments'] = (in_array('quarantine_attachments', $_data['acl'])) ? 1 : 0;
+ $_data['quarantine_notification'] = (in_array('quarantine_notification', $_data['acl'])) ? 1 : 0;
+ $_data['quarantine_category'] = (in_array('quarantine_category', $_data['acl'])) ? 1 : 0;
+ $_data['app_passwds'] = (in_array('app_passwds', $_data['acl'])) ? 1 : 0;
+
+ $stmt = $pdo->prepare("INSERT INTO `user_acl`
+ (`username`, `spam_alias`, `tls_policy`, `spam_score`, `spam_policy`, `delimiter_action`, `syncjobs`, `eas_reset`, `sogo_profile_reset`,
+ `pushover`, `quarantine`, `quarantine_attachments`, `quarantine_notification`, `quarantine_category`, `app_passwds`)
+ VALUES (:username, :spam_alias, :tls_policy, :spam_score, :spam_policy, :delimiter_action, :syncjobs, :eas_reset, :sogo_profile_reset,
+ :pushover, :quarantine, :quarantine_attachments, :quarantine_notification, :quarantine_category, :app_passwds) ");
+ $stmt->execute(array(
+ ':username' => $username,
+ ':spam_alias' => $_data['spam_alias'],
+ ':tls_policy' => $_data['tls_policy'],
+ ':spam_score' => $_data['spam_score'],
+ ':spam_policy' => $_data['spam_policy'],
+ ':delimiter_action' => $_data['delimiter_action'],
+ ':syncjobs' => $_data['syncjobs'],
+ ':eas_reset' => $_data['eas_reset'],
+ ':sogo_profile_reset' => $_data['sogo_profile_reset'],
+ ':pushover' => $_data['pushover'],
+ ':quarantine' => $_data['quarantine'],
+ ':quarantine_attachments' => $_data['quarantine_attachments'],
+ ':quarantine_notification' => $_data['quarantine_notification'],
+ ':quarantine_category' => $_data['quarantine_category'],
+ ':app_passwds' => $_data['app_passwds']
+ ));
+ }
+ else {
+ $stmt = $pdo->prepare("INSERT INTO `user_acl` (`username`) VALUES (:username)");
+ $stmt->execute(array(
+ ':username' => $username
+ ));
+ }
+
+ if (isset($_data['rl_frame']) && isset($_data['rl_value'])){
+ ratelimit('edit', 'mailbox', array(
+ 'object' => $username,
+ 'rl_frame' => $_data['rl_frame'],
+ 'rl_value' => $_data['rl_value']
+ ));
+ }
+
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
@@ -1322,6 +1382,191 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
'msg' => array('resource_added', htmlspecialchars($name))
);
break;
+ case 'domain_templates':
+ if ($_SESSION['mailcow_cc_role'] != "admin") {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
+ if (empty($_data["template"])){
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
+ 'msg' => 'template_name_invalid'
+ );
+ return false;
+ }
+
+ // check if template name exists, return false
+ $stmt = $pdo->prepare("SELECT id FROM `templates` WHERE `type` = :type AND `template` = :template");
+ $stmt->execute(array(
+ ":type" => "domain",
+ ":template" => $_data["template"]
+ ));
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if (!empty($row)){
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
+ 'msg' => array('template_exists', $_data["template"])
+ );
+ return false;
+ }
+
+ // check attributes
+ $attr = array();
+ $attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : array();
+ $attr['max_num_aliases_for_domain'] = (isset($_data['max_num_aliases_for_domain'])) ? intval($_data['max_num_aliases_for_domain']) : 0;
+ $attr['max_num_mboxes_for_domain'] = (isset($_data['max_num_mboxes_for_domain'])) ? intval($_data['max_num_mboxes_for_domain']) : 0;
+ $attr['def_quota_for_mbox'] = (isset($_data['def_quota_for_mbox'])) ? intval($_data['def_quota_for_mbox']) * 1048576 : 0;
+ $attr['max_quota_for_mbox'] = (isset($_data['max_quota_for_mbox'])) ? intval($_data['max_quota_for_mbox']) * 1048576 : 0;
+ $attr['max_quota_for_domain'] = (isset($_data['max_quota_for_domain'])) ? intval($_data['max_quota_for_domain']) * 1048576 : 0;
+ $attr['rl_frame'] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : "s";
+ $attr['rl_value'] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : "";
+ $attr['active'] = isset($_data['active']) ? intval($_data['active']) : 1;
+ $attr['gal'] = (isset($_data['gal'])) ? intval($_data['gal']) : 1;
+ $attr['backupmx'] = (isset($_data['backupmx'])) ? intval($_data['backupmx']) : 0;
+ $attr['relay_all_recipients'] = (isset($_data['relay_all_recipients'])) ? intval($_data['relay_all_recipients']) : 0;
+ $attr['relay_unknown_only'] = (isset($_data['relay_unknown_only'])) ? intval($_data['relay_unknown_only']) : 0;
+ $attr['dkim_selector'] = (isset($_data['dkim_selector'])) ? $_data['dkim_selector'] : "dkim";
+ $attr['key_size'] = isset($_data['key_size']) ? intval($_data['key_size']) : 2048;
+
+
+ // save template
+ $stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`)
+ VALUES (:type, :template, :attributes)");
+ $stmt->execute(array(
+ ":type" => "domain",
+ ":template" => $_data["template"],
+ ":attributes" => json_encode($attr)
+ ));
+
+ // success
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => array('template_added', $_data["template"])
+ );
+ return true;
+ break;
+ case 'mailbox_templates':
+ if ($_SESSION['mailcow_cc_role'] != "admin") {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
+ if (empty($_data["template"])){
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
+ 'msg' => 'template_name_invalid'
+ );
+ return false;
+ }
+
+ // check if template name exists, return false
+ $stmt = $pdo->prepare("SELECT id FROM `templates` WHERE `type` = :type AND `template` = :template");
+ $stmt->execute(array(
+ ":type" => "mailbox",
+ ":template" => $_data["template"]
+ ));
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ if (!empty($row)){
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
+ 'msg' => array('template_exists', $_data["template"])
+ );
+ return false;
+ }
+
+
+ // check attributes
+ $attr = array();
+ $attr["quota"] = isset($_data['quota']) ? intval($_data['quota']) * 1048576 : 0;
+ $attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : array();
+ $attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification']);
+ $attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']);
+ $attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : "s";
+ $attr["rl_value"] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : "";
+ $attr["force_pw_update"] = isset($_data['force_pw_update']) ? intval($_data['force_pw_update']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update']);
+ $attr["sogo_access"] = isset($_data['sogo_access']) ? intval($_data['sogo_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['sogo_access']);
+ $attr["active"] = isset($_data['active']) ? intval($_data['active']) : 1;
+ $attr["tls_enforce_in"] = isset($_data['tls_enforce_in']) ? intval($_data['tls_enforce_in']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_in']);
+ $attr["tls_enforce_out"] = isset($_data['tls_enforce_out']) ? intval($_data['tls_enforce_out']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_out']);
+ if (isset($_data['protocol_access'])) {
+ $_data['protocol_access'] = (array)$_data['protocol_access'];
+ $attr['imap_access'] = (in_array('imap', $_data['protocol_access'])) ? 1 : intval($MAILBOX_DEFAULT_ATTRIBUTES['imap_access']);
+ $attr['pop3_access'] = (in_array('pop3', $_data['protocol_access'])) ? 1 : intval($MAILBOX_DEFAULT_ATTRIBUTES['pop3_access']);
+ $attr['smtp_access'] = (in_array('smtp', $_data['protocol_access'])) ? 1 : intval($MAILBOX_DEFAULT_ATTRIBUTES['smtp_access']);
+ $attr['sieve_access'] = (in_array('sieve', $_data['protocol_access'])) ? 1 : intval($MAILBOX_DEFAULT_ATTRIBUTES['sieve_access']);
+ }
+ else {
+ $attr['imap_access'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['imap_access']);
+ $attr['pop3_access'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['pop3_access']);
+ $attr['smtp_access'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['smtp_access']);
+ $attr['sieve_access'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['sieve_access']);
+ }
+ if (isset($_data['acl'])) {
+ $_data['acl'] = (array)$_data['acl'];
+ $attr['acl_spam_alias'] = (in_array('spam_alias', $_data['acl'])) ? 1 : 0;
+ $attr['acl_tls_policy'] = (in_array('tls_policy', $_data['acl'])) ? 1 : 0;
+ $attr['acl_spam_score'] = (in_array('spam_score', $_data['acl'])) ? 1 : 0;
+ $attr['acl_spam_policy'] = (in_array('spam_policy', $_data['acl'])) ? 1 : 0;
+ $attr['acl_delimiter_action'] = (in_array('delimiter_action', $_data['acl'])) ? 1 : 0;
+ $attr['acl_syncjobs'] = (in_array('syncjobs', $_data['acl'])) ? 1 : 0;
+ $attr['acl_eas_reset'] = (in_array('eas_reset', $_data['acl'])) ? 1 : 0;
+ $attr['acl_sogo_profile_reset'] = (in_array('sogo_profile_reset', $_data['acl'])) ? 1 : 0;
+ $attr['acl_pushover'] = (in_array('pushover', $_data['acl'])) ? 1 : 0;
+ $attr['acl_quarantine'] = (in_array('quarantine', $_data['acl'])) ? 1 : 0;
+ $attr['acl_quarantine_attachments'] = (in_array('quarantine_attachments', $_data['acl'])) ? 1 : 0;
+ $attr['acl_quarantine_notification'] = (in_array('quarantine_notification', $_data['acl'])) ? 1 : 0;
+ $attr['acl_quarantine_category'] = (in_array('quarantine_category', $_data['acl'])) ? 1 : 0;
+ $attr['acl_app_passwds'] = (in_array('app_passwds', $_data['acl'])) ? 1 : 0;
+ } else {
+ $_data['acl'] = (array)$_data['acl'];
+ $attr['acl_spam_alias'] = 1;
+ $attr['acl_tls_policy'] = 1;
+ $attr['acl_spam_score'] = 1;
+ $attr['acl_spam_policy'] = 1;
+ $attr['acl_delimiter_action'] = 1;
+ $attr['acl_syncjobs'] = 0;
+ $attr['acl_eas_reset'] = 1;
+ $attr['acl_sogo_profile_reset'] = 0;
+ $attr['acl_pushover'] = 1;
+ $attr['acl_quarantine'] = 1;
+ $attr['acl_quarantine_attachments'] = 1;
+ $attr['acl_quarantine_notification'] = 1;
+ $attr['acl_quarantine_category'] = 1;
+ $attr['acl_app_passwds'] = 1;
+ }
+
+
+
+ // save template
+ $stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`)
+ VALUES (:type, :template, :attributes)");
+ $stmt->execute(array(
+ ":type" => "mailbox",
+ ":template" => $_data["template"],
+ ":attributes" => json_encode($attr)
+ ));
+
+ // success
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => array('template_added', $_data["template"])
+ );
+ return true;
+ break;
}
break;
case 'edit':
@@ -2472,6 +2717,79 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
}
}
break;
+ case 'domain_templates':
+ if ($_SESSION['mailcow_cc_role'] != "admin") {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
+ if (!is_array($_data['ids'])) {
+ $ids = array();
+ $ids[] = $_data['ids'];
+ }
+ else {
+ $ids = $_data['ids'];
+ }
+ foreach ($ids as $id) {
+ $is_now = mailbox("get", "domain_templates", $id);
+ if (empty($is_now) ||
+ $is_now["type"] != "domain"){
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
+ 'msg' => 'template_id_invalid'
+ );
+ continue;
+ }
+
+ // check name
+ if ($is_now["template"] == "Default" && $is_now["template"] != $_data["template"]){
+ // keep template name of Default template
+ $_data["template"] = $is_now["template"];
+ }
+ else {
+ $_data["template"] = (isset($_data["template"])) ? $_data["template"] : $is_now["template"];
+ }
+ // check attributes
+ $attr = array();
+ $attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : array();
+ $attr['max_num_aliases_for_domain'] = (isset($_data['max_num_aliases_for_domain'])) ? intval($_data['max_num_aliases_for_domain']) : 0;
+ $attr['max_num_mboxes_for_domain'] = (isset($_data['max_num_mboxes_for_domain'])) ? intval($_data['max_num_mboxes_for_domain']) : 0;
+ $attr['def_quota_for_mbox'] = (isset($_data['def_quota_for_mbox'])) ? intval($_data['def_quota_for_mbox']) * 1048576 : 0;
+ $attr['max_quota_for_mbox'] = (isset($_data['max_quota_for_mbox'])) ? intval($_data['max_quota_for_mbox']) * 1048576 : 0;
+ $attr['max_quota_for_domain'] = (isset($_data['max_quota_for_domain'])) ? intval($_data['max_quota_for_domain']) * 1048576 : 0;
+ $attr['rl_frame'] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : "s";
+ $attr['rl_value'] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : "";
+ $attr['active'] = isset($_data['active']) ? intval($_data['active']) : 1;
+ $attr['gal'] = (isset($_data['gal'])) ? intval($_data['gal']) : 1;
+ $attr['backupmx'] = (isset($_data['backupmx'])) ? intval($_data['backupmx']) : 0;
+ $attr['relay_all_recipients'] = (isset($_data['relay_all_recipients'])) ? intval($_data['relay_all_recipients']) : 0;
+ $attr['relay_unknown_only'] = (isset($_data['relay_unknown_only'])) ? intval($_data['relay_unknown_only']) : 0;
+ $attr['dkim_selector'] = (isset($_data['dkim_selector'])) ? $_data['dkim_selector'] : "dkim";
+ $attr['key_size'] = isset($_data['key_size']) ? intval($_data['key_size']) : 2048;
+
+ // update template
+ $stmt = $pdo->prepare("UPDATE `templates`
+ SET `template` = :template, `attributes` = :attributes
+ WHERE id = :id");
+ $stmt->execute(array(
+ ":id" => $id ,
+ ":template" => $_data["template"] ,
+ ":attributes" => json_encode($attr)
+ ));
+ }
+
+
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => array('template_modified', $_data["template"])
+ );
+ return true;
+ break;
case 'mailbox':
if (!is_array($_data['username'])) {
$usernames = array();
@@ -2814,6 +3132,110 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
);
}
break;
+ case 'mailbox_templates':
+ if ($_SESSION['mailcow_cc_role'] != "admin") {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
+ if (!is_array($_data['ids'])) {
+ $ids = array();
+ $ids[] = $_data['ids'];
+ }
+ else {
+ $ids = $_data['ids'];
+ }
+ foreach ($ids as $id) {
+ $is_now = mailbox("get", "mailbox_templates", $id);
+ if (empty($is_now) ||
+ $is_now["type"] != "mailbox"){
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
+ 'msg' => 'template_id_invalid'
+ );
+ continue;
+ }
+
+
+ // check name
+ if ($is_now["template"] == "Default" && $is_now["template"] != $_data["template"]){
+ // keep template name of Default template
+ $_data["template"] = $is_now["template"];
+ }
+ else {
+ $_data["template"] = (isset($_data["template"])) ? $_data["template"] : $is_now["template"];
+ }
+ // check attributes
+ $attr = array();
+ $attr["quota"] = isset($_data['quota']) ? intval($_data['quota']) * 1048576 : 0;
+ $attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : $is_now['tags'];
+ $attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : $is_now['quarantine_notification'];
+ $attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : $is_now['quarantine_category'];
+ $attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : $is_now['rl_frame'];
+ $attr["rl_value"] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : $is_now['rl_value'];
+ $attr["force_pw_update"] = isset($_data['force_pw_update']) ? intval($_data['force_pw_update']) : $is_now['force_pw_update'];
+ $attr["sogo_access"] = isset($_data['sogo_access']) ? intval($_data['sogo_access']) : $is_now['sogo_access'];
+ $attr["active"] = isset($_data['active']) ? intval($_data['active']) : $is_now['active'];
+ $attr["tls_enforce_in"] = isset($_data['tls_enforce_in']) ? intval($_data['tls_enforce_in']) : $is_now['tls_enforce_in'];
+ $attr["tls_enforce_out"] = isset($_data['tls_enforce_out']) ? intval($_data['tls_enforce_out']) : $is_now['tls_enforce_out'];
+ if (isset($_data['protocol_access'])) {
+ $_data['protocol_access'] = (array)$_data['protocol_access'];
+ $attr['imap_access'] = (in_array('imap', $_data['protocol_access'])) ? 1 : 0;
+ $attr['pop3_access'] = (in_array('pop3', $_data['protocol_access'])) ? 1 : 0;
+ $attr['smtp_access'] = (in_array('smtp', $_data['protocol_access'])) ? 1 : 0;
+ $attr['sieve_access'] = (in_array('sieve', $_data['protocol_access'])) ? 1 : 0;
+ }
+ else {
+ foreach ($is_now as $key => $value){
+ $attr[$key] = $is_now[$key];
+ }
+ }
+ if (isset($_data['acl'])) {
+ $_data['acl'] = (array)$_data['acl'];
+ $attr['acl_spam_alias'] = (in_array('spam_alias', $_data['acl'])) ? 1 : 0;
+ $attr['acl_tls_policy'] = (in_array('tls_policy', $_data['acl'])) ? 1 : 0;
+ $attr['acl_spam_score'] = (in_array('spam_score', $_data['acl'])) ? 1 : 0;
+ $attr['acl_spam_policy'] = (in_array('spam_policy', $_data['acl'])) ? 1 : 0;
+ $attr['acl_delimiter_action'] = (in_array('delimiter_action', $_data['acl'])) ? 1 : 0;
+ $attr['acl_syncjobs'] = (in_array('syncjobs', $_data['acl'])) ? 1 : 0;
+ $attr['acl_eas_reset'] = (in_array('eas_reset', $_data['acl'])) ? 1 : 0;
+ $attr['acl_sogo_profile_reset'] = (in_array('sogo_profile_reset', $_data['acl'])) ? 1 : 0;
+ $attr['acl_pushover'] = (in_array('pushover', $_data['acl'])) ? 1 : 0;
+ $attr['acl_quarantine'] = (in_array('quarantine', $_data['acl'])) ? 1 : 0;
+ $attr['acl_quarantine_attachments'] = (in_array('quarantine_attachments', $_data['acl'])) ? 1 : 0;
+ $attr['acl_quarantine_notification'] = (in_array('quarantine_notification', $_data['acl'])) ? 1 : 0;
+ $attr['acl_quarantine_category'] = (in_array('quarantine_category', $_data['acl'])) ? 1 : 0;
+ $attr['acl_app_passwds'] = (in_array('app_passwds', $_data['acl'])) ? 1 : 0;
+ } else {
+ foreach ($is_now as $key => $value){
+ $attr[$key] = $is_now[$key];
+ }
+ }
+
+
+ // update template
+ $stmt = $pdo->prepare("UPDATE `templates`
+ SET `template` = :template, `attributes` = :attributes
+ WHERE id = :id");
+ $stmt->execute(array(
+ ":id" => $id ,
+ ":template" => $_data["template"] ,
+ ":attributes" => json_encode($attr)
+ ));
+ }
+
+
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => array('template_modified', $_data["template"])
+ );
+ return true;
+ break;
case 'resource':
if (!is_array($_data['name'])) {
$names = array();
@@ -3606,6 +4028,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
`mailboxes`,
`defquota`,
`maxquota`,
+ `created`,
+ `modified`,
`quota`,
`relayhost`,
`relay_all_recipients`,
@@ -3678,6 +4102,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$domaindata['relay_all_recipients_int'] = $row['relay_all_recipients'];
$domaindata['relay_unknown_only'] = $row['relay_unknown_only'];
$domaindata['relay_unknown_only_int'] = $row['relay_unknown_only'];
+ $domaindata['created'] = $row['created'];
+ $domaindata['modified'] = $row['modified'];
$stmt = $pdo->prepare("SELECT COUNT(`address`) AS `alias_count` FROM `alias`
WHERE (`domain`= :domain OR `domain` IN (SELECT `alias_domain` FROM `alias_domain` WHERE `target_domain` = :domain2))
AND `address` NOT IN (
@@ -3711,6 +4137,43 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
return $domaindata;
break;
+ case 'domain_templates':
+ if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
+ return false;
+ }
+ $_data = (isset($_data)) ? intval($_data) : null;
+
+ if (isset($_data)){
+ $stmt = $pdo->prepare("SELECT * FROM `templates`
+ WHERE `id` = :id AND type = :type");
+ $stmt->execute(array(
+ ":id" => $_data,
+ ":type" => "domain"
+ ));
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if (empty($row)){
+ return false;
+ }
+
+ $row["attributes"] = json_decode($row["attributes"], true);
+ return $row;
+ }
+ else {
+ $stmt = $pdo->prepare("SELECT * FROM `templates` WHERE `type` = 'domain'");
+ $stmt->execute();
+ $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+ if (empty($rows)){
+ return false;
+ }
+
+ foreach($rows as $key => $row){
+ $rows[$key]["attributes"] = json_decode($row["attributes"], true);
+ }
+ return $rows;
+ }
+ break;
case 'mailbox_details':
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
return false;
@@ -3725,6 +4188,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
`mailbox`.`domain`,
`mailbox`.`local_part`,
`mailbox`.`quota`,
+ `mailbox`.`created`,
+ `mailbox`.`modified`,
`quota2`.`bytes`,
`attributes`,
`quota2`.`messages`
@@ -3743,6 +4208,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
`mailbox`.`domain`,
`mailbox`.`local_part`,
`mailbox`.`quota`,
+ `mailbox`.`created`,
+ `mailbox`.`modified`,
`quota2replica`.`bytes`,
`attributes`,
`quota2replica`.`messages`
@@ -3769,6 +4236,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$mailboxdata['attributes'] = json_decode($row['attributes'], true);
$mailboxdata['quota_used'] = intval($row['bytes']);
$mailboxdata['percent_in_use'] = ($row['quota'] == 0) ? '- ' : round((intval($row['bytes']) / intval($row['quota'])) * 100);
+ $mailboxdata['created'] = $row['created'];
+ $mailboxdata['modified'] = $row['modified'];
if ($mailboxdata['percent_in_use'] === '- ') {
$mailboxdata['percent_class'] = "info";
@@ -3856,6 +4325,43 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
return $mailboxdata;
break;
+ case 'mailbox_templates':
+ if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
+ return false;
+ }
+ $_data = (isset($_data)) ? intval($_data) : null;
+
+ if (isset($_data)){
+ $stmt = $pdo->prepare("SELECT * FROM `templates`
+ WHERE `id` = :id AND type = :type");
+ $stmt->execute(array(
+ ":id" => $_data,
+ ":type" => "mailbox"
+ ));
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if (empty($row)){
+ return false;
+ }
+
+ $row["attributes"] = json_decode($row["attributes"], true);
+ return $row;
+ }
+ else {
+ $stmt = $pdo->prepare("SELECT * FROM `templates` WHERE `type` = 'mailbox'");
+ $stmt->execute();
+ $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+ if (empty($rows)){
+ return false;
+ }
+
+ foreach($rows as $key => $row){
+ $rows[$key]["attributes"] = json_decode($row["attributes"], true);
+ }
+ return $rows;
+ }
+ break;
case 'resource_details':
$resourcedata = array();
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
@@ -4224,6 +4730,42 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
);
}
break;
+ case 'domain_templates':
+ if ($_SESSION['mailcow_cc_role'] != "admin") {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
+ if (!is_array($_data['ids'])) {
+ $ids = array();
+ $ids[] = $_data['ids'];
+ }
+ else {
+ $ids = $_data['ids'];
+ }
+
+
+ foreach ($ids as $id) {
+ // delete template
+ $stmt = $pdo->prepare("DELETE FROM `templates`
+ WHERE id = :id AND type = :type AND NOT template = :template");
+ $stmt->execute(array(
+ ":id" => $id,
+ ":type" => "domain",
+ ":template" => "Default"
+ ));
+ }
+
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => 'template_removed'
+ );
+ return true;
+ break;
case 'alias':
if (!is_array($_data['id'])) {
$ids = array();
@@ -4518,6 +5060,42 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
);
}
break;
+ case 'mailbox_templates':
+ if ($_SESSION['mailcow_cc_role'] != "admin") {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
+ if (!is_array($_data['ids'])) {
+ $ids = array();
+ $ids[] = $_data['ids'];
+ }
+ else {
+ $ids = $_data['ids'];
+ }
+
+
+ foreach ($ids as $id) {
+ // delete template
+ $stmt = $pdo->prepare("DELETE FROM `templates`
+ WHERE id = :id AND type = :type AND NOT template = :template");
+ $stmt->execute(array(
+ ":id" => $id,
+ ":type" => "mailbox",
+ ":template" => "Default"
+ ));
+ }
+
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => 'template_removed'
+ );
+ return true;
+ break;
case 'resource':
if (!is_array($_data['name'])) {
$names = array();
diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php
index b47bd5c2..d43c9060 100644
--- a/data/web/inc/init_db.inc.php
+++ b/data/web/inc/init_db.inc.php
@@ -3,7 +3,7 @@ function init_db_schema() {
try {
global $pdo;
- $db_version = "25072022_2300";
+ $db_version = "16112022_1325";
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
@@ -225,6 +225,22 @@ function init_db_schema() {
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
+ "templates" => array(
+ "cols" => array(
+ "id" => "INT NOT NULL AUTO_INCREMENT",
+ "template" => "VARCHAR(255) NOT NULL",
+ "type" => "VARCHAR(255) NOT NULL",
+ "attributes" => "JSON",
+ "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
+ "modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP"
+ ),
+ "keys" => array(
+ "primary" => array(
+ "" => array("id")
+ )
+ ),
+ "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
+ ),
"domain" => array(
// Todo: Move some attributes to json
"cols" => array(
@@ -1292,6 +1308,95 @@ function init_db_schema() {
// Fix domain_admins
$pdo->query("DELETE FROM `domain_admins` WHERE `domain` = 'ALL';");
+ // add default templates
+ $default_domain_template = array(
+ "template" => "Default",
+ "type" => "domain",
+ "attributes" => array(
+ "tags" => array(),
+ "max_num_aliases_for_domain" => 400,
+ "max_num_mboxes_for_domain" => 10,
+ "def_quota_for_mbox" => 3072 * 1048576,
+ "max_quota_for_mbox" => 10240 * 1048576,
+ "max_quota_for_domain" => 10240 * 1048576,
+ "rl_frame" => "s",
+ "rl_value" => "",
+ "active" => 1,
+ "gal" => 1,
+ "backupmx" => 0,
+ "relay_all_recipients" => 0,
+ "relay_unknown_only" => 0,
+ "dkim_selector" => "dkim",
+ "key_size" => 2048,
+ "max_quota_for_domain" => 10240 * 1048576,
+ )
+ );
+ $default_mailbox_template = array(
+ "template" => "Default",
+ "type" => "mailbox",
+ "attributes" => array(
+ "tags" => array(),
+ "quota" => 0,
+ "quarantine_notification" => strval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['quarantine_notification']),
+ "quarantine_category" => strval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['quarantine_category']),
+ "rl_frame" => "s",
+ "rl_value" => "",
+ "force_pw_update" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['force_pw_update']),
+ "sogo_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['sogo_access']),
+ "active" => 1,
+ "tls_enforce_in" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['tls_enforce_in']),
+ "tls_enforce_out" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['tls_enforce_out']),
+ "imap_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['imap_access']),
+ "pop3_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['pop3_access']),
+ "smtp_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['smtp_access']),
+ "sieve_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['sieve_access']),
+ "acl_spam_alias" => 1,
+ "acl_tls_policy" => 1,
+ "acl_spam_score" => 1,
+ "acl_spam_policy" => 1,
+ "acl_delimiter_action" => 1,
+ "acl_syncjobs" => 0,
+ "acl_eas_reset" => 1,
+ "acl_sogo_profile_reset" => 0,
+ "acl_pushover" => 1,
+ "acl_quarantine" => 1,
+ "acl_quarantine_attachments" => 1,
+ "acl_quarantine_notification" => 1,
+ "acl_quarantine_category" => 1,
+ "acl_app_passwds" => 1,
+ )
+ );
+ $stmt = $pdo->prepare("SELECT id FROM `templates` WHERE `type` = :type AND `template` = :template");
+ $stmt->execute(array(
+ ":type" => "domain",
+ ":template" => $default_domain_template["template"]
+ ));
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ if (empty($row)){
+ $stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`)
+ VALUES (:type, :template, :attributes)");
+ $stmt->execute(array(
+ ":type" => "domain",
+ ":template" => $default_domain_template["template"],
+ ":attributes" => json_encode($default_domain_template["attributes"])
+ ));
+ }
+ $stmt = $pdo->prepare("SELECT id FROM `templates` WHERE `type` = :type AND `template` = :template");
+ $stmt->execute(array(
+ ":type" => "mailbox",
+ ":template" => $default_mailbox_template["template"]
+ ));
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+ if (empty($row)){
+ $stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`)
+ VALUES (:type, :template, :attributes)");
+ $stmt->execute(array(
+ ":type" => "mailbox",
+ ":template" => $default_mailbox_template["template"],
+ ":attributes" => json_encode($default_mailbox_template["attributes"])
+ ));
+ }
+
if (php_sapi_name() == "cli") {
echo "DB initialization completed" . PHP_EOL;
} else {
diff --git a/data/web/js/build/014-mailcow.js b/data/web/js/build/014-mailcow.js
index a2e25547..13bc2911 100644
--- a/data/web/js/build/014-mailcow.js
+++ b/data/web/js/build/014-mailcow.js
@@ -289,37 +289,6 @@ $(document).ready(function() {
addTag(this);
}
});
- function addTag(tagAddElem){
- var tagboxElem = $(tagAddElem).parent();
- var tagInputElem = $(tagboxElem).find(".tag-input")[0];
- var tagValuesElem = $(tagboxElem).find(".tag-values")[0];
-
- var tag = escapeHtml($(tagInputElem).val());
- if (!tag) return;
- var value_tags = [];
- try {
- value_tags = JSON.parse($(tagValuesElem).val());
- } catch {}
- if (!Array.isArray(value_tags)) value_tags = [];
- if (value_tags.includes(tag)) return;
-
- $(' ' + tag + '').insertBefore('.tag-input').click(function(){
- var del_tag = unescapeHtml($(this).text());
- var del_tags = [];
- try {
- del_tags = JSON.parse($(tagValuesElem).val());
- } catch {}
- if (Array.isArray(del_tags)){
- del_tags.splice(del_tags.indexOf(del_tag), 1);
- $(tagValuesElem).val(JSON.stringify(del_tags));
- }
- $(this).remove();
- });
-
- value_tags.push($(tagInputElem).val());
- $(tagValuesElem).val(JSON.stringify(value_tags));
- $(tagInputElem).val('');
- }
// Dark Mode Loader
$('#dark-mode-toggle').click(toggleDarkMode);
@@ -343,68 +312,42 @@ $(document).ready(function() {
localStorage.setItem('darkmode', 'true');
}
}
-
- // show whats new modal
- if (mailcow_cc_role === "admin" || mailcow_cc_role === "domainadmin"){
- if (mailcow_info.updatedAt > last_login){
- var parsedSeenTimestamp = parseInt(localStorage.getItem("seenChangelog"));
- if (!isNaN(parsedSeenTimestamp) && mailcow_info.updatedAt < parsedSeenTimestamp) {
- console.log("changelog seen");
- return;
- }
- $.ajax({
- type: 'GET',
- url: 'https://api.github.com/repos/' + mailcow_info.project_owner + '/' + mailcow_info.project_repo + '/releases/tags/' + mailcow_info.version_tag,
- dataType: 'json',
- success: function (data) {
- var md = window.markdownit();
- var result = md.render(data.body);
- result = parseGithubMarkdownLinks(result);
-
- $('#showWhatsNewModal').find(".modal-body").html(`
-
` + data.name + `
- ` + result + `
- `);
-
- localStorage.setItem("seenChangelog", Math.floor(Date.now() / 1000).toString());
- }
- });
-
- new bootstrap.Modal(document.getElementById("showWhatsNewModal"), {
- backdrop: 'static',
- keyboard: false
- }).show();
- }
- }
-
- function parseGithubMarkdownLinks(inputText) {
- var replacedText, replacePattern1;
-
- replacePattern1 = /(\b(https?):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
- replacedText = inputText.replace(replacePattern1, (matched, index, original, input_string) => {
- if (matched.includes('github.com')){
- // return short link if it's github link
- last_uri_path = matched.split('/');
- last_uri_path = last_uri_path[last_uri_path.length - 1];
-
- // adjust Full Changelog link to match last git version and new git version, if link is a compare link
- if (matched.includes('/compare/') && mailcow_info.last_version_tag !== ''){
- matched = matched.replace(last_uri_path, mailcow_info.last_version_tag + '...' + mailcow_info.version_tag);
- last_uri_path = mailcow_info.last_version_tag + '...' + mailcow_info.version_tag;
- }
-
- return '' + last_uri_path + '
';
- };
-
- // if it's not a github link, return complete link
- return '' + matched + '';
- });
-
- return replacedText;
- }
});
// https://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
function escapeHtml(n){var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="}; return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})}
function unescapeHtml(t){var n={"&":"&","<":"<",">":">",""":'"',"'":"'","/":"/","`":"`","=":"="};return String(t).replace(/&|<|>|"|'|/|`|=/g,function(t){return n[t]})}
+
+function addTag(tagAddElem, tag = null){
+ var tagboxElem = $(tagAddElem).parent();
+ var tagInputElem = $(tagboxElem).find(".tag-input")[0];
+ var tagValuesElem = $(tagboxElem).find(".tag-values")[0];
+
+ if (!tag)
+ tag = $(tagInputElem).val();
+ if (!tag) return;
+ var value_tags = [];
+ try {
+ value_tags = JSON.parse($(tagValuesElem).val());
+ } catch {}
+ if (!Array.isArray(value_tags)) value_tags = [];
+ if (value_tags.includes(tag)) return;
+
+ $(' ' + escapeHtml(tag) + '').insertBefore('.tag-input').click(function(){
+ var del_tag = unescapeHtml($(this).text());
+ var del_tags = [];
+ try {
+ del_tags = JSON.parse($(tagValuesElem).val());
+ } catch {}
+ if (Array.isArray(del_tags)){
+ del_tags.splice(del_tags.indexOf(del_tag), 1);
+ $(tagValuesElem).val(JSON.stringify(del_tags));
+ }
+ $(this).remove();
+ });
+
+ value_tags.push(tag);
+ $(tagValuesElem).val(JSON.stringify(value_tags));
+ $(tagInputElem).val('');
+}
\ No newline at end of file
diff --git a/data/web/js/site/debug.js b/data/web/js/site/debug.js
index dcc04210..b57f1dbc 100644
--- a/data/web/js/site/debug.js
+++ b/data/web/js/site/debug.js
@@ -47,6 +47,12 @@ $(document).ready(function() {
if (mailcow_info.branch === "master"){
check_update(mailcow_info.version_tag, mailcow_info.project_url);
}
+ $("#maiclow_version").click(function(){
+ if (mailcow_cc_role !== "admin" && mailcow_cc_role !== "domainadmin")
+ return;
+
+ showVersionModal("Version " + mailcow_info.version_tag, mailcow_info.version_tag);
+ })
// get public ips
get_public_ips();
update_container_stats();
@@ -1227,11 +1233,11 @@ function get_public_ips(){
}).then(function(data) {
console.log(data);
- if (data){
- // display host ips
+ // display host ips
+ if (data.ipv4)
$("#host_ipv4").text(data.ipv4);
+ if (data.ipv6)
$("#host_ipv6").text(data.ipv6);
- }
});
}
// format hosts uptime seconds to readable string
@@ -1452,10 +1458,13 @@ function check_update(current_version, github_repo_url){
} else {
// update available
$("#mailcow_update").removeClass("text-danger text-success").addClass("text-warning");
- $("#mailcow_update").html(
- `` + lang_debug.update_available + `
- `+latest_data.tag_name+``
- );
+ $("#mailcow_update").html(lang_debug.update_available + ` `+latest_data.tag_name+``);
+ $("#mailcow_update_changelog").click(function(){
+ if (mailcow_cc_role !== "admin" && mailcow_cc_role !== "domainadmin")
+ return;
+
+ showVersionModal("New Release " + latest_data.tag_name, latest_data.tag_name);
+ })
}
}).catch(err => {
// err
@@ -1470,3 +1479,55 @@ function check_update(current_version, github_repo_url){
$("#mailcow_update").html(""+ lang_debug.update_failed +"");
});
}
+// show version changelog modal
+function showVersionModal(title, version){
+ $.ajax({
+ type: 'GET',
+ url: 'https://api.github.com/repos/' + mailcow_info.project_owner + '/' + mailcow_info.project_repo + '/releases/tags/' + version,
+ dataType: 'json',
+ success: function (data) {
+ var md = window.markdownit();
+ var result = md.render(data.body);
+ result = parseGithubMarkdownLinks(result);
+
+ $('#showVersionModal').find(".modal-title").html(title);
+ $('#showVersionModal').find(".modal-body").html(`
+ ` + data.name + `
+ ` + result + `
+ Github Link:
+ ` + version + `
+
+ `);
+
+ new bootstrap.Modal(document.getElementById("showVersionModal"), {
+ backdrop: 'static',
+ keyboard: false
+ }).show();
+ }
+ });
+}
+function parseGithubMarkdownLinks(inputText) {
+ var replacedText, replacePattern1;
+
+ replacePattern1 = /(\b(https?):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
+ replacedText = inputText.replace(replacePattern1, (matched, index, original, input_string) => {
+ if (matched.includes('github.com')){
+ // return short link if it's github link
+ last_uri_path = matched.split('/');
+ last_uri_path = last_uri_path[last_uri_path.length - 1];
+
+ // adjust Full Changelog link to match last git version and new git version, if link is a compare link
+ if (matched.includes('/compare/') && mailcow_info.last_version_tag !== ''){
+ matched = matched.replace(last_uri_path, mailcow_info.last_version_tag + '...' + mailcow_info.version_tag);
+ last_uri_path = mailcow_info.last_version_tag + '...' + mailcow_info.version_tag;
+ }
+
+ return '' + last_uri_path + '
';
+ };
+
+ // if it's not a github link, return complete link
+ return '' + matched + '';
+ });
+
+ return replacedText;
+}
\ No newline at end of file
diff --git a/data/web/js/site/edit.js b/data/web/js/site/edit.js
index 31b9d08b..55a8e6b4 100644
--- a/data/web/js/site/edit.js
+++ b/data/web/js/site/edit.js
@@ -57,6 +57,17 @@ $(document).ready(function() {
$("#multiple_bookings_custom").bind("change keypress keyup blur", function() {
$('input[name=multiple_bookings]').val($("#multiple_bookings_custom").val());
});
+
+ // load tags
+ if ($('#tags').length){
+ var tagsEl = $('#tags').parent().find('.tag-values')[0];
+ console.log($(tagsEl).val())
+ var tags = JSON.parse($(tagsEl).val());
+ $(tagsEl).val("");
+
+ for (var i = 0; i < tags.length; i++)
+ addTag($('#tags'), tags[i]);
+ }
});
jQuery(function($){
diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js
index 77da5029..8c98e922 100644
--- a/data/web/js/site/mailbox.js
+++ b/data/web/js/site/mailbox.js
@@ -77,6 +77,90 @@ $(document).ready(function() {
$('.dns-modal-body').html(xhr.responseText);
}
});
+ });
+ // @Open Domain add modal
+ $('#addDomainModal').on('show.bs.modal', function(e) {
+ $.ajax({
+ url: '/api/v1/get/domain/template/all',
+ data: {},
+ dataType: 'json',
+ success: async function(data){
+ $('#domain_templates').find('option').remove();
+ $('#domain_templates').selectpicker('destroy');
+ $('#domain_templates').selectpicker();
+ for (var i = 0; i < data.length; i++){
+ if (data[i].template === "Default"){
+ $('#domain_templates').prepend($('