From 60e97503f711ed776c68a8adaa0a5cd2c20fd1a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Wed, 8 Nov 2017 11:07:32 +0100 Subject: [PATCH] [Web, Dovecot] Show wether a sync job is running, validate min max input attr and validate these values --- data/Dockerfiles/dovecot/imapsync_cron.pl | 6 +++- data/web/inc/init_db.inc.php | 3 +- data/web/js/api.js | 36 +++++++++++++++++++++-- data/web/js/mailbox.js | 11 ++++++- data/web/js/user.js | 23 +++++++++++---- data/web/json_api.php | 35 +++++++++++++++++++++- data/web/lang/lang.de.php | 6 ++++ data/web/lang/lang.en.php | 6 ++++ data/web/modals/mailbox.php | 4 +++ data/web/modals/user.php | 3 ++ docker-compose.yml | 2 +- 11 files changed, 122 insertions(+), 13 deletions(-) diff --git a/data/Dockerfiles/dovecot/imapsync_cron.pl b/data/Dockerfiles/dovecot/imapsync_cron.pl index 132e536e3..ddd4746a3 100755 --- a/data/Dockerfiles/dovecot/imapsync_cron.pl +++ b/data/Dockerfiles/dovecot/imapsync_cron.pl @@ -54,6 +54,10 @@ while ($row = $sth->fetchrow_arrayref()) { $delete1 = @$row[12]; $delete2 = @$row[13]; + $is_running = $dbh->prepare("UPDATE imapsync SET is_running = 1 WHERE id = ?"); + $is_running->bind_param( 1, ${id} ); + $is_running->execute(); + if ($enc1 eq "TLS") { $enc1 = "--tls1"; } elsif ($enc1 eq "SSL") { $enc1 = "--ssl1"; } else { undef $enc1; } my $template = $run_dir . '/imapsync.XXXXXXX'; @@ -83,7 +87,7 @@ while ($row = $sth->fetchrow_arrayref()) { "--passfile2", $passfile2->filename, '--no-modulesversion'], ">", \my $stdout; - $update = $dbh->prepare("UPDATE imapsync SET returned_text = ?, last_run = NOW() WHERE id = ?"); + $update = $dbh->prepare("UPDATE imapsync SET returned_text = ?, last_run = NOW(), is_running = 0 WHERE id = ?"); $update->bind_param( 1, ${stdout} ); $update->bind_param( 2, ${id} ); $update->execute(); diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index 9b6a63c93..1bc024977 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 = "31102017_1049"; + $db_version = "08112017_1049"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -314,6 +314,7 @@ function init_db_schema() { "delete2duplicates" => "TINYINT(1) NOT NULL DEFAULT '1'", "delete1" => "TINYINT(1) NOT NULL DEFAULT '0'", "delete2" => "TINYINT(1) NOT NULL DEFAULT '0'", + "is_running" => "TINYINT(1) NOT NULL DEFAULT '0'", "returned_text" => "TEXT", "last_run" => "TIMESTAMP NULL DEFAULT NULL", "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", diff --git a/data/web/js/api.js b/data/web/js/api.js index 23bf229e8..824e2d646 100644 --- a/data/web/js/api.js +++ b/data/web/js/api.js @@ -79,6 +79,21 @@ $(document).ready(function() { $(this).removeClass('inputMissingAttr'); } } + if ($(this).attr("max")) { + if ($(this).val() > $(this).attr("max")) { + invalid = true; + $(this).addClass('inputMissingAttr'); + } else { + if ($(this).attr("min")) { + if ($(this).val() < $(this).attr("min")) { + invalid = true; + $(this).addClass('inputMissingAttr'); + } else { + $(this).removeClass('inputMissingAttr'); + } + } + } + } }); if (!req_empty) { var attr_to_merge = $(this).closest("form").serializeObject(); @@ -129,18 +144,33 @@ $(document).ready(function() { // If clicked button is in a form with the same data-id as the button, // we merge all input fields by {"name":"value"} into api-attr if ($(this).closest("form").data('id') == id) { - var req_empty = false; + var invalid = false; $(this).closest("form").find('select, textarea, input').each(function() { if ($(this).prop('required')) { if (!$(this).val() && $(this).prop('disabled') === false) { - req_empty = true; + invalid = true; $(this).addClass('inputMissingAttr'); } else { $(this).removeClass('inputMissingAttr'); } } + if ($(this).attr("max")) { + if ($(this).val() > $(this).attr("max")) { + invalid = true; + $(this).addClass('inputMissingAttr'); + } else { + if ($(this).attr("min")) { + if ($(this).val() < $(this).attr("min")) { + invalid = true; + $(this).addClass('inputMissingAttr'); + } else { + $(this).removeClass('inputMissingAttr'); + } + } + } + } }); - if (!req_empty) { + if (!invalid) { var attr_to_merge = $(this).closest("form").serializeObject(); var api_attr = $.extend(api_attr, attr_to_merge) } else { diff --git a/data/web/js/mailbox.js b/data/web/js/mailbox.js index d55b19133..9e2afa2c5 100644 --- a/data/web/js/mailbox.js +++ b/data/web/js/mailbox.js @@ -421,7 +421,8 @@ jQuery(function($){ {"name":"mins_interval","title":lang.mins_interval,"breakpoints":"all"}, {"name":"last_run","title":lang.last_run,"breakpoints":"all"}, {"name":"log","title":"Log"}, - {"name":"active","filterable": false,"style":{"maxWidth":"50px","width":"70px"},"title":lang.active}, + {"name":"active","filterable": false,"style":{"maxWidth":"70px","width":"70px"},"title":lang.active}, + {"name":"is_running","filterable": false,"style":{"maxWidth":"120px","width":"100px"},"title":lang.status}, {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} ], "empty": lang.empty, @@ -442,6 +443,14 @@ jQuery(function($){ ' ' + lang.remove + '' + ''; item.chkbox = ''; + if (item.is_running == 1) { + item.is_running = '' + lang.running + ''; + } else { + item.is_running = '' + lang.waiting + ''; + } + if (!item.last_run > 0) { + item.last_run = lang.waiting; + } }); } }), diff --git a/data/web/js/user.js b/data/web/js/user.js index 239507f4c..900dced17 100644 --- a/data/web/js/user.js +++ b/data/web/js/user.js @@ -89,13 +89,14 @@ jQuery(function($){ {"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px","text-align":"center"},"filterable": false,"sortable": false,"type":"html"}, {"sorted": true,"name":"id","title":"ID","style":{"maxWidth":"60px","width":"60px","text-align":"center"}}, {"name":"server_w_port","title":"Server"}, - {"name":"enc1","title":lang.encryption}, + {"name":"enc1","title":lang.encryption,"breakpoints":"xs sm"}, {"name":"user1","title":lang.username}, - {"name":"exclude","title":lang.excludes}, + {"name":"exclude","title":lang.excludes,"breakpoints":"xs sm"}, {"name":"mins_interval","title":lang.interval + " (min)"}, - {"name":"last_run","title":lang.last_run}, + {"name":"last_run","title":lang.last_run,"breakpoints":"xs sm"}, {"name":"log","title":"Log"}, - {"name":"active","filterable": false,"style":{"maxWidth":"50px","width":"70px"},"title":lang.active}, + {"name":"active","filterable": false,"style":{"maxWidth":"70px","width":"70px"},"title":lang.active}, + {"name":"is_running","filterable": false,"style":{"maxWidth":"120px","width":"100px"},"title":lang.status}, {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} ], "empty": lang.empty, @@ -109,7 +110,11 @@ jQuery(function($){ success: function (data) { $.each(data, function (i, item) { item.log = 'Open logs' - item.exclude = '' + item.exclude + '' + if (!item.exclude > 0) { + item.exclude = '-'; + } else { + item.exclude = '' + item.exclude + ''; + } item.server_w_port = item.user1 + '@' + item.host1 + ':' + item.port1; if (acl_data.syncjobs === 1) { item.action = '
' + @@ -122,6 +127,14 @@ jQuery(function($){ item.action = '-'; item.chkbox = ''; } + if (item.is_running == 1) { + item.is_running = '' + lang.running + ''; + } else { + item.is_running = '' + lang.waiting + ''; + } + if (!item.last_run > 0) { + item.last_run = lang.waiting; + } }); } }), diff --git a/data/web/json_api.php b/data/web/json_api.php index 0bc5e3a61..b622c3120 100644 --- a/data/web/json_api.php +++ b/data/web/json_api.php @@ -13,7 +13,7 @@ delete/alias => POST data: */ header('Content-Type: application/json'); -require_once 'inc/prerequisites.inc.php'; +require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php'; error_reporting(0); if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_username'])) { if (isset($_GET['query'])) { @@ -489,6 +489,39 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u )); } break; + case "syncjob": + if (isset($_POST['attr'])) { + $attr = (array)json_decode($_POST['attr'], true); + if (mailbox('add', 'syncjob', $attr) === false) { + if (isset($_SESSION['return'])) { + echo json_encode($_SESSION['return']); + } + else { + echo json_encode(array( + 'type' => 'error', + 'msg' => 'Cannot add item' + )); + } + } + else { + if (isset($_SESSION['return'])) { + echo json_encode($_SESSION['return']); + } + else { + echo json_encode(array( + 'type' => 'success', + 'msg' => 'Task completed' + )); + } + } + } + else { + echo json_encode(array( + 'type' => 'error', + 'msg' => 'Cannot find attributes in post data' + )); + } + break; } break; case "get": diff --git a/data/web/lang/lang.de.php b/data/web/lang/lang.de.php index 86c4505f4..2dd5cd9e0 100644 --- a/data/web/lang/lang.de.php +++ b/data/web/lang/lang.de.php @@ -158,6 +158,9 @@ $lang['user']['spamfilter_red'] = 'Rot: Die Nachricht ist eindeutig Spam und wir $lang['user']['spamfilter_default_score'] = 'Standardwert:'; $lang['user']['spamfilter_hint'] = 'Der erste Wert beschreibt den "low spam score", der zweite Wert den "high spam score".'; $lang['user']['spamfilter_table_domain_policy'] = "n.v. (Domainrichtlinie)"; +$lang['user']['waiting'] = "Warte auf Ausführung"; +$lang['user']['status'] = "Status"; +$lang['user']['running'] = "Wird ausgeführt"; $lang['user']['tls_policy_warning'] = 'Vorsicht: Entscheiden Sie sich unverschlüsselte Verbindungen abzulehnen, kann dies dazu führen, dass Kontakte Sie nicht mehr erreichen.
Nachrichten, die die Richtlinie nicht erfüllen, werden durch einen Hard-Fail im Mailsystem abgewiesen.
Diese Einstellung ist aktiv für die primäre Mailbox, für alle Alias-Adressen, die dieser Mailbox direkt zugeordnet sind (lediglich eine einzige Ziel-Adresse) und der Adressen, die sich aus Alias-Domains ergeben. Ausgeschlossen sind temporäre Aliasse ("Spam-Alias-Adressen"), Catch-All Alias-Adressen sowie Alias-Adressen mit mehreren Zielen.'; $lang['user']['tls_policy'] = 'Verschlüsselungsrichtlinie'; @@ -554,3 +557,6 @@ $lang['admin']['remove_row'] = "Zeile entfernen"; $lang['admin']['add_row'] = "Zeile hinzufügen"; $lang['admin']['reset_default'] = "Auf Standard zurücksetzen"; $lang['admin']['merged_vars_hint'] = 'Ausgegraute Zeilen wurden aus der Datei vars.inc.(local.)php gelesen und können nicht mittels UI verändert werden.'; +$lang['mailbox']['waiting'] = "Wartend"; +$lang['mailbox']['status'] = "Status"; +$lang['mailbox']['running'] = "In Ausführung"; \ No newline at end of file diff --git a/data/web/lang/lang.en.php b/data/web/lang/lang.en.php index 01996066d..8832c3341 100644 --- a/data/web/lang/lang.en.php +++ b/data/web/lang/lang.en.php @@ -160,6 +160,9 @@ $lang['user']['spamfilter_red'] = 'Red: This message is spam and will be rejecte $lang['user']['spamfilter_default_score'] = 'Default values:'; $lang['user']['spamfilter_hint'] = 'The first value describes the "low spam score", the second represents the "high spam score".'; $lang['user']['spamfilter_table_domain_policy'] = "n/a (domain policy)"; +$lang['user']['waiting'] = "Waiting"; +$lang['user']['status'] = "Status"; +$lang['user']['running'] = "Running"; $lang['user']['tls_policy_warning'] = 'Warning: If you decide to enforce encrypted mail transfer, you may lose emails.
Messages to not satisfy the policy will be bounced with a hard fail by the mail system.
This option applies to your primary email address (login name), all addresses derived from alias domains as well as alias addresses with only this single mailbox as target.'; $lang['user']['tls_policy'] = 'Encryption policy'; @@ -567,6 +570,9 @@ $lang['admin']['remove_row'] = "Remove row"; $lang['admin']['add_row'] = "Add row"; $lang['admin']['reset_default'] = "Reset to default"; $lang['admin']['merged_vars_hint'] = 'Greyed out rows were merged from vars.inc.(local.)php and cannot be modified.'; +$lang['mailbox']['waiting'] = "Waiting"; +$lang['mailbox']['status'] = "Status"; +$lang['mailbox']['running'] = "Running"; $lang['edit']['tls_policy'] = "Change TLS policy"; $lang['edit']['spam_score'] = "Set a custom spam score"; diff --git a/data/web/modals/mailbox.php b/data/web/modals/mailbox.php index 0dcdfd445..192124c2c 100644 --- a/data/web/modals/mailbox.php +++ b/data/web/modals/mailbox.php @@ -44,6 +44,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
+ min. 1
@@ -344,6 +345,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
+ 1-65535
@@ -372,6 +374,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
+ 10-3600
@@ -384,6 +387,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
+ 0-32000
diff --git a/data/web/modals/user.php b/data/web/modals/user.php index da1e98ce6..a7cc39959 100644 --- a/data/web/modals/user.php +++ b/data/web/modals/user.php @@ -25,6 +25,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
+ 1-65535
@@ -53,6 +54,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
+ 10-3600
@@ -65,6 +67,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
+ 0-32000
diff --git a/docker-compose.yml b/docker-compose.yml index ac85c6fd6..e4b6e858a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -143,7 +143,7 @@ services: - sogo dovecot-mailcow: - image: mailcow/dovecot:1.11 + image: mailcow/dovecot:1.12 build: ./data/Dockerfiles/dovecot cap_add: - NET_BIND_SERVICE