From 32014dfcecd9133c68998bce641e447a697650d3 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it <75116288+FreddleSpl0it@users.noreply.github.com> Date: Wed, 6 May 2026 11:01:15 +0200 Subject: [PATCH] [Web] Add password change acl --- data/web/inc/functions.inc.php | 8 ++++++++ data/web/inc/functions.mailbox.inc.php | 10 ++++++++-- data/web/inc/init_db.inc.php | 4 +++- data/web/js/site/mailbox.js | 3 +++ data/web/lang/lang.de-de.json | 1 + data/web/lang/lang.en-gb.json | 1 + data/web/templates/edit/mailbox-templates.twig | 1 + data/web/templates/modals/mailbox.twig | 1 + data/web/templates/user/tab-user-auth.twig | 2 ++ 9 files changed, 28 insertions(+), 3 deletions(-) diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index 89f14b574..95f980721 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -1035,6 +1035,14 @@ function edit_user_account($_data) { // edit password $is_forced_pw_update = !empty($_SESSION['pending_pw_update']); if (((!empty($password_old) || $is_forced_pw_update) && !empty($_data['user_new_pass']) && !empty($_data['user_new_pass2']))) { + if (!$is_forced_pw_update && (!isset($_SESSION['acl']['pw_change']) || $_SESSION['acl']['pw_change'] != "1")) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_data_log), + 'msg' => 'access_denied' + ); + return false; + } // Only verify old password if this is NOT a forced password update if (!$is_forced_pw_update) { $stmt = $pdo->prepare("SELECT `password` FROM `mailbox` diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index adb330ea8..2f097d8a3 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -1331,6 +1331,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $_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; + $_data['pw_change'] = (in_array('pw_change', $_data['acl'])) ? 1 : 0; $_data['pw_reset'] = (in_array('pw_reset', $_data['acl'])) ? 1 : 0; } else { $_data['spam_alias'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_spam_alias']); @@ -1347,15 +1348,16 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $_data['quarantine_notification'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_quarantine_notification']); $_data['quarantine_category'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_quarantine_category']); $_data['app_passwds'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_app_passwds']); + $_data['pw_change'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_pw_change']); $_data['pw_reset'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_pw_reset']); } try { $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`, `pw_reset`) + `pushover`, `quarantine`, `quarantine_attachments`, `quarantine_notification`, `quarantine_category`, `app_passwds`, `pw_change`, `pw_reset`) 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, :pw_reset) "); + :pushover, :quarantine, :quarantine_attachments, :quarantine_notification, :quarantine_category, :app_passwds, :pw_change, :pw_reset) "); $stmt->execute(array( ':username' => $username, ':spam_alias' => $_data['spam_alias'], @@ -1372,6 +1374,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ':quarantine_notification' => $_data['quarantine_notification'], ':quarantine_category' => $_data['quarantine_category'], ':app_passwds' => $_data['app_passwds'], + ':pw_change' => $_data['pw_change'], ':pw_reset' => $_data['pw_reset'] )); } @@ -1792,6 +1795,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $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; + $attr['acl_pw_change'] = (in_array('pw_change', $_data['acl'])) ? 1 : 0; $attr['acl_pw_reset'] = (in_array('pw_reset', $_data['acl'])) ? 1 : 0; } else { $_data['acl'] = (array)$_data['acl']; @@ -1809,6 +1813,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $attr['acl_quarantine_notification'] = 0; $attr['acl_quarantine_category'] = 0; $attr['acl_app_passwds'] = 0; + $attr['acl_pw_change'] = 0; } @@ -3862,6 +3867,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $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; + $attr['acl_pw_change'] = (in_array('pw_change', $_data['acl'])) ? 1 : 0; $attr['acl_pw_reset'] = (in_array('pw_reset', $_data['acl'])) ? 1 : 0; } else { foreach ($is_now as $key => $value){ diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index 72018a6bc..dbde76b94 100644 --- a/data/web/inc/init_db.inc.php +++ b/data/web/inc/init_db.inc.php @@ -4,7 +4,7 @@ function init_db_schema() try { global $pdo; - $db_version = "19022026_1220"; + $db_version = "16042026_1402"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -513,6 +513,7 @@ function init_db_schema() "quarantine_notification" => "TINYINT(1) NOT NULL DEFAULT '1'", "quarantine_category" => "TINYINT(1) NOT NULL DEFAULT '1'", "app_passwds" => "TINYINT(1) NOT NULL DEFAULT '1'", + "pw_change" => "TINYINT(1) NOT NULL DEFAULT '1'", "pw_reset" => "TINYINT(1) NOT NULL DEFAULT '1'", ), "keys" => array( @@ -1478,6 +1479,7 @@ function init_db_schema() "acl_quarantine_notification" => 1, "acl_quarantine_category" => 1, "acl_app_passwds" => 1, + "acl_pw_change" => 1, ) ); $stmt = $pdo->prepare("SELECT id FROM `templates` WHERE `type` = :type AND `template` = :template"); diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js index e8edb9940..5fe6b8141 100644 --- a/data/web/js/site/mailbox.js +++ b/data/web/js/site/mailbox.js @@ -403,6 +403,9 @@ $(document).ready(function() { if (template.acl_app_passwds == 1){ acl.push("app_passwds"); } + if (template.acl_pw_change == 1){ + acl.push("pw_change"); + } if (template.acl_pw_reset == 1){ acl.push("pw_reset"); } diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index 3672762df..5ab60067c 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -14,6 +14,7 @@ "prohibited": "Untersagt durch Richtlinie", "protocol_access": "Ändern der erlaubten Protokolle", "pushover": "Pushover", + "pw_change": "Passwortänderung erlauben", "pw_reset": "Verwalten der E-Mail zur Passwortwiederherstellung erlauben", "quarantine": "Quarantäne-Aktionen", "quarantine_attachments": "Anhänge aus Quarantäne", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index e786bcbe5..bc2cd0c21 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -14,6 +14,7 @@ "prohibited": "Prohibited by ACL", "protocol_access": "Change protocol access", "pushover": "Pushover", + "pw_change": "Allow password change", "pw_reset": "Allow to reset mailcow user password", "quarantine": "Quarantine actions", "quarantine_attachments": "Quarantine attachments", diff --git a/data/web/templates/edit/mailbox-templates.twig b/data/web/templates/edit/mailbox-templates.twig index ddc139586..80bf112c2 100644 --- a/data/web/templates/edit/mailbox-templates.twig +++ b/data/web/templates/edit/mailbox-templates.twig @@ -131,6 +131,7 @@ + diff --git a/data/web/templates/modals/mailbox.twig b/data/web/templates/modals/mailbox.twig index 924d88c8b..def601332 100644 --- a/data/web/templates/modals/mailbox.twig +++ b/data/web/templates/modals/mailbox.twig @@ -172,6 +172,7 @@ + diff --git a/data/web/templates/user/tab-user-auth.twig b/data/web/templates/user/tab-user-auth.twig index 171545d6c..9e3850b59 100644 --- a/data/web/templates/user/tab-user-auth.twig +++ b/data/web/templates/user/tab-user-auth.twig @@ -108,7 +108,9 @@