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 132e536e..ddd4746a 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 9b6a63c9..1bc02497 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 23bf229e..824e2d64 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 d55b1913..9e2afa2c 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 239507f4..900dced1 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 0bc5e3a6..b622c312 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 86c4505f..2dd5cd9e 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 01996066..8832c334 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 0dcdfd44..192124c2 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 da1e98ce..a7cc3995 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 ac85c6fd..e4b6e858 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