Better log table, some MySQL to Redis migrations, API changes, other minor changes...

master
andryyy 2017-05-08 15:41:05 +02:00
parent 2e6fdba2b6
commit f77c40a179
7 changed files with 122 additions and 110 deletions

View File

@ -1327,7 +1327,7 @@ function edit_delimiter_action($postarray) {
// Array items
// 'username' can be set, defaults to mailcow_cc_username
global $lang;
global $pdo;
global $redis;
if (isset($postarray['username']) && filter_var($postarray['username'], FILTER_VALIDATE_EMAIL)) {
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $postarray['username'])) {
$_SESSION['return'] = array(
@ -1343,7 +1343,6 @@ function edit_delimiter_action($postarray) {
else {
$username = $_SESSION['mailcow_cc_username'];
}
($postarray['tagged_mail_handler'] == "subject") ? $wants_tagged_subject = '1' : $wants_tagged_subject = '0';
if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
$_SESSION['return'] = array(
'type' => 'danger',
@ -1351,18 +1350,30 @@ function edit_delimiter_action($postarray) {
);
return false;
}
if (isset($postarray['tagged_mail_handler']) && $postarray['tagged_mail_handler'] == "subject") {
try {
$stmt = $pdo->prepare("UPDATE `mailbox` SET `wants_tagged_subject` = :wants_tagged_subject WHERE `username` = :username");
$stmt->execute(array(':username' => $username, ':wants_tagged_subject' => $wants_tagged_subject));
$SelectData = $stmt->fetch(PDO::FETCH_ASSOC);
$redis->hSet('RCPT_WANTS_SUBJECT_TAG', $username, 1);
}
catch(PDOException $e) {
catch (RedisException $e) {
$_SESSION['return'] = array(
'type' => 'danger',
'msg' => 'MySQL: '.$e
'msg' => 'Redis: '.$e
);
return false;
}
}
else {
try {
$redis->hDel('RCPT_WANTS_SUBJECT_TAG', $username);
}
catch (RedisException $e) {
$_SESSION['return'] = array(
'type' => 'danger',
'msg' => 'Redis: '.$e
);
return false;
}
}
$_SESSION['return'] = array(
'type' => 'success',
'msg' => sprintf($lang['success']['mailbox_modified'], $username)
@ -1372,7 +1383,7 @@ function edit_delimiter_action($postarray) {
function get_delimiter_action($username = null) {
// 'username' can be set, defaults to mailcow_cc_username
global $lang;
global $pdo;
global $redis;
$data = array();
if (isset($username) && filter_var($username, FILTER_VALIDATE_EMAIL)) {
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
@ -1383,18 +1394,20 @@ function get_delimiter_action($username = null) {
$username = $_SESSION['mailcow_cc_username'];
}
try {
$stmt = $pdo->prepare("SELECT `wants_tagged_subject` FROM `mailbox` WHERE `username` = :username");
$stmt->execute(array(':username' => $username));
$data = $stmt->fetch(PDO::FETCH_ASSOC);
if ($redis->hGet('RCPT_WANTS_SUBJECT_TAG', $username)) {
return "subject";
}
catch(PDOException $e) {
else {
return "subfolder";
}
}
catch (RedisException $e) {
$_SESSION['return'] = array(
'type' => 'danger',
'msg' => 'MySQL: '.$e
'msg' => 'Redis: '.$e
);
return false;
}
return $data;
}
function user_get_alias_details($username) {
global $lang;
@ -2413,13 +2426,31 @@ function dkim_add_key($postarray) {
), 1, -1)
);
// Save public key and selector to redis
try {
$redis->hSet('DKIM_PUB_KEYS', $domain, $pubKey);
$redis->hSet('DKIM_SELECTORS', $domain, $dkim_selector);
}
catch (RedisException $e) {
$_SESSION['return'] = array(
'type' => 'danger',
'msg' => 'Redis: '.$e
);
return false;
}
// Export private key and save private key to redis
openssl_pkey_export($keypair_ressource, $privKey);
if (isset($privKey) && !empty($privKey)) {
try {
$redis->hSet('DKIM_PRIV_KEYS', $dkim_selector . '.' . $domain, trim($privKey));
}
catch (RedisException $e) {
$_SESSION['return'] = array(
'type' => 'danger',
'msg' => 'Redis: '.$e
);
return false;
}
}
$_SESSION['return'] = array(
'type' => 'success',
'msg' => sprintf($lang['success']['dkim_added'])
@ -2438,18 +2469,7 @@ function dkim_get_key_details($domain) {
$data = array();
global $redis;
if (hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
$dkim_pubkey_file = escapeshellarg($GLOBALS["MC_DKIM_TXTS"]. "/" . $domain . "." . "dkim");
if (file_exists(substr($dkim_pubkey_file, 1, -1))) {
$data['pubkey'] = file_get_contents($GLOBALS["MC_DKIM_TXTS"]. "/" . $domain . "." . "dkim");
$data['length'] = (strlen($data['pubkey']) < 391) ? 1024 : 2048;
$data['dkim_txt'] = 'v=DKIM1;k=rsa;t=s;s=email;p=' . file_get_contents($GLOBALS["MC_DKIM_TXTS"]. "/" . $domain . "." . "dkim");
$data['dkim_selector'] = 'dkim';
// Migrate key to redis
$redis->hSet('DKIM_PRIV_KEYS', $data['dkim_selector'] . '.' . $domain, trim(file_get_contents($GLOBALS["MC_DKIM_KEYS"]. "/" . $domain . "." . "dkim")));
$redis->hSet('DKIM_PUB_KEYS', $domain, $data['pubkey']);
$redis->hSet('DKIM_SELECTORS', $domain, 'dkim');
}
elseif ($redis_dkim_key_data = $redis->hGet('DKIM_PUB_KEYS', $domain)) {
if ($redis_dkim_key_data = $redis->hGet('DKIM_PUB_KEYS', $domain)) {
$data['pubkey'] = $redis_dkim_key_data;
$data['length'] = (strlen($data['pubkey']) < 391) ? 1024 : 2048;
$data['dkim_txt'] = 'v=DKIM1;k=rsa;t=s;s=email;p=' . $redis_dkim_key_data;
@ -2469,11 +2489,6 @@ function dkim_get_blind_keys() {
return false;
}
$domains = array();
$dnstxt_folder = scandir($GLOBALS["MC_DKIM_TXTS"]);
$dnstxt_files = array_diff($dnstxt_folder, array('.', '..'));
foreach($dnstxt_files as $file) {
$domains[] = substr($file, 0, -5);
}
foreach ($redis->hKeys('DKIM_PUB_KEYS') as $redis_dkim_domain) {
$domains[] = $redis_dkim_domain;
}
@ -2491,13 +2506,6 @@ function dkim_delete_key($postarray) {
);
return false;
}
// if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
// $_SESSION['return'] = array(
// 'type' => 'danger',
// 'msg' => sprintf($lang['danger']['access_denied'])
// );
// return false;
// }
if (!is_valid_domain_name($domain)) {
$_SESSION['return'] = array(
'type' => 'danger',
@ -2505,41 +2513,20 @@ function dkim_delete_key($postarray) {
);
return false;
}
foreach (array('DKIM_PUB_KEYS', 'DKIM_SELECTORS',) as $hash) {
if (!$redis->hDel($hash, $domain)) {
$_SESSION['return'] = array(
'type' => 'danger',
'msg' => sprintf($lang['danger']['dkim_remove_failed'])
);
return false;
try {
foreach ($redis->hGetAll('DKIM_PRIV_KEYS') as $key => $value) {
if (preg_match('/\.' . $domain . '$/i', $key)) {
$redis->hDel('DKIM_PUB_KEYS', $key);
}
}
if (!empty($key_details = dkim_get_key_details($domain))) {
if (!$redis->hDel($hash . $key_details['dkim_selector'], $domain)) {
$_SESSION['return'] = array(
'type' => 'danger',
'msg' => sprintf($lang['danger']['dkim_remove_failed'])
);
return false;
}
}
$redis->hDel('DKIM_PUB_KEYS', $domain);
$redis->hDel('DKIM_PRIV_KEYS', $domain);
$redis->hDel('DKIM_SELECTORS', $domain);
exec('rm -f ' . escapeshellarg($GLOBALS['MC_DKIM_TXTS'] . '/' . $domain . '.dkim'), $out, $return);
if ($return != "0") {
$_SESSION['return'] = array(
'type' => 'danger',
'msg' => sprintf($lang['danger']['dkim_remove_failed'])
);
return false;
$redis->hDel('DKIM_PRIV_KEYS', $domain);
}
exec('rm -f ' . escapeshellarg($GLOBALS['MC_DKIM_KEYS'] . '/' . $domain . '.dkim'), $out, $return);
if ($return != "0") {
catch (RedisException $e) {
$_SESSION['return'] = array(
'type' => 'danger',
'msg' => sprintf($lang['danger']['dkim_remove_failed'])
'msg' => 'Redis: '.$e
);
return false;
}
@ -2654,6 +2641,16 @@ function mailbox_add_domain($postarray) {
':active' => $active,
':relay_all_recipients' => $relay_all_recipients
));
try {
$redis->hSet('DOMAIN_MAP', $domain, 1);
}
catch (RedisException $e) {
$_SESSION['return'] = array(
'type' => 'danger',
'msg' => 'Redis: '.$e
);
return false;
}
$_SESSION['return'] = array(
'type' => 'success',
'msg' => sprintf($lang['success']['domain_added'], htmlspecialchars($domain))
@ -4646,6 +4643,16 @@ function mailbox_delete_domain($postarray) {
);
return false;
}
try {
$redis->hDel('DOMAIN_MAP', $domain);
}
catch (RedisException $e) {
$_SESSION['return'] = array(
'type' => 'danger',
'msg' => 'Redis: '.$e
);
return false;
}
$_SESSION['return'] = array(
'type' => 'success',
'msg' => sprintf($lang['success']['domain_removed'], htmlspecialchars($domain))

View File

@ -42,8 +42,6 @@ return array(
"jsUrl" => get_trusted_hostname(),
"tokenLength" => 10,
"secureCookie" => false,
"disabledJavascriptMessage" => "This site attempts to protect users against <a href=\"https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29\">
Cross-Site Request Forgeries </a> attacks. In order to do so, you must have JavaScript enabled in your web browser otherwise this site will fail to work correctly for you.
See details of your web browser for how to enable JavaScript.",
"disabledJavascriptMessage" => "",
"verifyGetFor" => array()
);

View File

@ -1,16 +1,16 @@
<?php
require_once 'inc/sessions.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/sessions.inc.php';
require_once 'inc/vars.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/vars.inc.php';
if (file_exists('./inc/vars.local.inc.php')) {
include_once 'inc/vars.local.inc.php';
}
// Yubi OTP API
require_once 'inc/lib/Yubico.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/Yubico.php';
// Autoload composer
require_once 'inc/lib/vendor/autoload.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/vendor/autoload.php';
// U2F API + T/HOTP API
$u2f = new u2flib_server\U2F('https://' . $_SERVER['HTTP_HOST']);
@ -117,9 +117,9 @@ if (isset($_GET['lang'])) {
break;
}
}
require_once 'lang/lang.en.php';
include 'lang/lang.'.$_SESSION['mailcow_locale'].'.php';
require_once 'inc/functions.inc.php';
require_once 'inc/init_db.inc.php';
require_once 'inc/triggers.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/lang/lang.en.php';
include $_SERVER['DOCUMENT_ROOT'] . '/lang/lang.'.$_SESSION['mailcow_locale'].'.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/init_db.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.inc.php';
init_db_schema();

View File

@ -79,17 +79,24 @@ function get_spf_allowed_hosts($domain)
return $hosts;
}
function get_mx_hosts($domain)
{
$hosts = array();
try {
$mx_records = dns_get_record($domain, DNS_MX);
foreach ($mx_records as $mx_record)
{
$new_hosts = get_a_hosts($mx_record['target']);
$hosts = array_unique(array_merge($hosts,$new_hosts), SORT_REGULAR);
}
}
catch (Exception $e) {
if ($e->getMessage() !== 'dns_get_record(): A temporary server error occurred.') {
throw $e;
}
$mx_records = false;
}
return $hosts;
}

View File

@ -4,7 +4,7 @@ $(document).ready(function() {
url: '/api/v1/get/domain-admin/all',
jsonp: false,
error: function () {
alert('Cannot draw domain administrator table');
console.log('Cannot draw domain admin table');
},
success: function (data) {
$.each(data, function (i, item) {
@ -53,7 +53,7 @@ $(document).ready(function() {
url: '/api/v1/get/logs/dovecot/1000',
jsonp: false,
error: function () {
alert('Cannot draw dovecot log table');
console.log('Cannot draw dovecot log table');
},
success: function (data) {
$.each(data, function (i, item) {
@ -109,7 +109,7 @@ $(document).ready(function() {
url: '/api/v1/get/logs/postfix/1000',
jsonp: false,
error: function () {
alert('Cannot draw postfix log table');
console.log('Cannot draw postfix log table');
},
success: function (data) {
$.each(data, function (i, item) {
@ -128,7 +128,7 @@ $(document).ready(function() {
});
ft_postfix_logs = FooTable.init("#postfix_log", {
"columns": [
{"name":"time","formatter":function unix_time_format(tm) {var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
{"name":"time","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
{"name":"priority","title":lang.priority,"style":{"width":"80px"}},
{"name":"message","title":lang.message},
],

View File

@ -61,7 +61,7 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
case "logs":
switch ($object) {
case "dovecot":
if (isset($extra) && !empty($extra) && is_int($extra)) {
if (isset($extra) && !empty($extra)) {
$extra = intval($extra);
$logs = get_logs('dovecot-mailcow', $extra);
}
@ -77,7 +77,7 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
break;
case "postfix":
if (isset($extra) && !empty($extra) && is_int($extra)) {
if (isset($extra) && !empty($extra)) {
$extra = intval($extra);
$logs = get_logs('postfix-mailcow', $extra);
}

View File

@ -125,14 +125,14 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
<hr>
<?php // Show tagging options ?>
<form class="form-horizontal" role="form" method="post">
<?php $get_tagging_options = get_delimiter_action()['wants_tagged_subject'];?>
<?php $get_tagging_options = get_delimiter_action();?>
<div class="row">
<div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['tag_handling'];?>:</div>
<div class="col-md-9 col-xs-7">
<input type="hidden" name="edit_delimiter_action" value="1">
<select name="tagged_mail_handler" class="selectpicker" onchange="this.form.submit()">
<option value="subfolder" <?=($get_tagging_options == "0") ? 'selected' : null; ?>><?=$lang['user']['tag_in_subfolder'];?></option>
<option value="subject" <?=($get_tagging_options == "1") ? 'selected' : null; ?>><?=$lang['user']['tag_in_subject'];?></option>
<option value="subfolder" <?=($get_tagging_options == "subfolder") ? 'selected' : null; ?>><?=$lang['user']['tag_in_subfolder'];?></option>
<option value="subject" <?=($get_tagging_options == "subject") ? 'selected' : null; ?>><?=$lang['user']['tag_in_subject'];?></option>
</select>
<p class="help-block"><?=$lang['user']['tag_help_explain'];?></p>
<p class="help-block"><?=$lang['user']['tag_help_example'];?></p>