diff --git a/data/web/edit.php b/data/web/edit.php index 185e7934b..09db796d3 100644 --- a/data/web/edit.php +++ b/data/web/edit.php @@ -39,17 +39,7 @@ if (isset($_SESSION['mailcow_cc_role'])) { $template_data = ['admin' => $admin]; } elseif (isset($_GET['domain'])) { - if ($_GET['domain'] == "defaults") { - // edit domain default settings - //$result = mailbox('get', 'domain_defaults'); - //$rl = ratelimit('get', 'domain_defaults'); - $result = true; - $template = 'edit/domain-defaults.twig'; - $template_data = [ - // 'rl' => $rl, - ]; - } - elseif (is_valid_domain_name($_GET["domain"]) && + if (is_valid_domain_name($_GET["domain"]) && !empty($_GET["domain"])) { // edit domain $domain = $_GET["domain"]; @@ -69,6 +59,26 @@ if (isset($_SESSION['mailcow_cc_role'])) { ]; } } + elseif (isset($_GET["template"])){ + $domain_template = mailbox('get', 'domain_templates', $_GET["template"]); + if ($domain_template){ + $template_data = [ + '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"]) && !empty($_GET["oauth2client"])) { @@ -92,17 +102,7 @@ if (isset($_SESSION['mailcow_cc_role'])) { ]; } elseif (isset($_GET['mailbox'])){ - if ($_GET['mailbox'] == "defaults"){ - // edit mailbox default settings - // $result = mailbox('get', 'mailbox_defaults'); - // $rl = ratelimit('get', 'mailbox_defaults'); - $result = true; - $template = 'edit/mailbox-defaults.twig'; - $template_data = [ - // 'rl' => $rl, - ]; - } - elseif(filter_var(html_entity_decode(rawurldecode($_GET["mailbox"])), FILTER_VALIDATE_EMAIL) && !empty($_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); diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 2cf9f6c65..b30a4a974 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(); @@ -3711,6 +4133,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; @@ -3856,6 +4315,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 +4720,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 +5050,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 b47bd5c23..1dc39b541 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 = "10112022_1146"; $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,89 @@ 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("INSERT INTO `templates` (`type`, `template`, `attributes`) + SELECT :type, :template, :attributes FROM `templates` + WHERE NOT EXISTS ( + SELECT `template` FROM `templates` WHERE `template` = :template2 AND `type` = :type2 + ) LIMIT 1;"); + $stmt->execute(array( + ":type" => "domain", + ":type2" => "domain", + ":template" => $default_domain_template["template"], + ":template2" => $default_mailbox_template["template"], + ":attributes" => json_encode($default_domain_template["attributes"]) + )); + $stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`) + SELECT :type, :template, :attributes FROM `templates` + WHERE NOT EXISTS ( + SELECT `template` FROM `templates` WHERE `template` = :template2 AND `type` = :type2 + ) LIMIT 1;"); + $stmt->execute(array( + ":type" => "mailbox", + ":type2" => "mailbox", + ":template" => $default_mailbox_template["template"], + ":template2" => $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 a2e255476..a211643a1 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); @@ -367,13 +336,14 @@ $(document).ready(function() { `); localStorage.setItem("seenChangelog", Math.floor(Date.now() / 1000).toString()); + + new bootstrap.Modal(document.getElementById("showWhatsNewModal"), { + backdrop: 'static', + keyboard: false + }).show(); } }); - new bootstrap.Modal(document.getElementById("showWhatsNewModal"), { - backdrop: 'static', - keyboard: false - }).show(); } } @@ -408,3 +378,36 @@ $(document).ready(function() { // 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/edit.js b/data/web/js/site/edit.js index 31b9d08ba..55a8e6b40 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 77da5029d..275b977ff 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($('