From 66ae588445af7db7d7cd274b7c82d38a935e9fa4 Mon Sep 17 00:00:00 2001 From: andryyy Date: Fri, 18 Aug 2017 22:18:14 +0200 Subject: [PATCH] [Web] Started work on ACL, fix notifications --- data/web/inc/footer.inc.php | 3 +- data/web/inc/functions.inc.php | 17 ++++++ data/web/inc/functions.mailbox.inc.php | 74 ++++++++++++++++++++++++++ data/web/inc/functions.policy.inc.php | 15 +++++- data/web/inc/init_db.inc.php | 63 +++++++++++++++++++++- data/web/inc/prerequisites.inc.php | 3 ++ data/web/js/user.js | 38 +++++++++---- data/web/user.php | 62 ++++++++++++++++++--- 8 files changed, 254 insertions(+), 21 deletions(-) diff --git a/data/web/inc/footer.inc.php b/data/web/inc/footer.inc.php index 8daaff79..55a8f88d 100644 --- a/data/web/inc/footer.inc.php +++ b/data/web/inc/footer.inc.php @@ -18,7 +18,8 @@ function setLang(sel) { $(document).ready(function() { function mailcow_alert_box(message, type) { - $.notify({message: message},{type: type,placement: {from: "bottom",align: "right"},animate: {enter: 'animated fadeInUp',exit: 'animated fadeOutDown'}}); + msg = $('').html(message).text(); + $.notify({message: msg},{type: type,placement: {from: "bottom",align: "right"},animate: {enter: 'animated fadeInUp',exit: 'animated fadeOutDown'}}); } mailcow_alert_box("", ""); diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index dee9cf41..00fb1b4e 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -218,6 +218,23 @@ function check_login($user, $pass) { } sleep($_SESSION['ldelay']); } +function set_acl() { + global $pdo; + if (!isset($_SESSION['mailcow_cc_username'])) { + return false; + } + $username = strtolower(trim($_SESSION['mailcow_cc_username'])); + $stmt = $pdo->prepare("SELECT * FROM `user_acl` WHERE `username` = :username"); + $stmt->execute(array(':username' => $username)); + $acl['acl'] = $stmt->fetch(PDO::FETCH_ASSOC); + unset($acl['acl']['username']); + if (!empty($acl)) { + $_SESSION = array_merge($_SESSION, $acl); + } + else { + return false; + } +} function formatBytes($size, $precision = 2) { if(!is_numeric($size)) { return "0"; diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index af46b6dc..7769e0d3 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -7,6 +7,13 @@ function mailbox($_action, $_type, $_data = null) { case 'add': switch ($_type) { case 'time_limited_alias': + if (!isset($_SESSION['acl']['spam_alias']) || $_SESSION['acl']['spam_alias'] != "1" ) { + $_SESSION['return'] = array( + 'type' => 'danger', + 'msg' => sprintf($lang['danger']['access_denied']) + ); + return false; + } if (isset($_data['username']) && filter_var($_data['username'], FILTER_VALIDATE_EMAIL)) { if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data['username'])) { $_SESSION['return'] = array( @@ -66,6 +73,13 @@ function mailbox($_action, $_type, $_data = null) { ); break; case 'syncjob': + if (!isset($_SESSION['acl']['syncjobs']) || $_SESSION['acl']['syncjobs'] != "1" ) { + $_SESSION['return'] = array( + 'type' => 'danger', + 'msg' => sprintf($lang['danger']['access_denied']) + ); + return false; + } if (isset($_data['username']) && filter_var($_data['username'], FILTER_VALIDATE_EMAIL)) { if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data['username'])) { $_SESSION['return'] = array( @@ -743,6 +757,10 @@ function mailbox($_action, $_type, $_data = null) { ':domain' => $domain, ':active' => $active )); + $stmt = $pdo->prepare("INSERT INTO `user_acl` (`username`) VALUES (:username)"); + $stmt->execute(array( + ':username' => $username + )); $_SESSION['return'] = array( 'type' => 'success', 'msg' => sprintf($lang['success']['mailbox_added'], htmlspecialchars($username)) @@ -949,6 +967,13 @@ function mailbox($_action, $_type, $_data = null) { else { $usernames = $_data['username']; } + if (!isset($_SESSION['acl']['tls_policy']) || $_SESSION['acl']['tls_policy'] != "1" ) { + $_SESSION['return'] = array( + 'type' => 'danger', + 'msg' => sprintf($lang['danger']['access_denied']) + ); + return false; + } foreach ($usernames as $username) { if (!filter_var($username, FILTER_VALIDATE_EMAIL) || !hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) { $_SESSION['return'] = array( @@ -998,6 +1023,13 @@ function mailbox($_action, $_type, $_data = null) { else { $usernames = $_data['username']; } + if (!isset($_SESSION['acl']['spam_score']) || $_SESSION['acl']['spam_score'] != "1" ) { + $_SESSION['return'] = array( + 'type' => 'danger', + 'msg' => sprintf($lang['danger']['access_denied']) + ); + return false; + } foreach ($usernames as $username) { $lowspamlevel = explode(',', $_data['spam_score'])[0]; $highspamlevel = explode(',', $_data['spam_score'])[1]; @@ -1046,6 +1078,13 @@ function mailbox($_action, $_type, $_data = null) { ); break; case 'time_limited_alias': + if (!isset($_SESSION['acl']['spam_alias']) || $_SESSION['acl']['spam_alias'] != "1" ) { + $_SESSION['return'] = array( + 'type' => 'danger', + 'msg' => sprintf($lang['danger']['access_denied']) + ); + return false; + } if (!is_array($_data['address'])) { $addresses = array(); $addresses[] = $_data['address']; @@ -1103,6 +1142,13 @@ function mailbox($_action, $_type, $_data = null) { else { $usernames = $_data['username']; } + if (!isset($_SESSION['acl']['delimiter_action']) || $_SESSION['acl']['delimiter_action'] != "1" ) { + $_SESSION['return'] = array( + 'type' => 'danger', + 'msg' => sprintf($lang['danger']['access_denied']) + ); + return false; + } foreach ($usernames as $username) { if (!filter_var($username, FILTER_VALIDATE_EMAIL) || !hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) { $_SESSION['return'] = array( @@ -1206,6 +1252,13 @@ function mailbox($_action, $_type, $_data = null) { else { $ids = $_data['id']; } + if (!isset($_SESSION['acl']['syncjobs']) || $_SESSION['acl']['syncjobs'] != "1" ) { + $_SESSION['return'] = array( + 'type' => 'danger', + 'msg' => sprintf($lang['danger']['access_denied']) + ); + return false; + } foreach ($ids as $id) { $is_now = mailbox('get', 'syncjob_details', $id); if (!empty($is_now)) { @@ -2677,6 +2730,13 @@ function mailbox($_action, $_type, $_data = null) { else { $ids = $_data['id']; } + if (!isset($_SESSION['acl']['syncjobs']) || $_SESSION['acl']['syncjobs'] != "1" ) { + $_SESSION['return'] = array( + 'type' => 'danger', + 'msg' => sprintf($lang['danger']['access_denied']) + ); + return false; + } foreach ($ids as $id) { if (!is_numeric($id)) { $_SESSION['return'] = array( @@ -2721,6 +2781,13 @@ function mailbox($_action, $_type, $_data = null) { else { $addresses = $_data['address']; } + if (!isset($_SESSION['acl']['spam_alias']) || $_SESSION['acl']['spam_alias'] != "1" ) { + $_SESSION['return'] = array( + 'type' => 'danger', + 'msg' => sprintf($lang['danger']['access_denied']) + ); + return false; + } foreach ($addresses as $address) { try { $stmt = $pdo->prepare("SELECT `goto` FROM `spamalias` WHERE `address` = :address"); @@ -2769,6 +2836,13 @@ function mailbox($_action, $_type, $_data = null) { else { $usernames = $_data['username']; } + if (!isset($_SESSION['acl']['eas_reset']) || $_SESSION['acl']['eas_reset'] != "1" ) { + $_SESSION['return'] = array( + 'type' => 'danger', + 'msg' => sprintf($lang['danger']['access_denied']) + ); + return false; + } foreach ($usernames as $username) { if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) { $_SESSION['return'] = array( diff --git a/data/web/inc/functions.policy.inc.php b/data/web/inc/functions.policy.inc.php index 3070b5dc..2de1c6e2 100644 --- a/data/web/inc/functions.policy.inc.php +++ b/data/web/inc/functions.policy.inc.php @@ -1,5 +1,4 @@ 'danger', + 'msg' => sprintf($lang['danger']['access_denied']) + ); + return false; + } if ($_data['object_list'] == "bl") { $object_list = "blacklist_from"; } @@ -233,6 +239,13 @@ function policy($_action, $_scope, $_data = null) { else { $prefids = $_data['prefid']; } + if (!isset($_SESSION['acl']['spam_policy']) || $_SESSION['acl']['spam_policy'] != "1" ) { + $_SESSION['return'] = array( + 'type' => 'danger', + 'msg' => sprintf($lang['danger']['access_denied']) + ); + return false; + } foreach ($prefids as $prefid) { if (!is_numeric($prefid)) { $_SESSION['return'] = array( diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index 0940ca18..6b1aeec1 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 = "20072107_1029"; + $db_version = "02082017_0938"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -127,6 +127,30 @@ function init_db_schema() { ), "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" ), + "user_acl" => array( + "cols" => array( + "username" => "VARCHAR(255) NOT NULL", + "spam_alias" => "TINYINT(1) NOT NULL DEFAULT '1'", + "tls_policy" => "TINYINT(1) NOT NULL DEFAULT '1'", + "spam_score" => "TINYINT(1) NOT NULL DEFAULT '1'", + "spam_policy" => "TINYINT(1) NOT NULL DEFAULT '1'", + "delimiter_action" => "TINYINT(1) NOT NULL DEFAULT '1'", + "syncjobs" => "TINYINT(1) NOT NULL DEFAULT '1'", + "eas_reset" => "TINYINT(1) NOT NULL DEFAULT '1'", + "eas_autoconfig" => "TINYINT(1) NOT NULL DEFAULT '1'" + ), + "keys" => array( + "fkey" => array( + "fk_username" => array( + "col" => "username", + "ref" => "mailbox.username", + "delete" => "CASCADE", + "update" => "NO ACTION" + ) + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), "alias_domain" => array( "cols" => array( "alias_domain" => "VARCHAR(255) NOT NULL", @@ -511,6 +535,19 @@ function init_db_schema() { $pdo->query("ALTER TABLE `" . $table . "` " . $is_drop . "ADD UNIQUE KEY `" . $key_name . "` (" . $fields . ")"); } } + if (strtolower($key_type) == 'fkey') { + foreach ($key_content as $key_name => $key_values) { + $fields = "`" . implode("`, `", $key_values) . "`"; + $stmt = $pdo->query("SHOW KEYS FROM `" . $table . "` WHERE Key_name = '" . $key_name . "'"); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $pdo->query("ALTER TABLE `" . $table . "` DROP FOREIGN KEY `" . $key_name . "`"); + } + @list($table_ref, $field_ref) = explode('.', $key_values['ref']); + $pdo->query("ALTER TABLE `" . $table . "` ADD FOREIGN KEY `" . $key_name . "` (" . $key_values['col'] . ") REFERENCES `" . $table_ref . "` (`" . $field_ref . "`) + ON DELETE " . $key_values['delete'] . " ON UPDATE " . $key_values['update']); + } + } } // Drop all vanished columns $stmt = $pdo->query("SHOW COLUMNS FROM `" . $table . "`"); @@ -535,10 +572,21 @@ function init_db_schema() { $keys_to_exist[] = $key_name; } } + // Index for foreign key must exist + if (isset($properties['keys']['fkey']) && is_array($properties['keys']['fkey'])) { + foreach ($properties['keys']['fkey'] as $key_name => $key_values) { + $keys_to_exist[] = $key_name; + } + } // Step 2: Drop all vanished indexes while ($row = array_shift($keys_in_table)) { if (!in_array($row['Key_name'], $keys_to_exist)) { - $pdo->query("ALTER TABLE `" . $table . "` DROP INDEX `" . $row['Key_name'] . "`"); + try { + $pdo->query("ALTER TABLE `" . $table . "` DROP FOREIGN KEY `" . $row['Key_name'] . "`"); + } + finally { + $pdo->query("ALTER TABLE `" . $table . "` DROP INDEX `" . $row['Key_name'] . "`"); + } } } // Step 3: Drop all vanished primary keys @@ -575,6 +623,14 @@ function init_db_schema() { $sql .= "UNIQUE KEY `" . $key_name . "` (" . $fields . ")" . ","; } } + elseif (strtolower($key_type) == 'fkey') { + foreach ($key_content as $key_name => $key_values) { + @list($table_ref, $field_ref) = explode('.', $key_values['ref']); + $fields = "`" . implode("`, `", $key_values) . "`"; + $sql .= "FOREIGN KEY `" . $key_name . "` (" . $key_values['col'] . ") REFERENCES `" . $table_ref . "` (`" . $field_ref . "`) + ON DELETE " . $key_values['delete'] . " ON UPDATE " . $key_values['update'] . ","; + } + } } $sql = rtrim($sql, ","); $sql .= ") " . $properties['attr']; @@ -606,6 +662,9 @@ function init_db_schema() { 'type' => 'success', 'msg' => 'Database initialisation completed' ); + + // Fix user_acl + $stmt = $pdo->query("INSERT INTO `user_acl` (`username`) SELECT `username` FROM `mailbox` WHERE `kind` = '' AND NOT EXISTS (SELECT `username` FROM `user_acl`);"); } catch (PDOException $e) { $_SESSION['return'] = array( diff --git a/data/web/inc/prerequisites.inc.php b/data/web/inc/prerequisites.inc.php index e92a91fc..a394943e 100644 --- a/data/web/inc/prerequisites.inc.php +++ b/data/web/inc/prerequisites.inc.php @@ -70,3 +70,6 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.fail2ban.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/init_db.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.inc.php'; init_db_schema(); +if (isset($_SESSION['mailcow_cc_role'])) { + set_acl(); +} \ No newline at end of file diff --git a/data/web/js/user.js b/data/web/js/user.js index e448b5c9..c091ac85 100644 --- a/data/web/js/user.js +++ b/data/web/js/user.js @@ -34,6 +34,8 @@ jQuery(function($){ var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString(); } + acl_data = JSON.parse(acl); + function draw_tla_table() { ft_tla_table = FooTable.init('#tla_table', { "columns": [ @@ -52,10 +54,16 @@ jQuery(function($){ }, success: function (data) { $.each(data, function (i, item) { - item.action = '
' + - ' ' + lang.remove + '' + - '
'; - item.chkbox = ''; + if (acl_data.spam_alias === 1) { + item.action = '
' + + ' ' + lang.remove + '' + + '
'; + item.chkbox = ''; + } + else { + item.chkbox = ''; + item.action = '-'; + } }); } }), @@ -97,11 +105,17 @@ jQuery(function($){ item.log = 'Open logs' item.exclude = '' + item.exclude + '' item.server_w_port = item.user1 + '@' + item.host1 + ':' + item.port1; - item.action = ''; - item.chkbox = ''; + if (acl_data.syncjobs === 1) { + item.action = ''; + item.chkbox = ''; + } + else { + item.action = '-'; + item.chkbox = ''; + } }); } }), @@ -139,6 +153,9 @@ jQuery(function($){ else { item.chkbox = ''; } + if (acl_data.spam_policy === 0) { + item.chkbox = ''; + } }); } }), @@ -176,6 +193,9 @@ jQuery(function($){ else { item.chkbox = ''; } + if (acl_data.spam_policy === 0) { + item.chkbox = ''; + } }); } }), diff --git a/data/web/user.php b/data/web/user.php index 0eeafb81..2211c7f7 100644 --- a/data/web/user.php +++ b/data/web/user.php @@ -78,7 +78,8 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
+ $user_get_alias_details = user_get_alias_details($username); + ?>
:
@@ -121,9 +122,12 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '

/ ,

-
- - + '; + // Show tagging options + if ($_SESSION['acl']['delimiter_action'] == 1): + $get_tagging_options = mailbox('get', 'delimiter_action', $username); + ?>
:
@@ -148,8 +152,12 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '

- - +
:
@@ -173,7 +181,11 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '

- +
:
@@ -181,6 +193,9 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '

+ @@ -201,6 +216,9 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == ' +
@@ -224,6 +242,9 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
+
@@ -251,7 +272,10 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '

-
+ +
+
@@ -269,6 +296,9 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
+
@@ -284,6 +314,9 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
+

@@ -291,6 +324,9 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
+
@@ -308,6 +344,9 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
+
@@ -316,6 +355,9 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
+
@@ -329,6 +371,9 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
+
@@ -343,6 +388,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/modals/user.php';