From 6007e35666323d9addec8b2cdf563f28f89e9640 Mon Sep 17 00:00:00 2001 From: fbird Date: Sat, 5 Oct 2024 13:15:49 +0200 Subject: [PATCH 1/7] IMAP Authentication added IMAP auth added: - Standard.php extended, having imap_connection saved into baikal.yaml config file & Webadmin UI got a new conneted field to read/modify the IMAP connection - Server.php modified, to be able to use imap_connection from baikal.yaml Including Sabre.io/dav v4.6.0 IMAP Auth code, some tweaking --- Core/Frameworks/Baikal/Core/IMAP.php | 82 +++++++++++++++++++ Core/Frameworks/Baikal/Core/Server.php | 2 + .../Baikal/Model/Config/Standard.php | 9 +- 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 Core/Frameworks/Baikal/Core/IMAP.php diff --git a/Core/Frameworks/Baikal/Core/IMAP.php b/Core/Frameworks/Baikal/Core/IMAP.php new file mode 100644 index 00000000..3a183111 --- /dev/null +++ b/Core/Frameworks/Baikal/Core/IMAP.php @@ -0,0 +1,82 @@ +mailbox = $mailbox; + } + + /** + * Connects to an IMAP server and tries to authenticate. + * + * @param string $username + * @param string $password + * + * @return bool + */ + protected function imapOpen($username, $password) + { + $success = false; + + try { + $imap = imap_open($this->mailbox, $username, $password, OP_HALFOPEN | OP_READONLY, 1); + if ($imap) { + $success = true; + } + } catch (\ErrorException $e) { + error_log($e->getMessage()); + } + + $errors = imap_errors(); + if ($errors) { + foreach ($errors as $error) { + error_log($error); + } + } + + if (isset($imap) && $imap) { + imap_close($imap); + } + + return $success; + } + + /** + * Validates a username and password by trying to authenticate against IMAP. + * + * @param string $username + * @param string $password + * + * @return bool + */ + protected function validateUserPass($username, $password) + { + return $this->imapOpen($username, $password); + } +} diff --git a/Core/Frameworks/Baikal/Core/Server.php b/Core/Frameworks/Baikal/Core/Server.php index b0baf5a4..05894865 100644 --- a/Core/Frameworks/Baikal/Core/Server.php +++ b/Core/Frameworks/Baikal/Core/Server.php @@ -134,6 +134,8 @@ protected function initServer() { $authBackend = new \Baikal\Core\PDOBasicAuth($this->pdo, $this->authRealm); } elseif ($this->authType === 'Apache') { $authBackend = new \Sabre\DAV\Auth\Backend\Apache(); + } elseif ($this->authType === 'IMAP') { + $authBackend = new \Sabre\DAV\Auth\Backend\IMAP('{' . $config['system']["imap_connection"] . '}',$GLOBALS["DB"]->getPDO(),60); } else { $authBackend = new \Sabre\DAV\Auth\Backend\PDO($this->pdo); $authBackend->setRealm($this->authRealm); diff --git a/Core/Frameworks/Baikal/Model/Config/Standard.php b/Core/Frameworks/Baikal/Model/Config/Standard.php index 310d512d..2f4ddc96 100644 --- a/Core/Frameworks/Baikal/Model/Config/Standard.php +++ b/Core/Frameworks/Baikal/Model/Config/Standard.php @@ -43,6 +43,7 @@ class Standard extends \Baikal\Model\Config { // could be set to different value when migrating from legacy config "auth_realm" => "BaikalDAV", "base_uri" => "", + "imap_connection" => "localhost:993/imap/ssl/novalidate-cert", ]; function __construct() { @@ -79,7 +80,13 @@ function formMorphologyForThisModelInstance() { $oMorpho->add(new \Formal\Element\Listbox([ "prop" => "dav_auth_type", "label" => "WebDAV authentication type", - "options" => ["Digest", "Basic", "Apache"], + "options" => ["Digest", "Basic", "Apache", "IMAP"], + ])); + + $oMorpho->add(new \Formal\Element\Text([ + "prop" => "imap_connection", + "label" => "IMAP auth connection string", + "help" => "For production, use your real IMAP servername with TLS (SSL[993] or StartTLS(143)), eg.: imap.server.com:993/imap/ssl", ])); $oMorpho->add(new \Formal\Element\Password([ From 365d94d460e8769f1fc9c3a1778f2d88c148ce0e Mon Sep 17 00:00:00 2001 From: fbird Date: Mon, 7 Oct 2024 16:25:38 +0200 Subject: [PATCH 2/7] IMAP suepport web-admin UI update The web-admin UI now handles the additional IMAP connection input field as it is in the database settings page: when IMAP selected the field rendered, if not it gots hidden. (No validation built-in) --- .../Baikal/Model/Config/Standard.php | 1 + .../Controller/Settings/Standard.php | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/Core/Frameworks/Baikal/Model/Config/Standard.php b/Core/Frameworks/Baikal/Model/Config/Standard.php index 2f4ddc96..1f49bbb1 100644 --- a/Core/Frameworks/Baikal/Model/Config/Standard.php +++ b/Core/Frameworks/Baikal/Model/Config/Standard.php @@ -81,6 +81,7 @@ function formMorphologyForThisModelInstance() { "prop" => "dav_auth_type", "label" => "WebDAV authentication type", "options" => ["Digest", "Basic", "Apache", "IMAP"], + "refreshonchange" => true, ])); $oMorpho->add(new \Formal\Element\Text([ diff --git a/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php b/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php index 204f31b8..7e29bc55 100644 --- a/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php +++ b/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php @@ -48,6 +48,8 @@ function execute() { $this->oForm = $this->oModel->formForThisModelInstance([ "close" => false, + "hook.morphology" => [$this, "morphologyHook"], + "hook.validation" => [$this, "validationHook"], ]); if ($this->oForm->submitted()) { @@ -61,4 +63,22 @@ function render() { return $oView->render(); } + + + function morphologyHook(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) { + if ($oForm->submitted()) { + $bAuthtype = $oForm->postValue("dav_auth_type"); + } else { + try { + $config = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml"); + } catch (\Exception $e) { + error_log('Error reading baikal.yaml file : ' . $e->getMessage()); + } + $bAuthtype = $config['system']['dav_auth_type'] ?? true; + } + + if ($bAuthtype == "Digest" || $bAuthtype == "Basic" || $bAuthtype == "Apache") { + $oMorpho->remove("imap_connection"); + } + } } From b5fc176942781dd371b902473bf669f330c64eeb Mon Sep 17 00:00:00 2001 From: fbird Date: Mon, 7 Oct 2024 16:41:44 +0200 Subject: [PATCH 3/7] Update Standard.php Fix: remove declaration of non-existent validation-hook --- Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php b/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php index 7e29bc55..78ead849 100644 --- a/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php +++ b/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php @@ -49,7 +49,6 @@ function execute() { $this->oForm = $this->oModel->formForThisModelInstance([ "close" => false, "hook.morphology" => [$this, "morphologyHook"], - "hook.validation" => [$this, "validationHook"], ]); if ($this->oForm->submitted()) { From ebe8252c6af12274cb22a26b7bcb90be0fa0d4b5 Mon Sep 17 00:00:00 2001 From: fbird Date: Thu, 10 Oct 2024 23:55:45 +0200 Subject: [PATCH 4/7] IMAP Auth namespace and Baikal's PHP-CS alignments The unchanged IMAP.php from sabre.io/dav got updated: - the Baikal namespace & class extension - the GitHub PR at Baikel using different PHP-CS requirements than the one at Sabre.io/dav -> CS has been aligned to Baikal's one The same CS alignation applied to: - Core/Server.php - Model/Config/Standard.php - Controller/Settings/Standard.php --- Core/Frameworks/Baikal/Core/IMAP.php | 14 +++++--------- Core/Frameworks/Baikal/Core/Server.php | 2 +- Core/Frameworks/Baikal/Model/Config/Standard.php | 2 +- .../BaikalAdmin/Controller/Settings/Standard.php | 2 +- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/Core/Frameworks/Baikal/Core/IMAP.php b/Core/Frameworks/Baikal/Core/IMAP.php index 3a183111..a9a4610d 100644 --- a/Core/Frameworks/Baikal/Core/IMAP.php +++ b/Core/Frameworks/Baikal/Core/IMAP.php @@ -1,6 +1,6 @@ mailbox = $mailbox; } @@ -40,8 +38,7 @@ public function __construct($mailbox) * * @return bool */ - protected function imapOpen($username, $password) - { + protected function imapOpen($username, $password) { $success = false; try { @@ -75,8 +72,7 @@ protected function imapOpen($username, $password) * * @return bool */ - protected function validateUserPass($username, $password) - { + protected function validateUserPass($username, $password) { return $this->imapOpen($username, $password); } } diff --git a/Core/Frameworks/Baikal/Core/Server.php b/Core/Frameworks/Baikal/Core/Server.php index 05894865..05f48b0c 100644 --- a/Core/Frameworks/Baikal/Core/Server.php +++ b/Core/Frameworks/Baikal/Core/Server.php @@ -134,7 +134,7 @@ protected function initServer() { $authBackend = new \Baikal\Core\PDOBasicAuth($this->pdo, $this->authRealm); } elseif ($this->authType === 'Apache') { $authBackend = new \Sabre\DAV\Auth\Backend\Apache(); - } elseif ($this->authType === 'IMAP') { + } elseif ($this->authType === 'IMAP') { $authBackend = new \Sabre\DAV\Auth\Backend\IMAP('{' . $config['system']["imap_connection"] . '}',$GLOBALS["DB"]->getPDO(),60); } else { $authBackend = new \Sabre\DAV\Auth\Backend\PDO($this->pdo); diff --git a/Core/Frameworks/Baikal/Model/Config/Standard.php b/Core/Frameworks/Baikal/Model/Config/Standard.php index 1f49bbb1..be43fead 100644 --- a/Core/Frameworks/Baikal/Model/Config/Standard.php +++ b/Core/Frameworks/Baikal/Model/Config/Standard.php @@ -84,7 +84,7 @@ function formMorphologyForThisModelInstance() { "refreshonchange" => true, ])); - $oMorpho->add(new \Formal\Element\Text([ + $oMorpho->add(new \Formal\Element\Text([ "prop" => "imap_connection", "label" => "IMAP auth connection string", "help" => "For production, use your real IMAP servername with TLS (SSL[993] or StartTLS(143)), eg.: imap.server.com:993/imap/ssl", diff --git a/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php b/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php index 78ead849..524f49bf 100644 --- a/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php +++ b/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php @@ -64,7 +64,7 @@ function render() { } - function morphologyHook(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) { + function morphologyHook(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) { if ($oForm->submitted()) { $bAuthtype = $oForm->postValue("dav_auth_type"); } else { From 50f4627d78cf37b7ea17b8fecd87e226e27ae222 Mon Sep 17 00:00:00 2001 From: fbird Date: Fri, 11 Oct 2024 00:02:52 +0200 Subject: [PATCH 5/7] PHP-CS fixes again --- Core/Frameworks/Baikal/Core/Server.php | 2 +- Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/Frameworks/Baikal/Core/Server.php b/Core/Frameworks/Baikal/Core/Server.php index 05f48b0c..e945c5dc 100644 --- a/Core/Frameworks/Baikal/Core/Server.php +++ b/Core/Frameworks/Baikal/Core/Server.php @@ -135,7 +135,7 @@ protected function initServer() { } elseif ($this->authType === 'Apache') { $authBackend = new \Sabre\DAV\Auth\Backend\Apache(); } elseif ($this->authType === 'IMAP') { - $authBackend = new \Sabre\DAV\Auth\Backend\IMAP('{' . $config['system']["imap_connection"] . '}',$GLOBALS["DB"]->getPDO(),60); + $authBackend = new \Sabre\DAV\Auth\Backend\IMAP('{' . $config['system']["imap_connection"] . '}', $GLOBALS["DB"]->getPDO(),60); } else { $authBackend = new \Sabre\DAV\Auth\Backend\PDO($this->pdo); $authBackend->setRealm($this->authRealm); diff --git a/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php b/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php index 524f49bf..dcd07a62 100644 --- a/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php +++ b/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php @@ -63,7 +63,6 @@ function render() { return $oView->render(); } - function morphologyHook(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) { if ($oForm->submitted()) { $bAuthtype = $oForm->postValue("dav_auth_type"); From 9346479dd751c208db7ba179b85bd2afad2fb903 Mon Sep 17 00:00:00 2001 From: fbird Date: Fri, 11 Oct 2024 00:04:34 +0200 Subject: [PATCH 6/7] Hopefully the final PHP-CS fix --- Core/Frameworks/Baikal/Core/Server.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Frameworks/Baikal/Core/Server.php b/Core/Frameworks/Baikal/Core/Server.php index e945c5dc..439f7a4d 100644 --- a/Core/Frameworks/Baikal/Core/Server.php +++ b/Core/Frameworks/Baikal/Core/Server.php @@ -135,7 +135,7 @@ protected function initServer() { } elseif ($this->authType === 'Apache') { $authBackend = new \Sabre\DAV\Auth\Backend\Apache(); } elseif ($this->authType === 'IMAP') { - $authBackend = new \Sabre\DAV\Auth\Backend\IMAP('{' . $config['system']["imap_connection"] . '}', $GLOBALS["DB"]->getPDO(),60); + $authBackend = new \Sabre\DAV\Auth\Backend\IMAP('{' . $config['system']["imap_connection"] . '}', $GLOBALS["DB"]->getPDO(), 60); } else { $authBackend = new \Sabre\DAV\Auth\Backend\PDO($this->pdo); $authBackend->setRealm($this->authRealm); From b323d456dba57fbd2340d2bc055e9063e4f83b89 Mon Sep 17 00:00:00 2001 From: fbird Date: Fri, 11 Oct 2024 00:09:38 +0200 Subject: [PATCH 7/7] add Yaml namespace --- Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php b/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php index dcd07a62..9b07182d 100644 --- a/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php +++ b/Core/Frameworks/BaikalAdmin/Controller/Settings/Standard.php @@ -27,6 +27,8 @@ namespace BaikalAdmin\Controller\Settings; +use Symfony\Component\Yaml\Yaml; + class Standard extends \Flake\Core\Controller { /** * @var \Baikal\Model\Config\Standard