From edb1bf29eb12dca0c2029ecc27321d6ea35e1ba9 Mon Sep 17 00:00:00 2001 From: Akhil Date: Fri, 4 Aug 2023 01:03:06 +0530 Subject: [PATCH 01/28] Attempt to add basic nextcloud addressbook --- plugins/nextcloud/NextcloudAddressBook.php | 93 ++++++++++++++++++++++ plugins/nextcloud/index.php | 4 + 2 files changed, 97 insertions(+) create mode 100644 plugins/nextcloud/NextcloudAddressBook.php diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php new file mode 100644 index 0000000000..4e3129861e --- /dev/null +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -0,0 +1,93 @@ +contactsManager = \OC::$server->getContactsManager(); + foreach ($this->contactsManager->getAddressBooks() as $addressbook) { + if ($addressbook->getKey() !== self::URI) { + $this->contactsManager->unregisterAddressBook($addressbook); + } + } + } + + public function IsSupported() : bool { + // Maybe just return true, contacts app is just a frontend + //return \OC::$server->getAppManager()->isEnabledForUser('contacts'); + return true; + } + + public function SetEmail(string $sEmail) : bool { + return true; + } + + public function Sync() : bool { + return false; + } + + public function Export(string $sType = 'vcf') : bool { + return false; + } + + public function ContactSave(Contact $oContact) : bool { + if ($this->contactsManager->createOrUpdate($oContact->vCard->jsonSerialize(), self::URI)) { + return true; + } + return false; + } + + public function DeleteContacts(array $aContactIds) : bool { + return false; + } + + public function DeleteAllContacts(string $sEmail) : bool { + return false; + } + + public function GetContacts(int $iOffset = 0, int $iLimit = 20, string $sSearch = '', int &$iResultCount = 0) : array { + $options = [ + 'offset' => $iOffset, + 'limit' => $iLimit + ]; + $results = $this->contactsManager->search($sSearch, [], $options); + $iResultCount = count($results); + return $results; + + } + + public function GetContactByEmail(string $sEmail) : ?Contact { + return null; + } + + public function GetContactByID($mID, bool $bIsStrID = false) : ?Contact { + return null; + } + + public function GetSuggestions(string $sSearch, int $iLimit = 20) : array { + $options = [ + 'limit' => $iLimit + ]; + return $this->contactsManager->search($sSearch, [], $options); + } + + /** + * Add/increment email address usage + * Handy for "most used" sorting suggestions in PdoAddressBook + */ + public function IncFrec(array $aEmails, bool $bCreateAuto = true) : bool { + return false; + } + + public function Test() : string { + return ''; + } +} diff --git a/plugins/nextcloud/index.php b/plugins/nextcloud/index.php index 72af1ed3dc..05ea772cdd 100644 --- a/plugins/nextcloud/index.php +++ b/plugins/nextcloud/index.php @@ -259,6 +259,10 @@ public function MainFabrica(string $sName, &$mResult) $this->Config()->Get('plugin', 'ignoreSystemAddressbook', true) ); } + if ('address-book' === $sName) { + include_once __DIR__ . '/NextcloudAddressBook.php'; + $mResult = new NextcloudAddressBook(); + } } } From 65521c56e3cb78ebd63dd50b2e7d2e61f91394e6 Mon Sep 17 00:00:00 2001 From: Akhil Date: Fri, 4 Aug 2023 01:06:26 +0530 Subject: [PATCH 02/28] Check if array --- plugins/nextcloud/index.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/nextcloud/index.php b/plugins/nextcloud/index.php index 05ea772cdd..718ca69b31 100644 --- a/plugins/nextcloud/index.php +++ b/plugins/nextcloud/index.php @@ -260,6 +260,9 @@ public function MainFabrica(string $sName, &$mResult) ); } if ('address-book' === $sName) { + if (!\is_array($mResult)) { + $mResult = array(); + } include_once __DIR__ . '/NextcloudAddressBook.php'; $mResult = new NextcloudAddressBook(); } From 1ee07bb83d89248ac69e4d8bec514fbd01002d3c Mon Sep 17 00:00:00 2001 From: Akhil Date: Fri, 4 Aug 2023 01:08:21 +0530 Subject: [PATCH 03/28] Remove unused imports --- plugins/nextcloud/NextcloudAddressBook.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index 4e3129861e..25c21c692b 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -1,10 +1,6 @@ Date: Fri, 4 Aug 2023 01:17:36 +0530 Subject: [PATCH 04/28] convert results from nc to sm contacts --- plugins/nextcloud/NextcloudAddressBook.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index 25c21c692b..922f3431c7 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -56,7 +56,7 @@ public function GetContacts(int $iOffset = 0, int $iLimit = 20, string $sSearch ]; $results = $this->contactsManager->search($sSearch, [], $options); $iResultCount = count($results); - return $results; + return $this->convertResultsToSnappymailContacts($results); } @@ -72,7 +72,8 @@ public function GetSuggestions(string $sSearch, int $iLimit = 20) : array { $options = [ 'limit' => $iLimit ]; - return $this->contactsManager->search($sSearch, [], $options); + $results = $this->contactsManager->search($sSearch, [], $options); + return $this->convertResultsToSnappymailContacts($results); } /** @@ -86,4 +87,16 @@ public function IncFrec(array $aEmails, bool $bCreateAuto = true) : bool { public function Test() : string { return ''; } + + private function convertResultsToSnappymailContacts(array $results = []) { + $contacts = []; + foreach($results as $result) { + $vCard = \Sabre\VObject\Reader::readJson($result); + $contact = new Contact(); + $contact->setVCard($vCard); + $contacts[] = $contact; + } + + return $contacts; + } } From 2f7d121fef437b33ed67b9a8a2f22052117c0e38 Mon Sep 17 00:00:00 2001 From: Akhil Date: Fri, 4 Aug 2023 01:57:53 +0530 Subject: [PATCH 05/28] Copy incfrec from kolab --- plugins/nextcloud/NextcloudAddressBook.php | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index 922f3431c7..434f8db15a 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -1,5 +1,6 @@ $sAddress) { + $oVCard = new VCard; + $oVCard->add('EMAIL', $sEmail); + $sFullName = \trim(\MailSo\Mime\Email::Parse(\trim($sAddress))->GetDisplayName()); + if ('' !== $sFullName) { + $sFirst = $sLast = ''; + if (false !== \strpos($sFullName, ' ')) { + $aNames = \explode(' ', $sFullName, 2); + $sFirst = isset($aNames[0]) ? $aNames[0] : ''; + $sLast = isset($aNames[1]) ? $aNames[1] : ''; + } else { + $sFirst = $sFullName; + } + if (\strlen($sFirst) || \strlen($sLast)) { + $oVCard->N = array($sLast, $sFirst, '', '', ''); + } + } + $oContact = new Contact(); + $oContact->setVCard($oVCard); + $this->ContactSave($oContact); + } + return true; + } return false; } From 147ba65a358c6e90365313eace70ef6f6b29b098 Mon Sep 17 00:00:00 2001 From: Akhil Date: Fri, 4 Aug 2023 02:52:23 +0530 Subject: [PATCH 06/28] Keep only incfrec --- plugins/nextcloud/NextcloudAddressBook.php | 57 +++++----------------- 1 file changed, 13 insertions(+), 44 deletions(-) diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index 434f8db15a..2bfb5027f7 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -4,16 +4,21 @@ class NextcloudAddressBook implements \RainLoop\Providers\AddressBook\AddressBookInterface { + use Rainloop\Providers\AddressBook\CardDAV; private const URI = 'webmail'; private $contactsManager; + private $key; function __construct() { $this->contactsManager = \OC::$server->getContactsManager(); - foreach ($this->contactsManager->getAddressBooks() as $addressbook) { - if ($addressbook->getKey() !== self::URI) { + foreach ($this->contactsManager->getUserAddressBooks() as $addressbook) { + if ($addressbook->getUri() !== self::URI) { $this->contactsManager->unregisterAddressBook($addressbook); } + else { + $this->key = $addressbook->getKey(); + } } } @@ -36,9 +41,6 @@ public function Export(string $sType = 'vcf') : bool { } public function ContactSave(Contact $oContact) : bool { - if ($this->contactsManager->createOrUpdate($oContact->vCard->jsonSerialize(), self::URI)) { - return true; - } return false; } @@ -51,14 +53,7 @@ public function DeleteAllContacts(string $sEmail) : bool { } public function GetContacts(int $iOffset = 0, int $iLimit = 20, string $sSearch = '', int &$iResultCount = 0) : array { - $options = [ - 'offset' => $iOffset, - 'limit' => $iLimit - ]; - $results = $this->contactsManager->search($sSearch, [], $options); - $iResultCount = count($results); - return $this->convertResultsToSnappymailContacts($results); - + return []; } public function GetContactByEmail(string $sEmail) : ?Contact { @@ -70,11 +65,7 @@ public function GetContactByID($mID, bool $bIsStrID = false) : ?Contact { } public function GetSuggestions(string $sSearch, int $iLimit = 20) : array { - $options = [ - 'limit' => $iLimit - ]; - $results = $this->contactsManager->search($sSearch, [], $options); - return $this->convertResultsToSnappymailContacts($results); + return []; } /** @@ -83,26 +74,14 @@ public function GetSuggestions(string $sSearch, int $iLimit = 20) : array { */ public function IncFrec(array $aEmails, bool $bCreateAuto = true) : bool { if ($bCreateAuto) { + $properties = []; foreach ($aEmails as $sEmail => $sAddress) { - $oVCard = new VCard; - $oVCard->add('EMAIL', $sEmail); + $properties['EMAIL'] = $sAddress; $sFullName = \trim(\MailSo\Mime\Email::Parse(\trim($sAddress))->GetDisplayName()); if ('' !== $sFullName) { - $sFirst = $sLast = ''; - if (false !== \strpos($sFullName, ' ')) { - $aNames = \explode(' ', $sFullName, 2); - $sFirst = isset($aNames[0]) ? $aNames[0] : ''; - $sLast = isset($aNames[1]) ? $aNames[1] : ''; - } else { - $sFirst = $sFullName; - } - if (\strlen($sFirst) || \strlen($sLast)) { - $oVCard->N = array($sLast, $sFirst, '', '', ''); - } + $properties['FN'] = $sFullName; } - $oContact = new Contact(); - $oContact->setVCard($oVCard); - $this->ContactSave($oContact); + $this->contactsManager->createOrUpdate($properties, $this->key); } return true; } @@ -113,15 +92,5 @@ public function Test() : string { return ''; } - private function convertResultsToSnappymailContacts(array $results = []) { - $contacts = []; - foreach($results as $result) { - $vCard = \Sabre\VObject\Reader::readJson($result); - $contact = new Contact(); - $contact->setVCard($vCard); - $contacts[] = $contact; - } - return $contacts; - } } From dc6e93afaa0021674a94e409c41a49b1802542e6 Mon Sep 17 00:00:00 2001 From: Nivesh Krishna Date: Wed, 16 Aug 2023 00:02:06 +0530 Subject: [PATCH 07/28] create addressbook if not already exists --- plugins/nextcloud/NextcloudAddressBook.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index 2bfb5027f7..e4ce6711c0 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -12,14 +12,17 @@ class NextcloudAddressBook implements \RainLoop\Providers\AddressBook\AddressBoo function __construct() { $this->contactsManager = \OC::$server->getContactsManager(); - foreach ($this->contactsManager->getUserAddressBooks() as $addressbook) { - if ($addressbook->getUri() !== self::URI) { - $this->contactsManager->unregisterAddressBook($addressbook); - } - else { - $this->key = $addressbook->getKey(); - } + $uid = \OC::$server->getUserSession()->getUser()->getUID(); + $cardDavBackend = \OC::$server->get(\OCA\DAV\CardDAV\CardDavBackend::class); + $principalUri = 'principals/users/'. $uid; + $addressBookId = $cardDavBackend->getAddressBooksByUri($principalUri, self::URI)->id; + if (empty($addressBookId)) { + $addressBookId = $cardDavBackend->createAddressBook($principalUri, self::URI, array_filter([ + '{DAV:}displayname' => 'Webmail', + '{urn:ietf:params:xml:ns:carddav}addressbook-description' => 'Recipients from snappymail', + ])); } + $this->key = $addressBookId; } public function IsSupported() : bool { From b0a6d3b0ef16bc2baf935c05f2d28e4cce5f695b Mon Sep 17 00:00:00 2001 From: Nivesh Krishna Date: Wed, 16 Aug 2023 00:16:28 +0530 Subject: [PATCH 08/28] fix addressbookid --- plugins/nextcloud/NextcloudAddressBook.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index e4ce6711c0..64b969e94b 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -15,12 +15,14 @@ function __construct() $uid = \OC::$server->getUserSession()->getUser()->getUID(); $cardDavBackend = \OC::$server->get(\OCA\DAV\CardDAV\CardDavBackend::class); $principalUri = 'principals/users/'. $uid; - $addressBookId = $cardDavBackend->getAddressBooksByUri($principalUri, self::URI)->id; - if (empty($addressBookId)) { + $addressBookId = $cardDavBackend->getAddressBooksByUri($principalUri, self::URI); + if ($addressBookId === null) { $addressBookId = $cardDavBackend->createAddressBook($principalUri, self::URI, array_filter([ '{DAV:}displayname' => 'Webmail', '{urn:ietf:params:xml:ns:carddav}addressbook-description' => 'Recipients from snappymail', ])); + } else { + $addressBookId = $addressBookId['id']; } $this->key = $addressBookId; } From 6f61b06bbb4ac2a3db977a80f535fb26e911bec5 Mon Sep 17 00:00:00 2001 From: Nivesh Krishna Date: Thu, 24 Aug 2023 13:00:10 +0530 Subject: [PATCH 09/28] add firstname to contacts --- plugins/nextcloud/NextcloudAddressBook.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index 64b969e94b..c301b82375 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -82,7 +82,7 @@ public function IncFrec(array $aEmails, bool $bCreateAuto = true) : bool { $properties = []; foreach ($aEmails as $sEmail => $sAddress) { $properties['EMAIL'] = $sAddress; - $sFullName = \trim(\MailSo\Mime\Email::Parse(\trim($sAddress))->GetDisplayName()); + $sFullName = ucfirst(strstr($sAddress, '@', true)); if ('' !== $sFullName) { $properties['FN'] = $sFullName; } From 8a4eabe699470fa6a41e3813a28f07d85a81c369 Mon Sep 17 00:00:00 2001 From: Akhil Date: Thu, 31 Aug 2023 19:56:27 +0530 Subject: [PATCH 10/28] Add IsExternal for external contact sources Signed-off-by: Akhil --- dev/Stores/User/App.js | 2 +- plugins/kolab/KolabAddressBook.php | 5 +++++ plugins/nextcloud/NextcloudAddressBook.php | 5 +++++ snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php | 1 + .../v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php | 1 + .../v/0.0.0/app/libraries/RainLoop/Providers/AddressBook.php | 5 +++++ .../RainLoop/Providers/AddressBook/AddressBookInterface.php | 2 ++ .../RainLoop/Providers/AddressBook/PdoAddressBook.php | 5 +++++ 8 files changed, 25 insertions(+), 1 deletion(-) diff --git a/dev/Stores/User/App.js b/dev/Stores/User/App.js index 9825c8951e..0a8723c409 100644 --- a/dev/Stores/User/App.js +++ b/dev/Stores/User/App.js @@ -4,7 +4,7 @@ import { ThemeStore } from 'Stores/Theme'; import { arePopupsVisible } from 'Knoin/Knoin'; export const AppUserStore = { - allowContacts: () => !!SettingsGet('contactsAllowed') + allowContacts: () => !!SettingsGet('contactsAllowed') && !!SettingsGet('contactsExternal') }; addObservablesTo(AppUserStore, { diff --git a/plugins/kolab/KolabAddressBook.php b/plugins/kolab/KolabAddressBook.php index 8c7df93167..1e01b216a1 100644 --- a/plugins/kolab/KolabAddressBook.php +++ b/plugins/kolab/KolabAddressBook.php @@ -99,6 +99,11 @@ public function IsSupported() : bool return true; } + public function IsExternal(): bool + { + return false; + } + public function SetEmail(string $sEmail) : bool { return true; diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index c301b82375..4ba57fc5bb 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -33,6 +33,11 @@ public function IsSupported() : bool { return true; } + public function IsExternal(): bool + { + return true; + } + public function SetEmail(string $sEmail) : bool { return true; } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php index eb7356db58..3ebb1de279 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -678,6 +678,7 @@ public function AppData(bool $bAdmin): array 'accountSignMe' => isset($_COOKIE[self::AUTH_SIGN_ME_TOKEN_KEY]), 'contactsAllowed' => $this->AddressBookProvider($oAccount)->IsActive(), + 'contactsExternal' => $this->AddressBookProvider($oAccount)->IsExternal(), 'ViewHTML' => (bool) $oConfig->Get('defaults', 'view_html', true), 'ViewImages' => $oConfig->Get('defaults', 'view_images', 'ask'), diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php index 7316ddc2e1..7c9724e7a2 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php @@ -202,6 +202,7 @@ public function getAccountData(Account $oAccount): array 'accountHash' => $oAccount->Hash(), 'mainEmail' => \RainLoop\Api::Actions()->getMainAccountFromToken()->Email(), 'contactsAllowed' => $this->AddressBookProvider($oAccount)->IsActive(), + 'contactsExternal' => $this->AddressBookProvider($oAccount)->IsExternal(), 'HideUnsubscribed' => false, 'UseThreads' => (bool) $oConfig->Get('defaults', 'mail_use_threads', false), 'ReplySameFolder' => (bool) $oConfig->Get('defaults', 'mail_reply_same_folder', false), diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook.php index affaecd998..332836449a 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook.php @@ -25,6 +25,11 @@ public function IsActive() : bool return $this->oDriver && $this->oDriver->IsSupported(); } + public function IsExternal() : bool + { + return $this->IsActive() ? $this->oDriver->IsExternal() : false; + } + public function Sync() : bool { return $this->IsActive() ? $this->oDriver->Sync() : false; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/AddressBookInterface.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/AddressBookInterface.php index 564a0d48b3..50d7732445 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/AddressBookInterface.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/AddressBookInterface.php @@ -6,6 +6,8 @@ interface AddressBookInterface { public function IsSupported() : bool; + public function IsExternal() : bool; + public function SetEmail(string $sEmail) : bool; public function Sync() : bool; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php index fbf5aeebc0..76af282f32 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php @@ -76,6 +76,11 @@ public function IsSupported() : bool return \is_array($aDrivers) && \in_array($this->settings->driver, $aDrivers); } + public function IsExternal(): bool + { + return false; + } + public function SetEmail(string $sEmail) : bool { $this->iUserID = $this->getUserId($sEmail); From b84487f4d6e6894901cb2376d8c6d40fcd053e36 Mon Sep 17 00:00:00 2001 From: Akhil Date: Thu, 31 Aug 2023 20:20:51 +0530 Subject: [PATCH 11/28] Fix IncFrec logic to actually create or update --- plugins/nextcloud/NextcloudAddressBook.php | 38 ++++++++++++++++++---- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index 4ba57fc5bb..a85ec9c900 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -78,18 +78,44 @@ public function GetSuggestions(string $sSearch, int $iLimit = 20) : array { return []; } + private function GetEmailObjects(array $aEmails) : array { + $aEmailsObjects = \array_map(function ($mItem) { + $oResult = null; + try { + $oResult = \MailSo\Mime\Email::Parse(\trim($mItem)); + } + catch (\Throwable $oException) { + unset($oException); + } + return $oResult; + }, $aEmails); + + $aEmailsObjects = \array_filter($aEmailsObjects, function ($oItem) { + return !!$oItem; + }); + return $aEmailsObjects; + } + /** * Add/increment email address usage * Handy for "most used" sorting suggestions in PdoAddressBook */ public function IncFrec(array $aEmails, bool $bCreateAuto = true) : bool { if ($bCreateAuto) { - $properties = []; - foreach ($aEmails as $sEmail => $sAddress) { - $properties['EMAIL'] = $sAddress; - $sFullName = ucfirst(strstr($sAddress, '@', true)); - if ('' !== $sFullName) { - $properties['FN'] = $sFullName; + $aEmailsObjects = $this->GetEmailObjects($aEmails); + foreach ($aEmailsObjects as $oEmail) { + $properties = []; + if ('' === \trim($oEmail->GetEmail())) { + continue; + } + $sEmail = \trim($oEmail->GetEmail(true)); + $existingResults = $this->contactsManager->search($sEmail, ['EMAIL'], ['strict_search' => true]); + if (!empty($existingResults)) { + $properties['URI'] = $existingResults[0]['UID'] . '.vcf'; + } + $properties['EMAIL'] = \trim($oEmail->GetEmail(true)); + if ('' !== \trim($oEmail->GetDisplayName())) { + $properties['FN'] = $oEmail->GetDisplayName(); } $this->contactsManager->createOrUpdate($properties, $this->key); } From d77e8633cebbb124d3641bdc3fe25aee8412c0f7 Mon Sep 17 00:00:00 2001 From: Akhil Date: Mon, 4 Sep 2023 15:37:45 +0530 Subject: [PATCH 12/28] Bump version to 3.0 --- plugins/nextcloud/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/nextcloud/index.php b/plugins/nextcloud/index.php index 718ca69b31..2b68d41928 100644 --- a/plugins/nextcloud/index.php +++ b/plugins/nextcloud/index.php @@ -4,7 +4,7 @@ class NextcloudPlugin extends \RainLoop\Plugins\AbstractPlugin { const NAME = 'Nextcloud', - VERSION = '2.23', + VERSION = '3.0', RELEASE = '2023-04-11', CATEGORY = 'Integrations', DESCRIPTION = 'Integrate with Nextcloud v20+', From 46cfa9ffa184501a79e25dfc7060a33d79e1f847 Mon Sep 17 00:00:00 2001 From: Akhil Date: Mon, 4 Sep 2023 17:17:41 +0530 Subject: [PATCH 13/28] Unregister system addressbook --- plugins/nextcloud/NextcloudAddressBook.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index a85ec9c900..e17deffb6e 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -12,6 +12,12 @@ class NextcloudAddressBook implements \RainLoop\Providers\AddressBook\AddressBoo function __construct() { $this->contactsManager = \OC::$server->getContactsManager(); + + foreach($this->contactsManager->getUserAddressBooks() as $addressBook) { + if($addressBook->isSystemAddressBook()) { + $this->contactsManager->unregisterAddressBook($addressBook); + } + } $uid = \OC::$server->getUserSession()->getUser()->getUID(); $cardDavBackend = \OC::$server->get(\OCA\DAV\CardDAV\CardDavBackend::class); $principalUri = 'principals/users/'. $uid; @@ -103,6 +109,10 @@ private function GetEmailObjects(array $aEmails) : array { public function IncFrec(array $aEmails, bool $bCreateAuto = true) : bool { if ($bCreateAuto) { $aEmailsObjects = $this->GetEmailObjects($aEmails); + + if (!count($aEmailsObjects)) { + return false; + } foreach ($aEmailsObjects as $oEmail) { $properties = []; if ('' === \trim($oEmail->GetEmail())) { @@ -113,7 +123,7 @@ public function IncFrec(array $aEmails, bool $bCreateAuto = true) : bool { if (!empty($existingResults)) { $properties['URI'] = $existingResults[0]['UID'] . '.vcf'; } - $properties['EMAIL'] = \trim($oEmail->GetEmail(true)); + $properties['EMAIL'] = \trim($sEmail); if ('' !== \trim($oEmail->GetDisplayName())) { $properties['FN'] = $oEmail->GetDisplayName(); } From cc25129a5e7b8f8fabf98544ef5d58a93733f773 Mon Sep 17 00:00:00 2001 From: Akhil Date: Fri, 8 Sep 2023 14:04:37 +0530 Subject: [PATCH 14/28] Fix namespace and FN default --- plugins/nextcloud/NextcloudAddressBook.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index e17deffb6e..ed2d24d438 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -1,10 +1,9 @@ GetDisplayName())) { $properties['FN'] = $oEmail->GetDisplayName(); + } else { + $properties['FN'] = \trim($sEmail); } $this->contactsManager->createOrUpdate($properties, $this->key); } From 3c7ef4df46bff00647328eae66865013a5d392ed Mon Sep 17 00:00:00 2001 From: Akhil Date: Fri, 19 Jan 2024 16:22:12 +0530 Subject: [PATCH 15/28] Fix issue when contact is found in some other addressbook Signed-off-by: Akhil --- plugins/nextcloud/NextcloudAddressBook.php | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index ed2d24d438..2571854764 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -113,20 +113,26 @@ public function IncFrec(array $aEmails, bool $bCreateAuto = true) : bool { return false; } foreach ($aEmailsObjects as $oEmail) { - $properties = []; if ('' === \trim($oEmail->GetEmail())) { continue; } $sEmail = \trim($oEmail->GetEmail(true)); - $existingResults = $this->contactsManager->search($sEmail, ['EMAIL'], ['strict_search' => true]); - if (!empty($existingResults)) { - $properties['URI'] = $existingResults[0]['UID'] . '.vcf'; - } - $properties['EMAIL'] = \trim($sEmail); + + $properties = [ + 'EMAIL' => $sEmail, + 'FN' => $sEmail + ]; + if ('' !== \trim($oEmail->GetDisplayName())) { $properties['FN'] = $oEmail->GetDisplayName(); - } else { - $properties['FN'] = \trim($sEmail); + } + $existingResults = $this->contactsManager->search($sEmail, ['EMAIL'], ['strict_search' => true]); + + foreach ($existingResults as $contact) { + if ($contact['addressbook-key'] === $this->key) { + $properties['URI'] = $contact['UID'] . '.vcf'; + break; + } } $this->contactsManager->createOrUpdate($properties, $this->key); } From cdaa4b1434824d91c601f3d423da1f3969528393 Mon Sep 17 00:00:00 2001 From: Akhil Date: Fri, 19 Jan 2024 19:34:24 +0530 Subject: [PATCH 16/28] Do not save contact if it already exists Signed-off-by: Akhil --- plugins/nextcloud/NextcloudAddressBook.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index 2571854764..2790e4e5c9 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -117,6 +117,11 @@ public function IncFrec(array $aEmails, bool $bCreateAuto = true) : bool { continue; } $sEmail = \trim($oEmail->GetEmail(true)); + $existingResults = $this->contactsManager->search($sEmail, ['EMAIL'], ['strict_search' => true]); + + if (!empty($existingResults)) { + continue; + } $properties = [ 'EMAIL' => $sEmail, @@ -126,14 +131,6 @@ public function IncFrec(array $aEmails, bool $bCreateAuto = true) : bool { if ('' !== \trim($oEmail->GetDisplayName())) { $properties['FN'] = $oEmail->GetDisplayName(); } - $existingResults = $this->contactsManager->search($sEmail, ['EMAIL'], ['strict_search' => true]); - - foreach ($existingResults as $contact) { - if ($contact['addressbook-key'] === $this->key) { - $properties['URI'] = $contact['UID'] . '.vcf'; - break; - } - } $this->contactsManager->createOrUpdate($properties, $this->key); } return true; From 500b997f91abeec90df0fceb994edf0ea56ad802 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Thu, 29 Aug 2024 14:09:18 +0600 Subject: [PATCH 17/28] feat: add addressBook user settings section for nextcloud plugin --- plugins/nextcloud/NextcloudAddressBook.php | 100 +++++++++---- plugins/nextcloud/index.php | 139 +++++++++++++----- plugins/nextcloud/js/addressbook.js | 36 +++++ plugins/nextcloud/langs/de.json | 3 +- plugins/nextcloud/langs/en.json | 3 +- plugins/nextcloud/langs/pl.json | 3 +- plugins/nextcloud/langs/ru.json | 3 +- plugins/nextcloud/langs/zh-TW.json | 3 +- plugins/nextcloud/langs/zh.json | 3 +- .../templates/AddressBookSettings.html | 12 ++ 10 files changed, 232 insertions(+), 73 deletions(-) create mode 100644 plugins/nextcloud/js/addressbook.js create mode 100644 plugins/nextcloud/templates/AddressBookSettings.html diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index 2790e4e5c9..4d3d06de62 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -1,38 +1,44 @@ GetSavedAddressBookKey(); + } + + private function GetSavedAddressBookKey(): string { $this->contactsManager = \OC::$server->getContactsManager(); - foreach($this->contactsManager->getUserAddressBooks() as $addressBook) { - if($addressBook->isSystemAddressBook()) { - $this->contactsManager->unregisterAddressBook($addressBook); + foreach ($this->contactsManager->getUserAddressBooks() as $addressBook) { + if ($addressBook->isSystemAddressBook()) { + $this->contactsManager->unregisterAddressBook($addressBook); } } $uid = \OC::$server->getUserSession()->getUser()->getUID(); $cardDavBackend = \OC::$server->get(\OCA\DAV\CardDAV\CardDavBackend::class); - $principalUri = 'principals/users/'. $uid; - $addressBookId = $cardDavBackend->getAddressBooksByUri($principalUri, self::URI); + $principalUri = 'principals/users/' . $uid; + $uri = $this->GetSavedUri(); + $addressBookId = $cardDavBackend->getAddressBooksByUri($principalUri, $uri); if ($addressBookId === null) { - $addressBookId = $cardDavBackend->createAddressBook($principalUri, self::URI, array_filter([ - '{DAV:}displayname' => 'Webmail', - '{urn:ietf:params:xml:ns:carddav}addressbook-description' => 'Recipients from snappymail', - ])); + $addressBookId = $cardDavBackend->createAddressBook($principalUri, $uri, array_filter([ + '{DAV:}displayname' => 'WebMail', + '{urn:ietf:params:xml:ns:carddav}addressbook-description' => 'Recipients from snappymail', + ])); } else { $addressBookId = $addressBookId['id']; } - $this->key = $addressBookId; + return $addressBookId; } - public function IsSupported() : bool { + public function IsSupported(): bool + { // Maybe just return true, contacts app is just a frontend //return \OC::$server->getAppManager()->isEnabledForUser('contacts'); return true; @@ -43,53 +49,63 @@ public function IsExternal(): bool return true; } - public function SetEmail(string $sEmail) : bool { + public function SetEmail(string $sEmail): bool + { return true; } - public function Sync() : bool { + public function Sync(): bool + { return false; } - public function Export(string $sType = 'vcf') : bool { + public function Export(string $sType = 'vcf'): bool + { return false; } - public function ContactSave(Contact $oContact) : bool { + public function ContactSave(Contact $oContact): bool + { return false; } - public function DeleteContacts(array $aContactIds) : bool { + public function DeleteContacts(array $aContactIds): bool + { return false; } - public function DeleteAllContacts(string $sEmail) : bool { + public function DeleteAllContacts(string $sEmail): bool + { return false; } - public function GetContacts(int $iOffset = 0, int $iLimit = 20, string $sSearch = '', int &$iResultCount = 0) : array { + public function GetContacts(int $iOffset = 0, int $iLimit = 20, string $sSearch = '', int &$iResultCount = 0): array + { return []; } - public function GetContactByEmail(string $sEmail) : ?Contact { + public function GetContactByEmail(string $sEmail): ?Contact + { return null; } - public function GetContactByID($mID, bool $bIsStrID = false) : ?Contact { + public function GetContactByID($mID, bool $bIsStrID = false): ?Contact + { return null; } - public function GetSuggestions(string $sSearch, int $iLimit = 20) : array { + public function GetSuggestions(string $sSearch, int $iLimit = 20): array + { return []; } - private function GetEmailObjects(array $aEmails) : array { + private function GetEmailObjects(array $aEmails): array + { $aEmailsObjects = \array_map(function ($mItem) { $oResult = null; try { $oResult = \MailSo\Mime\Email::Parse(\trim($mItem)); - } - catch (\Throwable $oException) { + } catch (\Throwable $oException) { unset($oException); } return $oResult; @@ -105,20 +121,21 @@ private function GetEmailObjects(array $aEmails) : array { * Add/increment email address usage * Handy for "most used" sorting suggestions in PdoAddressBook */ - public function IncFrec(array $aEmails, bool $bCreateAuto = true) : bool { + public function IncFrec(array $aEmails, bool $bCreateAuto = true): bool + { if ($bCreateAuto) { $aEmailsObjects = $this->GetEmailObjects($aEmails); if (!count($aEmailsObjects)) { return false; } - foreach ($aEmailsObjects as $oEmail) { + foreach ($aEmailsObjects as $oEmail) { if ('' === \trim($oEmail->GetEmail())) { continue; } $sEmail = \trim($oEmail->GetEmail(true)); $existingResults = $this->contactsManager->search($sEmail, ['EMAIL'], ['strict_search' => true]); - + if (!empty($existingResults)) { continue; } @@ -127,20 +144,39 @@ public function IncFrec(array $aEmails, bool $bCreateAuto = true) : bool { 'EMAIL' => $sEmail, 'FN' => $sEmail ]; - + if ('' !== \trim($oEmail->GetDisplayName())) { $properties['FN'] = $oEmail->GetDisplayName(); } - $this->contactsManager->createOrUpdate($properties, $this->key); + $this->contactsManager->createOrUpdate($properties, $this->GetSavedAddressBookKey()); } return true; } return false; } - public function Test() : string { + public function Test(): string + { return ''; } + private function Account(): \RainLoop\Model\Account + { + return \RainLoop\Api::Actions()->getAccountFromToken(); + } + private function SettingsProvider(): \RainLoop\Providers\Settings + { + return \RainLoop\Api::Actions()->SettingsProvider(true); + } + + private function Settings(): \RainLoop\Settings + { + return $this->SettingsProvider()->Load($this->Account()); + } + + private function GetSavedUri(): string + { + return $this->Settings()->GetConf('NextCloudAddressBookUri', 'webmail'); + } } diff --git a/plugins/nextcloud/index.php b/plugins/nextcloud/index.php index 614f1bcfbf..04bc3a0843 100644 --- a/plugins/nextcloud/index.php +++ b/plugins/nextcloud/index.php @@ -10,7 +10,7 @@ class NextcloudPlugin extends \RainLoop\Plugins\AbstractPlugin DESCRIPTION = 'Integrate with Nextcloud v20+', REQUIRED = '2.36.2'; - public function Init() : void + public function Init(): void { if (static::IsIntegrated()) { \SnappyMail\Log::debug('Nextcloud', 'integrated'); @@ -36,11 +36,16 @@ public function Init() : void $this->addTemplate('templates/PopupsNextcloudFiles.html'); $this->addTemplate('templates/PopupsNextcloudCalendars.html'); -// $this->addHook('login.credentials.step-2', 'loginCredentials2'); -// $this->addHook('login.credentials', 'loginCredentials'); + // $this->addHook('login.credentials.step-2', 'loginCredentials2'); + // $this->addHook('login.credentials', 'loginCredentials'); $this->addHook('imap.before-login', 'beforeLogin'); $this->addHook('smtp.before-login', 'beforeLogin'); $this->addHook('sieve.before-login', 'beforeLogin'); + + $this->addJs('js/addressbook.js'); // add js file + $this->addTemplate('templates/AddressBookSettings.html'); + $this->addJsonHook('JsonGetAddressbooks', 'GetAddressBooks'); + $this->addJsonHook('NextcloudUpdateAddressBook', 'UpdateAddressBook'); } else { \SnappyMail\Log::debug('Nextcloud', 'NOT integrated'); // \OC::$server->getConfig()->getAppValue('snappymail', 'snappymail-no-embed'); @@ -48,6 +53,48 @@ public function Init() : void } } + public function GetAddressBooks() + { + $addressBooks = []; + + $contactsManager = \OC::$server->getContactsManager(); + + $selectedUri = $this->Settings()->GetConf('NextCloudAddressBookUri', 'webmail'); + + foreach ($contactsManager->getUserAddressBooks() as $addressBook) { + if ($addressBook->isSystemAddressBook()) { + $contactsManager->unregisterAddressBook($addressBook); + continue; + } + + $book = new AddressBook(); + $book->uri = $addressBook->getUri(); + $book->name = $addressBook->getDisplayName(); + if (strcmp($selectedUri, $book->uri) === 0) { + $book->selected = true; + } + + $addressBooks[] = $book; + } + + + return $this->jsonResponse(__FUNCTION__, array( + 'addressbooks' => json_encode($addressBooks) + )); + } + + public function UpdateAddressBook(): array + { + $uri = $this->jsonParam('uri'); + $oSettings = $this->Settings(); + if (\is_string($uri)) { + $oSettings->SetConf('NextCloudAddressBookUri', $uri); + $this->SettingsProvider()->Save($this->Account(), $oSettings); + } + return $this->jsonResponse(__FUNCTION__, true); + } + + public function ContentSecurityPolicy(\SnappyMail\HTTP\CSP $CSP) { if (\method_exists($CSP, 'add')) { @@ -55,7 +102,7 @@ public function ContentSecurityPolicy(\SnappyMail\HTTP\CSP $CSP) } } - public function Supported() : string + public function Supported(): string { return static::IsIntegrated() ? '' : 'Nextcloud not found to use this plugin'; } @@ -70,24 +117,24 @@ public static function IsLoggedIn() return static::IsIntegrated() && \OC::$server->getUserSession()->isLoggedIn(); } - public function loginCredentials(string &$sEmail, string &$sLogin, ?string &$sPassword = null) : void + public function loginCredentials(string &$sEmail, string &$sLogin, ?string &$sPassword = null): void { /** * This has an issue. * When user changes email address, all settings are gone as the new * _data_/_default_/storage/{domain}/{local-part} is used */ -// $ocUser = \OC::$server->getUserSession()->getUser(); -// $sEmail = $ocUser->getEMailAddress() ?: $ocUser->getPrimaryEMailAddress() ?: $sEmail; + // $ocUser = \OC::$server->getUserSession()->getUser(); + // $sEmail = $ocUser->getEMailAddress() ?: $ocUser->getPrimaryEMailAddress() ?: $sEmail; } - public function loginCredentials2(string &$sEmail, ?string &$sPassword = null) : void + public function loginCredentials2(string &$sEmail, ?string &$sPassword = null): void { $ocUser = \OC::$server->getUserSession()->getUser(); $sEmail = $ocUser->getEMailAddress() ?: $ocUser->getPrimaryEMailAddress() ?: $sEmail; } - public function beforeLogin(\RainLoop\Model\Account $oAccount, \MailSo\Net\NetClient $oClient, \MailSo\Net\ConnectSettings $oSettings) : void + public function beforeLogin(\RainLoop\Model\Account $oAccount, \MailSo\Net\NetClient $oClient, \MailSo\Net\ConnectSettings $oSettings): void { // https://apps.nextcloud.com/apps/oidc_login $config = \OC::$server->getConfig(); @@ -104,11 +151,12 @@ public function beforeLogin(\RainLoop\Model\Account $oAccount, \MailSo\Net\NetCl // Only login with OIDC access token if // it is enabled in config, the user is currently logged in with OIDC, // the current snappymail account is the OIDC account and no account defined explicitly - if (\OC::$server->getConfig()->getAppValue('snappymail', 'snappymail-autologin-oidc', false) - && \OC::$server->getSession()->get('is_oidc') - && $sNcEmail === $oSettings->username - && !$bAccountDefinedExplicitly -// && $oClient->supportsAuthType('OAUTHBEARER') // v2.28 + if ( + \OC::$server->getConfig()->getAppValue('snappymail', 'snappymail-autologin-oidc', false) + && \OC::$server->getSession()->get('is_oidc') + && $sNcEmail === $oSettings->username + && !$bAccountDefinedExplicitly + // && $oClient->supportsAuthType('OAUTHBEARER') // v2.28 ) { $sAccessToken = \OC::$server->getSession()->get('oidc_access_token'); if ($sAccessToken) { @@ -123,7 +171,7 @@ public function beforeLogin(\RainLoop\Model\Account $oAccount, \MailSo\Net\NetCl \OC::$server->getLDAPProvider(); */ - public function NextcloudAttachFile() : array + public function NextcloudAttachFile(): array { $aResult = [ 'success' => false, @@ -147,10 +195,10 @@ public function NextcloudAttachFile() : array return $this->jsonResponse(__FUNCTION__, $aResult); } - public function NextcloudSaveMsg() : array + public function NextcloudSaveMsg(): array { $sSaveFolder = \ltrim($this->jsonParam('folder', ''), '/'); -// $aValues = \RainLoop\Api::Actions()->decodeRawKey($this->jsonParam('msgHash', '')); + // $aValues = \RainLoop\Api::Actions()->decodeRawKey($this->jsonParam('msgHash', '')); $msgHash = $this->jsonParam('msgHash', ''); $aValues = \json_decode(\MailSo\Base\Utils::UrlSafeBase64Decode($msgHash), true); $aResult = [ @@ -204,14 +252,14 @@ public function DoAttachmentsActions(\SnappyMail\AttachmentsAction $data) foreach ($data->items as $aItem) { $sSavedFileName = empty($aItem['fileName']) ? 'file.dat' : $aItem['fileName']; if (!empty($aItem['data'])) { - $sSavedFileNameFull = static::SmartFileExists($sSaveFolder.'/'.$sSavedFileName, $oFiles); + $sSavedFileNameFull = static::SmartFileExists($sSaveFolder . '/' . $sSavedFileName, $oFiles); if (!$oFiles->file_put_contents($sSavedFileNameFull, $aItem['data'])) { $data->result = false; } } else if (!empty($aItem['fileHash'])) { $fFile = $data->filesProvider->GetFile($data->account, $aItem['fileHash'], 'rb'); if (\is_resource($fFile)) { - $sSavedFileNameFull = static::SmartFileExists($sSaveFolder.'/'.$sSavedFileName, $oFiles); + $sSavedFileNameFull = static::SmartFileExists($sSaveFolder . '/' . $sSavedFileName, $oFiles); if (!$oFiles->file_put_contents($sSavedFileNameFull, $fFile)) { $data->result = false; } @@ -225,19 +273,19 @@ public function DoAttachmentsActions(\SnappyMail\AttachmentsAction $data) } } - public function FilterAppData($bAdmin, &$aResult) : void + public function FilterAppData($bAdmin, &$aResult): void { if (!$bAdmin && \is_array($aResult)) { $ocUser = \OC::$server->getUserSession()->getUser(); $sUID = $ocUser->getUID(); $oUrlGen = \OC::$server->getURLGenerator(); $sWebDAV = $oUrlGen->getAbsoluteURL($oUrlGen->linkTo('', 'remote.php') . '/dav'); -// $sWebDAV = \OCP\Util::linkToRemote('dav'); + // $sWebDAV = \OCP\Util::linkToRemote('dav'); $aResult['Nextcloud'] = [ 'UID' => $sUID, 'WebDAV' => $sWebDAV, 'CalDAV' => $this->Config()->Get('plugin', 'calendar', false) -// 'WebDAV_files' => $sWebDAV . '/files/' . $sUID + // 'WebDAV_files' => $sWebDAV . '/files/' . $sUID ]; if (empty($aResult['Auth'])) { $config = \OC::$server->getConfig(); @@ -259,9 +307,9 @@ public function FilterAppData($bAdmin, &$aResult) : void } if (!$sEmail) { $sEmail = $ocUser->getEMailAddress(); -// ?: $ocUser->getPrimaryEMailAddress(); + // ?: $ocUser->getPrimaryEMailAddress(); } -/* + /* if ($config->getAppValue('snappymail', 'snappymail-autologin-oidc', false)) { if (\OC::$server->getSession()->get('is_oidc')) { $sEmail = "{$sUID}@nextcloud"; @@ -308,7 +356,7 @@ public function FilterAppData($bAdmin, &$aResult) : void } } - public function FilterLanguage(&$sLanguage, $bAdmin) : void + public function FilterLanguage(&$sLanguage, $bAdmin): void { if (!\RainLoop\Api::Config()->Get('webmail', 'allow_languages_on_settings', true)) { $aResultLang = \SnappyMail\L10n::getLanguages($bAdmin); @@ -331,7 +379,7 @@ public function FilterLanguage(&$sLanguage, $bAdmin) : void * * @return string return locale */ - private function determineLocale(string $langCode, array $languagesArray) : ?string + private function determineLocale(string $langCode, array $languagesArray): ?string { // Direct check for the language code if (\in_array($langCode, $languagesArray)) { @@ -378,7 +426,7 @@ public function MainFabrica(string $sName, &$mResult) include_once __DIR__ . '/NextcloudAddressBook.php'; $mResult = new NextcloudAddressBook(); } -/* + /* if ($this->Config()->Get('plugin', 'storage', false) && ('storage' === $sName || 'storage-local' === $sName)) { require_once __DIR__ . '/storage.php'; $oDriver = new \NextcloudStorage(APP_PRIVATE_DATA.'storage', $sName === 'storage-local'); @@ -387,7 +435,7 @@ public function MainFabrica(string $sName, &$mResult) } } - protected function configMapping() : array + protected function configMapping(): array { return array( \RainLoop\Plugins\Property::NewInstance('suggestions')->SetLabel('Suggestions') @@ -396,7 +444,7 @@ protected function configMapping() : array \RainLoop\Plugins\Property::NewInstance('ignoreSystemAddressbook')->SetLabel('Ignore system addressbook') ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetDefaultValue(true), -/* + /* \RainLoop\Plugins\Property::NewInstance('storage')->SetLabel('Use Nextcloud user ID in config storage path') ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetDefaultValue(false) @@ -407,7 +455,7 @@ protected function configMapping() : array ); } - private static function SmartFileExists(string $sFilePath, $oFiles) : string + private static function SmartFileExists(string $sFilePath, $oFiles): string { $sFilePath = \str_replace('\\', '/', \trim($sFilePath)); @@ -421,11 +469,10 @@ private static function SmartFileExists(string $sFilePath, $oFiles) : string while (true) { ++$iIndex; - $sFilePathNew = $aFileInfo['dirname'].'/'. - \preg_replace('/\(\d{1,2}\)$/', '', $aFileInfo['filename']). - ' ('.$iIndex.')'. - (empty($aFileInfo['extension']) ? '' : '.'.$aFileInfo['extension']) - ; + $sFilePathNew = $aFileInfo['dirname'] . '/' . + \preg_replace('/\(\d{1,2}\)$/', '', $aFileInfo['filename']) . + ' (' . $iIndex . ')' . + (empty($aFileInfo['extension']) ? '' : '.' . $aFileInfo['extension']); if (!$oFiles->file_exists($sFilePathNew)) { return $sFilePathNew; } @@ -435,4 +482,26 @@ private static function SmartFileExists(string $sFilePath, $oFiles) : string } return $sFilePath; } + + private function Account(): \RainLoop\Model\Account + { + return \RainLoop\Api::Actions()->getAccountFromToken(); + } + + private function SettingsProvider(): \RainLoop\Providers\Settings + { + return \RainLoop\Api::Actions()->SettingsProvider(true); + } + + private function Settings(): \RainLoop\Settings + { + return $this->SettingsProvider()->Load($this->Account()); + } +} + +class AddressBook +{ + public string $uri; + public string $name; + public bool $selected = false; } diff --git a/plugins/nextcloud/js/addressbook.js b/plugins/nextcloud/js/addressbook.js new file mode 100644 index 0000000000..1ce7bfc79e --- /dev/null +++ b/plugins/nextcloud/js/addressbook.js @@ -0,0 +1,36 @@ +(rl => { + if (rl) { + class AddressBookSettings /* extends AbstractViewSettings */ { + constructor() { + this.addressBookList = ko.observableArray(); + this.selectedAddressBook = ko.observable(); + + rl.pluginRemoteRequest((iError, oData) => { + if (!iError) { + const books = JSON.parse(oData.Result.addressbooks); + books.forEach(book => { + this.addressBookList.push(book); + + if (book.selected) { + this.selectedAddressBook(book.uri); + } + }); + + this.selectedAddressBook.subscribe(value => { + rl.pluginRemoteRequest(() => { }, 'NextcloudUpdateAddressBook', { + uri: value + }); + }); + } + }, "JsonGetAddressbooks"); + } + } + + rl.addSettingsViewModel( + AddressBookSettings, + 'AddressBookSettings', + 'NEXTCLOUD/ADDRESS_BOOK', + 'addressbook' + ); + } +})(window.rl); diff --git a/plugins/nextcloud/langs/de.json b/plugins/nextcloud/langs/de.json index 5f43f1357f..a92d94b3ce 100644 --- a/plugins/nextcloud/langs/de.json +++ b/plugins/nextcloud/langs/de.json @@ -9,6 +9,7 @@ "SELECT_CALENDAR": "Kalender auswählen", "FILE_ATTACH": "anfügen", "FILE_INTERNAL": "intern", - "FILE_PUBLIC": "öffentlich" + "FILE_PUBLIC": "öffentlich", + "ADDRESS_BOOK": "Address Book" } } diff --git a/plugins/nextcloud/langs/en.json b/plugins/nextcloud/langs/en.json index 2c19d11c23..b4fb55a971 100644 --- a/plugins/nextcloud/langs/en.json +++ b/plugins/nextcloud/langs/en.json @@ -9,6 +9,7 @@ "SELECT_CALENDAR": "Select calendar", "FILE_ATTACH": "attach", "FILE_INTERNAL": "internal", - "FILE_PUBLIC": "public" + "FILE_PUBLIC": "public", + "ADDRESS_BOOK": "Address Book" } } diff --git a/plugins/nextcloud/langs/pl.json b/plugins/nextcloud/langs/pl.json index 82e0d4f181..57f28aa502 100644 --- a/plugins/nextcloud/langs/pl.json +++ b/plugins/nextcloud/langs/pl.json @@ -9,6 +9,7 @@ "SELECT_CALENDAR": "Wybierz kalendarz", "FILE_ATTACH": "dołącz", "FILE_INTERNAL": "link wewnętrzny", - "FILE_PUBLIC": "link publiczny" + "FILE_PUBLIC": "link publiczny", + "ADDRESS_BOOK": "Address Book" } } diff --git a/plugins/nextcloud/langs/ru.json b/plugins/nextcloud/langs/ru.json index a8b28372d3..4e71257705 100644 --- a/plugins/nextcloud/langs/ru.json +++ b/plugins/nextcloud/langs/ru.json @@ -9,6 +9,7 @@ "SELECT_CALENDAR": "Выбрать календарь", "FILE_ATTACH": "Прикрепить с ПК", "FILE_INTERNAL": "Внутреняя", - "FILE_PUBLIC": "Публичная" + "FILE_PUBLIC": "Публичная", + "ADDRESS_BOOK": "Address Book" } } diff --git a/plugins/nextcloud/langs/zh-TW.json b/plugins/nextcloud/langs/zh-TW.json index 292d022868..14f2276454 100644 --- a/plugins/nextcloud/langs/zh-TW.json +++ b/plugins/nextcloud/langs/zh-TW.json @@ -9,6 +9,7 @@ "SELECT_CALENDAR": "選擇日曆", "FILE_ATTACH": "附加", "FILE_INTERNAL": "內部", - "FILE_PUBLIC": "公開" + "FILE_PUBLIC": "公開", + "ADDRESS_BOOK": "Address Book" } } diff --git a/plugins/nextcloud/langs/zh.json b/plugins/nextcloud/langs/zh.json index 39b20ac2eb..4912213922 100644 --- a/plugins/nextcloud/langs/zh.json +++ b/plugins/nextcloud/langs/zh.json @@ -9,6 +9,7 @@ "SELECT_CALENDAR": "选择日历", "FILE_ATTACH": "附加", "FILE_INTERNAL": "内部", - "FILE_PUBLIC": "公开" + "FILE_PUBLIC": "公开", + "ADDRESS_BOOK": "Address Book" } } diff --git a/plugins/nextcloud/templates/AddressBookSettings.html b/plugins/nextcloud/templates/AddressBookSettings.html new file mode 100644 index 0000000000..e33682515c --- /dev/null +++ b/plugins/nextcloud/templates/AddressBookSettings.html @@ -0,0 +1,12 @@ +
+
AddressBook
+
+ +
+ + +
+ +
+
From a47cc450e81146ed970b5a919b69e19e59ad9a64 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Fri, 30 Aug 2024 13:55:55 +0600 Subject: [PATCH 18/28] feat: move nextcloud addressbook user settings under contatcs settings section --- plugins/nextcloud/NextcloudAddressBook.php | 14 +++-- plugins/nextcloud/index.php | 13 +++-- plugins/nextcloud/js/addressbook.js | 56 ++++++++++--------- .../templates/AddressBookSettings.html | 12 ---- 4 files changed, 46 insertions(+), 49 deletions(-) delete mode 100644 plugins/nextcloud/templates/AddressBookSettings.html diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index 4d3d06de62..aaccb0b316 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -7,6 +7,9 @@ class NextcloudAddressBook implements \RainLoop\Providers\AddressBook\AddressBoo use RainLoop\Providers\AddressBook\CardDAV; private $contactsManager; + private const DEFAULT_URI = 'webmail'; + private const SETTINGS_KEY = 'nextCloudAddressBookUri'; + function __construct() { $this->GetSavedAddressBookKey(); @@ -21,20 +24,21 @@ private function GetSavedAddressBookKey(): string $this->contactsManager->unregisterAddressBook($addressBook); } } + $uid = \OC::$server->getUserSession()->getUser()->getUID(); $cardDavBackend = \OC::$server->get(\OCA\DAV\CardDAV\CardDavBackend::class); $principalUri = 'principals/users/' . $uid; $uri = $this->GetSavedUri(); $addressBookId = $cardDavBackend->getAddressBooksByUri($principalUri, $uri); + if ($addressBookId === null) { - $addressBookId = $cardDavBackend->createAddressBook($principalUri, $uri, array_filter([ + return $cardDavBackend->createAddressBook($principalUri, $uri, array_filter([ '{DAV:}displayname' => 'WebMail', '{urn:ietf:params:xml:ns:carddav}addressbook-description' => 'Recipients from snappymail', ])); - } else { - $addressBookId = $addressBookId['id']; } - return $addressBookId; + + return $addressBookId['id']; } public function IsSupported(): bool @@ -177,6 +181,6 @@ private function Settings(): \RainLoop\Settings private function GetSavedUri(): string { - return $this->Settings()->GetConf('NextCloudAddressBookUri', 'webmail'); + return $this->Settings()->GetConf(self::SETTINGS_KEY, self::DEFAULT_URI); } } diff --git a/plugins/nextcloud/index.php b/plugins/nextcloud/index.php index 04bc3a0843..09164fff0c 100644 --- a/plugins/nextcloud/index.php +++ b/plugins/nextcloud/index.php @@ -10,6 +10,10 @@ class NextcloudPlugin extends \RainLoop\Plugins\AbstractPlugin DESCRIPTION = 'Integrate with Nextcloud v20+', REQUIRED = '2.36.2'; + + private const DEFAULT_ADDRESSBOOK_URI = 'webmail'; + private const ADDRESSBOOK_SETTINGS_KEY = 'nextCloudAddressBookUri'; + public function Init(): void { if (static::IsIntegrated()) { @@ -42,9 +46,8 @@ public function Init(): void $this->addHook('smtp.before-login', 'beforeLogin'); $this->addHook('sieve.before-login', 'beforeLogin'); - $this->addJs('js/addressbook.js'); // add js file - $this->addTemplate('templates/AddressBookSettings.html'); - $this->addJsonHook('JsonGetAddressbooks', 'GetAddressBooks'); + $this->addJs('js/addressbook.js'); + $this->addJsonHook('NextcloudGetAddressBooks', 'GetAddressBooks'); $this->addJsonHook('NextcloudUpdateAddressBook', 'UpdateAddressBook'); } else { \SnappyMail\Log::debug('Nextcloud', 'NOT integrated'); @@ -59,7 +62,7 @@ public function GetAddressBooks() $contactsManager = \OC::$server->getContactsManager(); - $selectedUri = $this->Settings()->GetConf('NextCloudAddressBookUri', 'webmail'); + $selectedUri = $this->Settings()->GetConf(self::ADDRESSBOOK_SETTINGS_KEY, self::DEFAULT_ADDRESSBOOK_URI); foreach ($contactsManager->getUserAddressBooks() as $addressBook) { if ($addressBook->isSystemAddressBook()) { @@ -88,7 +91,7 @@ public function UpdateAddressBook(): array $uri = $this->jsonParam('uri'); $oSettings = $this->Settings(); if (\is_string($uri)) { - $oSettings->SetConf('NextCloudAddressBookUri', $uri); + $oSettings->SetConf(self::ADDRESSBOOK_SETTINGS_KEY, $uri); $this->SettingsProvider()->Save($this->Account(), $oSettings); } return $this->jsonResponse(__FUNCTION__, true); diff --git a/plugins/nextcloud/js/addressbook.js b/plugins/nextcloud/js/addressbook.js index 1ce7bfc79e..c871c0928a 100644 --- a/plugins/nextcloud/js/addressbook.js +++ b/plugins/nextcloud/js/addressbook.js @@ -1,36 +1,38 @@ (rl => { if (rl) { - class AddressBookSettings /* extends AbstractViewSettings */ { - constructor() { - this.addressBookList = ko.observableArray(); - this.selectedAddressBook = ko.observable(); + addEventListener('rl-view-model', e => { + if ('SettingsContacts' === e.detail.viewModelTemplateID) { + const container = e.detail.viewModelDom.querySelector('.form-horizontal'); + if (container) { + rl.pluginRemoteRequest((iError, oData) => { + if (!iError) { + const mainDivElement = Element.fromHTML('
' + + '' + + '
'); - rl.pluginRemoteRequest((iError, oData) => { - if (!iError) { - const books = JSON.parse(oData.Result.addressbooks); - books.forEach(book => { - this.addressBookList.push(book); + const selectElement = Element.fromHTML(''); - if (book.selected) { - this.selectedAddressBook(book.uri); + const books = JSON.parse(oData.Result.addressbooks); + books.forEach(book => { + if (book.selected) { + selectElement.append(Element.fromHTML('')); + } else { + selectElement.append(Element.fromHTML('')); + } + }); + + selectElement.onchange = function() { + rl.pluginRemoteRequest(() => { }, 'NextcloudUpdateAddressBook', { + uri: selectElement.value + }); } - }); - this.selectedAddressBook.subscribe(value => { - rl.pluginRemoteRequest(() => { }, 'NextcloudUpdateAddressBook', { - uri: value - }); - }); - } - }, "JsonGetAddressbooks"); + mainDivElement.append(selectElement); + container.append(mainDivElement); + } + }, "NextcloudGetAddressBooks"); + } } - } - - rl.addSettingsViewModel( - AddressBookSettings, - 'AddressBookSettings', - 'NEXTCLOUD/ADDRESS_BOOK', - 'addressbook' - ); + }); } })(window.rl); diff --git a/plugins/nextcloud/templates/AddressBookSettings.html b/plugins/nextcloud/templates/AddressBookSettings.html deleted file mode 100644 index e33682515c..0000000000 --- a/plugins/nextcloud/templates/AddressBookSettings.html +++ /dev/null @@ -1,12 +0,0 @@ -
-
AddressBook
-
- -
- - -
- -
-
From bda1c28eb76736701cc18605627efe45dc017670 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Fri, 30 Aug 2024 15:58:34 +0600 Subject: [PATCH 19/28] fix: addressbook translation for nextcloud plugin --- plugins/nextcloud/langs/de.json | 2 +- plugins/nextcloud/langs/es.json | 5 +++++ plugins/nextcloud/langs/fr.json | 5 +++++ plugins/nextcloud/langs/it.json | 5 +++++ plugins/nextcloud/langs/pl.json | 3 +-- plugins/nextcloud/langs/ru.json | 3 +-- plugins/nextcloud/langs/zh-TW.json | 3 +-- plugins/nextcloud/langs/zh.json | 3 +-- 8 files changed, 20 insertions(+), 9 deletions(-) create mode 100644 plugins/nextcloud/langs/es.json create mode 100644 plugins/nextcloud/langs/fr.json create mode 100644 plugins/nextcloud/langs/it.json diff --git a/plugins/nextcloud/langs/de.json b/plugins/nextcloud/langs/de.json index a92d94b3ce..35c92421db 100644 --- a/plugins/nextcloud/langs/de.json +++ b/plugins/nextcloud/langs/de.json @@ -10,6 +10,6 @@ "FILE_ATTACH": "anfügen", "FILE_INTERNAL": "intern", "FILE_PUBLIC": "öffentlich", - "ADDRESS_BOOK": "Address Book" + "ADDRESS_BOOK": "Adressbuch" } } diff --git a/plugins/nextcloud/langs/es.json b/plugins/nextcloud/langs/es.json new file mode 100644 index 0000000000..652f678912 --- /dev/null +++ b/plugins/nextcloud/langs/es.json @@ -0,0 +1,5 @@ +{ + "NEXTCLOUD": { + "ADDRESS_BOOK": "Libreta de direcciones" + } +} diff --git a/plugins/nextcloud/langs/fr.json b/plugins/nextcloud/langs/fr.json new file mode 100644 index 0000000000..6396152e67 --- /dev/null +++ b/plugins/nextcloud/langs/fr.json @@ -0,0 +1,5 @@ +{ + "NEXTCLOUD": { + "ADDRESS_BOOK": "Carnet d'adresses" + } +} diff --git a/plugins/nextcloud/langs/it.json b/plugins/nextcloud/langs/it.json new file mode 100644 index 0000000000..7d3f183a1a --- /dev/null +++ b/plugins/nextcloud/langs/it.json @@ -0,0 +1,5 @@ +{ + "NEXTCLOUD": { + "ADDRESS_BOOK": "Rubrica" + } +} diff --git a/plugins/nextcloud/langs/pl.json b/plugins/nextcloud/langs/pl.json index 57f28aa502..82e0d4f181 100644 --- a/plugins/nextcloud/langs/pl.json +++ b/plugins/nextcloud/langs/pl.json @@ -9,7 +9,6 @@ "SELECT_CALENDAR": "Wybierz kalendarz", "FILE_ATTACH": "dołącz", "FILE_INTERNAL": "link wewnętrzny", - "FILE_PUBLIC": "link publiczny", - "ADDRESS_BOOK": "Address Book" + "FILE_PUBLIC": "link publiczny" } } diff --git a/plugins/nextcloud/langs/ru.json b/plugins/nextcloud/langs/ru.json index 4e71257705..a8b28372d3 100644 --- a/plugins/nextcloud/langs/ru.json +++ b/plugins/nextcloud/langs/ru.json @@ -9,7 +9,6 @@ "SELECT_CALENDAR": "Выбрать календарь", "FILE_ATTACH": "Прикрепить с ПК", "FILE_INTERNAL": "Внутреняя", - "FILE_PUBLIC": "Публичная", - "ADDRESS_BOOK": "Address Book" + "FILE_PUBLIC": "Публичная" } } diff --git a/plugins/nextcloud/langs/zh-TW.json b/plugins/nextcloud/langs/zh-TW.json index 14f2276454..292d022868 100644 --- a/plugins/nextcloud/langs/zh-TW.json +++ b/plugins/nextcloud/langs/zh-TW.json @@ -9,7 +9,6 @@ "SELECT_CALENDAR": "選擇日曆", "FILE_ATTACH": "附加", "FILE_INTERNAL": "內部", - "FILE_PUBLIC": "公開", - "ADDRESS_BOOK": "Address Book" + "FILE_PUBLIC": "公開" } } diff --git a/plugins/nextcloud/langs/zh.json b/plugins/nextcloud/langs/zh.json index 4912213922..39b20ac2eb 100644 --- a/plugins/nextcloud/langs/zh.json +++ b/plugins/nextcloud/langs/zh.json @@ -9,7 +9,6 @@ "SELECT_CALENDAR": "选择日历", "FILE_ATTACH": "附加", "FILE_INTERNAL": "内部", - "FILE_PUBLIC": "公开", - "ADDRESS_BOOK": "Address Book" + "FILE_PUBLIC": "公开" } } From 0c9e4717a305315be617a44700ae118ded8ea5d1 Mon Sep 17 00:00:00 2001 From: Akhil Date: Mon, 2 Sep 2024 20:28:03 +0530 Subject: [PATCH 20/28] Remove IsExternal Signed-off-by: Akhil --- dev/Stores/User/App.js | 2 +- plugins/kolab/KolabAddressBook.php | 5 ----- plugins/nextcloud/NextcloudAddressBook.php | 5 ----- snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php | 1 - .../v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php | 1 - .../v/0.0.0/app/libraries/RainLoop/Providers/AddressBook.php | 5 ----- .../RainLoop/Providers/AddressBook/AddressBookInterface.php | 2 -- .../RainLoop/Providers/AddressBook/PdoAddressBook.php | 5 ----- 8 files changed, 1 insertion(+), 25 deletions(-) diff --git a/dev/Stores/User/App.js b/dev/Stores/User/App.js index 0a8723c409..9825c8951e 100644 --- a/dev/Stores/User/App.js +++ b/dev/Stores/User/App.js @@ -4,7 +4,7 @@ import { ThemeStore } from 'Stores/Theme'; import { arePopupsVisible } from 'Knoin/Knoin'; export const AppUserStore = { - allowContacts: () => !!SettingsGet('contactsAllowed') && !!SettingsGet('contactsExternal') + allowContacts: () => !!SettingsGet('contactsAllowed') }; addObservablesTo(AppUserStore, { diff --git a/plugins/kolab/KolabAddressBook.php b/plugins/kolab/KolabAddressBook.php index 1e01b216a1..8c7df93167 100644 --- a/plugins/kolab/KolabAddressBook.php +++ b/plugins/kolab/KolabAddressBook.php @@ -99,11 +99,6 @@ public function IsSupported() : bool return true; } - public function IsExternal(): bool - { - return false; - } - public function SetEmail(string $sEmail) : bool { return true; diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index 2790e4e5c9..9c84e84ed6 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -38,11 +38,6 @@ public function IsSupported() : bool { return true; } - public function IsExternal(): bool - { - return true; - } - public function SetEmail(string $sEmail) : bool { return true; } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php index 3ebb1de279..eb7356db58 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -678,7 +678,6 @@ public function AppData(bool $bAdmin): array 'accountSignMe' => isset($_COOKIE[self::AUTH_SIGN_ME_TOKEN_KEY]), 'contactsAllowed' => $this->AddressBookProvider($oAccount)->IsActive(), - 'contactsExternal' => $this->AddressBookProvider($oAccount)->IsExternal(), 'ViewHTML' => (bool) $oConfig->Get('defaults', 'view_html', true), 'ViewImages' => $oConfig->Get('defaults', 'view_images', 'ask'), diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php index 7c9724e7a2..7316ddc2e1 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php @@ -202,7 +202,6 @@ public function getAccountData(Account $oAccount): array 'accountHash' => $oAccount->Hash(), 'mainEmail' => \RainLoop\Api::Actions()->getMainAccountFromToken()->Email(), 'contactsAllowed' => $this->AddressBookProvider($oAccount)->IsActive(), - 'contactsExternal' => $this->AddressBookProvider($oAccount)->IsExternal(), 'HideUnsubscribed' => false, 'UseThreads' => (bool) $oConfig->Get('defaults', 'mail_use_threads', false), 'ReplySameFolder' => (bool) $oConfig->Get('defaults', 'mail_reply_same_folder', false), diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook.php index 332836449a..affaecd998 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook.php @@ -25,11 +25,6 @@ public function IsActive() : bool return $this->oDriver && $this->oDriver->IsSupported(); } - public function IsExternal() : bool - { - return $this->IsActive() ? $this->oDriver->IsExternal() : false; - } - public function Sync() : bool { return $this->IsActive() ? $this->oDriver->Sync() : false; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/AddressBookInterface.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/AddressBookInterface.php index 50d7732445..564a0d48b3 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/AddressBookInterface.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/AddressBookInterface.php @@ -6,8 +6,6 @@ interface AddressBookInterface { public function IsSupported() : bool; - public function IsExternal() : bool; - public function SetEmail(string $sEmail) : bool; public function Sync() : bool; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php index 76af282f32..3c60f44f33 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php @@ -75,11 +75,6 @@ public function IsSupported() : bool $aDrivers = static::getAvailableDrivers(); return \is_array($aDrivers) && \in_array($this->settings->driver, $aDrivers); } - - public function IsExternal(): bool - { - return false; - } public function SetEmail(string $sEmail) : bool { From 022bf430ffcf687c4307dc94395fdaa370443aaf Mon Sep 17 00:00:00 2001 From: Akhil Date: Mon, 2 Sep 2024 20:30:03 +0530 Subject: [PATCH 21/28] Remove extra space Signed-off-by: Akhil --- .../libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php index 3c60f44f33..fbf5aeebc0 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php @@ -75,7 +75,7 @@ public function IsSupported() : bool $aDrivers = static::getAvailableDrivers(); return \is_array($aDrivers) && \in_array($this->settings->driver, $aDrivers); } - + public function SetEmail(string $sEmail) : bool { $this->iUserID = $this->getUserId($sEmail); From 19ddcfbf3773aafb2b5d186dc9263d53c4538d59 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Mon, 2 Sep 2024 18:41:08 +0600 Subject: [PATCH 22/28] feat: add admin settings for nextcloudAddressbook related changes --- plugins/nextcloud/NextcloudAddressBook.php | 28 ++++++--- plugins/nextcloud/index.php | 60 ++++++++++++++++--- .../nextcloud/js/hideInhouseAddressbook.js | 45 ++++++++++++++ 3 files changed, 116 insertions(+), 17 deletions(-) create mode 100644 plugins/nextcloud/js/hideInhouseAddressbook.js diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index aaccb0b316..a3d8c41fa0 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -7,11 +7,21 @@ class NextcloudAddressBook implements \RainLoop\Providers\AddressBook\AddressBoo use RainLoop\Providers\AddressBook\CardDAV; private $contactsManager; - private const DEFAULT_URI = 'webmail'; private const SETTINGS_KEY = 'nextCloudAddressBookUri'; - function __construct() + private string $defaultUri = 'webmail'; + private string $defaultName = 'WebMail'; + private string $defaultDescription = 'Recipients from snappymail'; + private bool $ignoreSystemAddressBook = true; + + + function __construct(string $defaultUri = 'webmail', string $defaultName = 'WebMail', string $defaultDescription = 'Recipients from snappymail', bool $ignoreSystemAddressBook = true) { + $this->defaultUri = $defaultUri; + $this->defaultName = $defaultName; + $this->defaultDescription = $defaultDescription; + $this->ignoreSystemAddressBook = $ignoreSystemAddressBook; + $this->GetSavedAddressBookKey(); } @@ -19,9 +29,11 @@ private function GetSavedAddressBookKey(): string { $this->contactsManager = \OC::$server->getContactsManager(); - foreach ($this->contactsManager->getUserAddressBooks() as $addressBook) { - if ($addressBook->isSystemAddressBook()) { - $this->contactsManager->unregisterAddressBook($addressBook); + if ($this->ignoreSystemAddressBook) { + foreach ($this->contactsManager->getUserAddressBooks() as $addressBook) { + if ($addressBook->isSystemAddressBook()) { + $this->contactsManager->unregisterAddressBook($addressBook); + } } } @@ -33,8 +45,8 @@ private function GetSavedAddressBookKey(): string if ($addressBookId === null) { return $cardDavBackend->createAddressBook($principalUri, $uri, array_filter([ - '{DAV:}displayname' => 'WebMail', - '{urn:ietf:params:xml:ns:carddav}addressbook-description' => 'Recipients from snappymail', + '{DAV:}displayname' => $this->defaultName, + '{urn:ietf:params:xml:ns:carddav}addressbook-description' => $this->defaultDescription, ])); } @@ -181,6 +193,6 @@ private function Settings(): \RainLoop\Settings private function GetSavedUri(): string { - return $this->Settings()->GetConf(self::SETTINGS_KEY, self::DEFAULT_URI); + return $this->Settings()->GetConf(self::SETTINGS_KEY, $this->defaultUri); } } diff --git a/plugins/nextcloud/index.php b/plugins/nextcloud/index.php index 09164fff0c..337a295bb1 100644 --- a/plugins/nextcloud/index.php +++ b/plugins/nextcloud/index.php @@ -11,6 +11,8 @@ class NextcloudPlugin extends \RainLoop\Plugins\AbstractPlugin REQUIRED = '2.36.2'; + private const DEFAULT_ADDRESSBOOK_NAME = 'WebMail'; + private const DEFAULT_ADDRESSBOOK_DESCRIPTION = 'Recipients from snappymail'; private const DEFAULT_ADDRESSBOOK_URI = 'webmail'; private const ADDRESSBOOK_SETTINGS_KEY = 'nextCloudAddressBookUri'; @@ -46,9 +48,15 @@ public function Init(): void $this->addHook('smtp.before-login', 'beforeLogin'); $this->addHook('sieve.before-login', 'beforeLogin'); - $this->addJs('js/addressbook.js'); - $this->addJsonHook('NextcloudGetAddressBooks', 'GetAddressBooks'); - $this->addJsonHook('NextcloudUpdateAddressBook', 'UpdateAddressBook'); + if ($this->Config()->Get('plugin', 'enableNcAddressbook', false)) { + $this->addJs('js/addressbook.js'); + $this->addJsonHook('NextcloudGetAddressBooks', 'GetAddressBooks'); + $this->addJsonHook('NextcloudUpdateAddressBook', 'UpdateAddressBook'); + } + + if ($this->Config()->Get('plugin', 'disableInhouseAddressbook', false)) { + $this->addJs('js/hideInhouseAddressbook.js'); + } } else { \SnappyMail\Log::debug('Nextcloud', 'NOT integrated'); // \OC::$server->getConfig()->getAppValue('snappymail', 'snappymail-no-embed'); @@ -62,10 +70,12 @@ public function GetAddressBooks() $contactsManager = \OC::$server->getContactsManager(); - $selectedUri = $this->Settings()->GetConf(self::ADDRESSBOOK_SETTINGS_KEY, self::DEFAULT_ADDRESSBOOK_URI); + $defaultUri = $this->Config()->Get('plugin', 'defaultNCAddressbookUri', self::DEFAULT_ADDRESSBOOK_URI); + $selectedUri = $this->UserSettings()->GetConf(self::ADDRESSBOOK_SETTINGS_KEY, $defaultUri); + $ignoreSystemAddressbook = $this->Config()->Get('plugin', 'ignoreSystemAddressbook', true); foreach ($contactsManager->getUserAddressBooks() as $addressBook) { - if ($addressBook->isSystemAddressBook()) { + if ($ignoreSystemAddressbook && $addressBook->isSystemAddressBook()) { $contactsManager->unregisterAddressBook($addressBook); continue; } @@ -89,7 +99,7 @@ public function GetAddressBooks() public function UpdateAddressBook(): array { $uri = $this->jsonParam('uri'); - $oSettings = $this->Settings(); + $oSettings = $this->UserSettings(); if (\is_string($uri)) { $oSettings->SetConf(self::ADDRESSBOOK_SETTINGS_KEY, $uri); $this->SettingsProvider()->Save($this->Account(), $oSettings); @@ -422,12 +432,24 @@ public function MainFabrica(string $sName, &$mResult) $this->Config()->Get('plugin', 'ignoreSystemAddressbook', true) ); } - if ('address-book' === $sName) { + + if ('address-book' === $sName && $this->Config()->Get('plugin', 'enableNcAddressbook', false)) { if (!\is_array($mResult)) { $mResult = array(); } include_once __DIR__ . '/NextcloudAddressBook.php'; - $mResult = new NextcloudAddressBook(); + + $ignoreSystemAddressbook = $this->Config()->Get('plugin', 'ignoreSystemAddressbook', true); + $defaultName = $this->Config()->Get('plugin', 'defaultNCAddressbookName', self::DEFAULT_ADDRESSBOOK_NAME); + $defaultDescription = $this->Config()->Get('plugin', 'defaultNCAddressbookDescription', self::DEFAULT_ADDRESSBOOK_DESCRIPTION); + $defaultUri = $this->Config()->Get('plugin', 'defaultNCAddressbookUri', self::DEFAULT_ADDRESSBOOK_URI); + + $mResult = new NextcloudAddressBook( + $defaultUri, + $defaultName, + $defaultDescription, + $ignoreSystemAddressbook + ); } /* if ($this->Config()->Get('plugin', 'storage', false) && ('storage' === $sName || 'storage-local' === $sName)) { @@ -453,6 +475,26 @@ protected function configMapping(): array ->SetDefaultValue(false) */ \RainLoop\Plugins\Property::NewInstance('calendar')->SetLabel('Enable "Put ICS in calendar"') + ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) + ->SetDefaultValue(false), + + \RainLoop\Plugins\Property::NewInstance('enableNcAddressbook')->SetLabel('Enable User to choose Nextcloud addressbook for recipients') + ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) + ->SetDefaultValue(false), + + \RainLoop\Plugins\Property::NewInstance('defaultNCAddressbookUri')->SetLabel('Default nextcloud addressbook URI for recipinets') + ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING) + ->SetDefaultValue('webmail'), + + \RainLoop\Plugins\Property::NewInstance('defaultNCAddressbookName')->SetLabel('Default nextcloud addressbook Name for recipinets') + ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING) + ->SetDefaultValue(self::DEFAULT_ADDRESSBOOK_NAME), + + \RainLoop\Plugins\Property::NewInstance('defaultNCAddressbookDescription')->SetLabel('Default nextcloud addressbook description for recipinets') + ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING) + ->SetDefaultValue(self::DEFAULT_ADDRESSBOOK_DESCRIPTION), + + \RainLoop\Plugins\Property::NewInstance('disableInhouseAddressbook')->SetLabel('Disable SnappyMail internal addressbook. This is recomended if nextcloud addressbook is being used.') ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetDefaultValue(false) ); @@ -496,7 +538,7 @@ private function SettingsProvider(): \RainLoop\Providers\Settings return \RainLoop\Api::Actions()->SettingsProvider(true); } - private function Settings(): \RainLoop\Settings + private function UserSettings(): \RainLoop\Settings { return $this->SettingsProvider()->Load($this->Account()); } diff --git a/plugins/nextcloud/js/hideInhouseAddressbook.js b/plugins/nextcloud/js/hideInhouseAddressbook.js new file mode 100644 index 0000000000..ed8197e180 --- /dev/null +++ b/plugins/nextcloud/js/hideInhouseAddressbook.js @@ -0,0 +1,45 @@ +(rl => { + if (rl) { + addEventListener('rl-view-model', e => { + if ('MailFolderList' === e.detail.viewModelTemplateID) { + const container = e.detail.viewModelDom.querySelector('.buttonContacts'); + if (container) { + container.remove(); + } + } + }); + + + addEventListener('rl-view-model', e => { + if ('SystemDropDown' === e.detail.viewModelTemplateID) { + const container = e.detail.viewModelDom.querySelector('.dropdown-menu'); + if (container) { + for (i = 0; i < container.children.length; i++) { + const element = container.children[i]; + const attr = element.getAttribute("data-bind"); + if (attr && attr.includes("visible: allowContacts")) { + element.remove(); + break; + } + } + } + } + }); + + addEventListener('rl-view-model', e => { + if ('PopupsCompose' === e.detail.viewModelTemplateID) { + const container = e.detail.viewModelDom.querySelector('.pull-right'); + if (container) { + for (i = 0; i < container.children.length; i++) { + const element = container.children[i]; + const attr = element.getAttribute("data-bind"); + if (attr && attr.includes("visible: allowContacts")) { + element.remove(); + break; + } + } + } + } + }); + } +})(window.rl); From 552a91acc2e7b51c4626d8307c03d9d0268fc48d Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 3 Sep 2024 12:37:37 +0600 Subject: [PATCH 23/28] chore: refactor nexcloud plugin- related to NC-addressbook --- plugins/nextcloud/NextcloudAddressBook.php | 105 ++++++++------ plugins/nextcloud/index.php | 136 ++++++++++-------- plugins/nextcloud/js/addressbook.js | 38 ----- .../nextcloud/js/hideInhouseAddressbook.js | 36 ++--- plugins/nextcloud/js/nextcloudAddressbook.js | 42 ++++++ 5 files changed, 197 insertions(+), 160 deletions(-) delete mode 100644 plugins/nextcloud/js/addressbook.js create mode 100644 plugins/nextcloud/js/nextcloudAddressbook.js diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index 7c8e4afb68..90a8331fe3 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -5,15 +5,15 @@ class NextcloudAddressBook implements \RainLoop\Providers\AddressBook\AddressBookInterface { use RainLoop\Providers\AddressBook\CardDAV; - private $contactsManager; - private const SETTINGS_KEY = 'nextCloudAddressBookUri'; + private const SETTINGS_KEY = 'nextcloudAddressBookUri'; private string $defaultUri = 'webmail'; private string $defaultName = 'WebMail'; private string $defaultDescription = 'Recipients from snappymail'; private bool $ignoreSystemAddressBook = true; + private $contactsManager; function __construct(string $defaultUri = 'webmail', string $defaultName = 'WebMail', string $defaultDescription = 'Recipients from snappymail', bool $ignoreSystemAddressBook = true) { @@ -25,14 +25,21 @@ function __construct(string $defaultUri = 'webmail', string $defaultName = 'WebM $this->GetSavedAddressBookKey(); } - private function GetSavedAddressBookKey(): string + private function getContactsManager() { - $this->contactsManager = \OC::$server->getContactsManager(); + if ($this->contactsManager == null) { + $this->contactsManager = \OC::$server->getContactsManager(); + } + return $this->contactsManager; + } + + private function GetSavedAddressBookKey() : string + { if ($this->ignoreSystemAddressBook) { - foreach ($this->contactsManager->getUserAddressBooks() as $addressBook) { + foreach ($this->getContactsManager()->getUserAddressBooks() as $addressBook) { if ($addressBook->isSystemAddressBook()) { - $this->contactsManager->unregisterAddressBook($addressBook); + $this->getContactsManager()->unregisterAddressBook($addressBook); } } } @@ -53,63 +60,63 @@ private function GetSavedAddressBookKey(): string return $addressBookId['id']; } - public function IsSupported(): bool + public function IsSupported() : bool { // Maybe just return true, contacts app is just a frontend - //return \OC::$server->getAppManager()->isEnabledForUser('contacts'); - return true; + return \OC::$server->getAppManager()->isEnabledForUser('contacts'); } - public function SetEmail(string $sEmail) : bool { + public function SetEmail(string $sEmail) : bool + { return true; } - public function Sync(): bool + public function Sync() : bool { return false; } - public function Export(string $sType = 'vcf'): bool + public function Export(string $sType = 'vcf') : bool { return false; } - public function ContactSave(Contact $oContact): bool + public function ContactSave(Contact $oContact) : bool { return false; } - public function DeleteContacts(array $aContactIds): bool + public function DeleteContacts(array $aContactIds) : bool { return false; } - public function DeleteAllContacts(string $sEmail): bool + public function DeleteAllContacts(string $sEmail) : bool { return false; } - public function GetContacts(int $iOffset = 0, int $iLimit = 20, string $sSearch = '', int &$iResultCount = 0): array + public function GetContacts(int $iOffset = 0, int $iLimit = 20, string $sSearch = '', int &$iResultCount = 0) : array { return []; } - public function GetContactByEmail(string $sEmail): ?Contact + public function GetContactByEmail(string $sEmail) : ?Contact { return null; } - public function GetContactByID($mID, bool $bIsStrID = false): ?Contact + public function GetContactByID($mID, bool $bIsStrID = false) : ?Contact { return null; } - public function GetSuggestions(string $sSearch, int $iLimit = 20): array + public function GetSuggestions(string $sSearch, int $iLimit = 20) : array { return []; } - private function GetEmailObjects(array $aEmails): array + private function GetEmailObjects(array $aEmails) : array { $aEmailsObjects = \array_map(function ($mItem) { $oResult = null; @@ -131,7 +138,7 @@ private function GetEmailObjects(array $aEmails): array * Add/increment email address usage * Handy for "most used" sorting suggestions in PdoAddressBook */ - public function IncFrec(array $aEmails, bool $bCreateAuto = true): bool + public function IncFrec(array $aEmails, bool $bCreateAuto = true) : bool { if ($bCreateAuto) { $aEmailsObjects = $this->GetEmailObjects($aEmails); @@ -139,53 +146,61 @@ public function IncFrec(array $aEmails, bool $bCreateAuto = true): bool if (!count($aEmailsObjects)) { return false; } - foreach ($aEmailsObjects as $oEmail) { - if ('' === \trim($oEmail->GetEmail())) { - continue; - } - $sEmail = \trim($oEmail->GetEmail(true)); - $existingResults = $this->contactsManager->search($sEmail, ['EMAIL'], ['strict_search' => true]); - - if (!empty($existingResults)) { - continue; - } - - $properties = [ - 'EMAIL' => $sEmail, - 'FN' => $sEmail - ]; - if ('' !== \trim($oEmail->GetDisplayName())) { - $properties['FN'] = $oEmail->GetDisplayName(); - } - $this->contactsManager->createOrUpdate($properties, $this->GetSavedAddressBookKey()); + foreach ($aEmailsObjects as $oEmail) { + $this->createOrUpdateContact($oEmail); } + return true; } + return false; } - public function Test(): string + private function createOrUpdateContact($oEmail) + { + if ('' === \trim($oEmail->GetEmail())) { + return; + } + $sEmail = \trim($oEmail->GetEmail(true)); + $existingResults = $this->getContactsManager()->search($sEmail, ['EMAIL'], ['strict_search' => true]); + + if (!empty($existingResults)) { + return; + } + + $properties = [ + 'EMAIL' => $sEmail, + 'FN' => $sEmail + ]; + + if ('' !== \trim($oEmail->GetDisplayName())) { + $properties['FN'] = $oEmail->GetDisplayName(); + } + $this->getContactsManager()->createOrUpdate($properties, $this->GetSavedAddressBookKey()); + } + + public function Test() : string { return ''; } - private function Account(): \RainLoop\Model\Account + private function Account() : \RainLoop\Model\Account { return \RainLoop\Api::Actions()->getAccountFromToken(); } - private function SettingsProvider(): \RainLoop\Providers\Settings + private function SettingsProvider() : \RainLoop\Providers\Settings { return \RainLoop\Api::Actions()->SettingsProvider(true); } - private function Settings(): \RainLoop\Settings + private function Settings() : \RainLoop\Settings { return $this->SettingsProvider()->Load($this->Account()); } - private function GetSavedUri(): string + private function GetSavedUri() : string { return $this->Settings()->GetConf(self::SETTINGS_KEY, $this->defaultUri); } diff --git a/plugins/nextcloud/index.php b/plugins/nextcloud/index.php index 229e534bdb..28adf35fb9 100644 --- a/plugins/nextcloud/index.php +++ b/plugins/nextcloud/index.php @@ -10,13 +10,27 @@ class NextcloudPlugin extends \RainLoop\Plugins\AbstractPlugin DESCRIPTION = 'Integrate with Nextcloud v20+', REQUIRED = '2.36.2'; + private const IGNORE_SYSTEM_ADDRESSBOOK_KEY = 'ignoreSystemAddressbook'; + private const IGNORE_SYSTEM_ADDRESSBOOK_DEFAULT_VALUE = true; + private const ENABLE_NC_ADDRESSBOOK_KEY = 'enableNcAddressbook'; + private const ENABLE_NC_ADDRESSBOOK_DEFAULT_VALUE = false; + + private const DISABLE_INHOUSE_ADDRESSBOOK_KEY = 'disableSnappymailContactsUI'; + private const DISABLE_INHOUSE_ADDRESSBOOK_DEFAULT_VALUE = false; + + private const DEFAULT_ADDRESSBOOK_URI_KEY = 'defaultNCAddressbookUri'; + private const DEFAULT_ADDRESSBOOK_URI = 'webmail'; + + private const DEFAULT_ADDRESSBOOK_NAME_KEY = 'defaultNCAddressbookName'; private const DEFAULT_ADDRESSBOOK_NAME = 'WebMail'; + + private const DEFAULT_ADDRESSBOOK_DESCRIPTION_KEY = 'defaultNCAddressbookDescription'; private const DEFAULT_ADDRESSBOOK_DESCRIPTION = 'Recipients from snappymail'; - private const DEFAULT_ADDRESSBOOK_URI = 'webmail'; - private const ADDRESSBOOK_SETTINGS_KEY = 'nextCloudAddressBookUri'; - public function Init(): void + private const ADDRESSBOOK_SETTINGS_KEY = 'nextcloudAddressBookUri'; + + public function Init() : void { if (static::IsIntegrated()) { \SnappyMail\Log::debug('Nextcloud', 'integrated'); @@ -42,19 +56,19 @@ public function Init(): void $this->addTemplate('templates/PopupsNextcloudFiles.html'); $this->addTemplate('templates/PopupsNextcloudCalendars.html'); - // $this->addHook('login.credentials.step-2', 'loginCredentials2'); - // $this->addHook('login.credentials', 'loginCredentials'); +// $this->addHook('login.credentials.step-2', 'loginCredentials2'); +// $this->addHook('login.credentials', 'loginCredentials'); $this->addHook('imap.before-login', 'beforeLogin'); $this->addHook('smtp.before-login', 'beforeLogin'); $this->addHook('sieve.before-login', 'beforeLogin'); - if ($this->Config()->Get('plugin', 'enableNcAddressbook', false)) { - $this->addJs('js/addressbook.js'); + if ($this->Config()->Get('plugin', self::ENABLE_NC_ADDRESSBOOK_KEY, self::ENABLE_NC_ADDRESSBOOK_DEFAULT_VALUE)) { + $this->addJs('js/nextcloudAddressbook.js'); $this->addJsonHook('NextcloudGetAddressBooks', 'GetAddressBooks'); $this->addJsonHook('NextcloudUpdateAddressBook', 'UpdateAddressBook'); } - if ($this->Config()->Get('plugin', 'disableInhouseAddressbook', false)) { + if ($this->Config()->Get('plugin', self::DISABLE_INHOUSE_ADDRESSBOOK_KEY, self::DISABLE_INHOUSE_ADDRESSBOOK_DEFAULT_VALUE)) { $this->addJs('js/hideInhouseAddressbook.js'); } } else { @@ -70,9 +84,9 @@ public function GetAddressBooks() $contactsManager = \OC::$server->getContactsManager(); - $defaultUri = $this->Config()->Get('plugin', 'defaultNCAddressbookUri', self::DEFAULT_ADDRESSBOOK_URI); + $defaultUri = $this->Config()->Get('plugin', self::DEFAULT_ADDRESSBOOK_URI_KEY, self::DEFAULT_ADDRESSBOOK_URI); $selectedUri = $this->UserSettings()->GetConf(self::ADDRESSBOOK_SETTINGS_KEY, $defaultUri); - $ignoreSystemAddressbook = $this->Config()->Get('plugin', 'ignoreSystemAddressbook', true); + $ignoreSystemAddressbook = $this->Config()->Get('plugin', self::IGNORE_SYSTEM_ADDRESSBOOK_KEY, self::IGNORE_SYSTEM_ADDRESSBOOK_DEFAULT_VALUE); foreach ($contactsManager->getUserAddressBooks() as $addressBook) { if ($ignoreSystemAddressbook && $addressBook->isSystemAddressBook()) { @@ -96,7 +110,7 @@ public function GetAddressBooks() )); } - public function UpdateAddressBook(): array + public function UpdateAddressBook() : array { $uri = $this->jsonParam('uri'); $oSettings = $this->UserSettings(); @@ -115,7 +129,7 @@ public function ContentSecurityPolicy(\SnappyMail\HTTP\CSP $CSP) } } - public function Supported(): string + public function Supported() : string { return static::IsIntegrated() ? '' : 'Nextcloud not found to use this plugin'; } @@ -130,24 +144,24 @@ public static function IsLoggedIn() return static::IsIntegrated() && \OC::$server->getUserSession()->isLoggedIn(); } - public function loginCredentials(string &$sEmail, string &$sLogin, ?string &$sPassword = null): void + public function loginCredentials(string &$sEmail, string &$sLogin, ?string &$sPassword = null) : void { /** * This has an issue. * When user changes email address, all settings are gone as the new * _data_/_default_/storage/{domain}/{local-part} is used */ - // $ocUser = \OC::$server->getUserSession()->getUser(); - // $sEmail = $ocUser->getEMailAddress() ?: $ocUser->getPrimaryEMailAddress() ?: $sEmail; +// $ocUser = \OC::$server->getUserSession()->getUser(); +// $sEmail = $ocUser->getEMailAddress() ?: $ocUser->getPrimaryEMailAddress() ?: $sEmail; } - public function loginCredentials2(string &$sEmail, ?string &$sPassword = null): void + public function loginCredentials2(string &$sEmail, ?string &$sPassword = null) : void { $ocUser = \OC::$server->getUserSession()->getUser(); $sEmail = $ocUser->getEMailAddress() ?: $ocUser->getPrimaryEMailAddress() ?: $sEmail; } - public function beforeLogin(\RainLoop\Model\Account $oAccount, \MailSo\Net\NetClient $oClient, \MailSo\Net\ConnectSettings $oSettings): void + public function beforeLogin(\RainLoop\Model\Account $oAccount, \MailSo\Net\NetClient $oClient, \MailSo\Net\ConnectSettings $oSettings) : void { // https://apps.nextcloud.com/apps/oidc_login $config = \OC::$server->getConfig(); @@ -164,12 +178,11 @@ public function beforeLogin(\RainLoop\Model\Account $oAccount, \MailSo\Net\NetCl // Only login with OIDC access token if // it is enabled in config, the user is currently logged in with OIDC, // the current snappymail account is the OIDC account and no account defined explicitly - if ( - \OC::$server->getConfig()->getAppValue('snappymail', 'snappymail-autologin-oidc', false) - && \OC::$server->getSession()->get('is_oidc') - && $sNcEmail === $oSettings->username - && !$bAccountDefinedExplicitly - // && $oClient->supportsAuthType('OAUTHBEARER') // v2.28 + if (\OC::$server->getConfig()->getAppValue('snappymail', 'snappymail-autologin-oidc', false) + && \OC::$server->getSession()->get('is_oidc') + && $sNcEmail === $oSettings->username + && !$bAccountDefinedExplicitly +// && $oClient->supportsAuthType('OAUTHBEARER') // v2.28 ) { $sAccessToken = \OC::$server->getSession()->get('oidc_access_token'); if ($sAccessToken) { @@ -184,7 +197,7 @@ public function beforeLogin(\RainLoop\Model\Account $oAccount, \MailSo\Net\NetCl \OC::$server->getLDAPProvider(); */ - public function NextcloudAttachFile(): array + public function NextcloudAttachFile() : array { $aResult = [ 'success' => false, @@ -208,10 +221,10 @@ public function NextcloudAttachFile(): array return $this->jsonResponse(__FUNCTION__, $aResult); } - public function NextcloudSaveMsg(): array + public function NextcloudSaveMsg() : array { $sSaveFolder = \ltrim($this->jsonParam('folder', ''), '/'); - // $aValues = \RainLoop\Api::Actions()->decodeRawKey($this->jsonParam('msgHash', '')); +// $aValues = \RainLoop\Api::Actions()->decodeRawKey($this->jsonParam('msgHash', '')); $msgHash = $this->jsonParam('msgHash', ''); $aValues = \json_decode(\MailSo\Base\Utils::UrlSafeBase64Decode($msgHash), true); $aResult = [ @@ -265,14 +278,14 @@ public function DoAttachmentsActions(\SnappyMail\AttachmentsAction $data) foreach ($data->items as $aItem) { $sSavedFileName = empty($aItem['fileName']) ? 'file.dat' : $aItem['fileName']; if (!empty($aItem['data'])) { - $sSavedFileNameFull = static::SmartFileExists($sSaveFolder . '/' . $sSavedFileName, $oFiles); + $sSavedFileNameFull = static::SmartFileExists($sSaveFolder.'/'.$sSavedFileName, $oFiles); if (!$oFiles->file_put_contents($sSavedFileNameFull, $aItem['data'])) { $data->result = false; } } else if (!empty($aItem['fileHash'])) { $fFile = $data->filesProvider->GetFile($data->account, $aItem['fileHash'], 'rb'); if (\is_resource($fFile)) { - $sSavedFileNameFull = static::SmartFileExists($sSaveFolder . '/' . $sSavedFileName, $oFiles); + $sSavedFileNameFull = static::SmartFileExists($sSaveFolder.'/'.$sSavedFileName, $oFiles); if (!$oFiles->file_put_contents($sSavedFileNameFull, $fFile)) { $data->result = false; } @@ -286,19 +299,19 @@ public function DoAttachmentsActions(\SnappyMail\AttachmentsAction $data) } } - public function FilterAppData($bAdmin, &$aResult): void + public function FilterAppData($bAdmin, &$aResult) : void { if (!$bAdmin && \is_array($aResult)) { $ocUser = \OC::$server->getUserSession()->getUser(); $sUID = $ocUser->getUID(); $oUrlGen = \OC::$server->getURLGenerator(); $sWebDAV = $oUrlGen->getAbsoluteURL($oUrlGen->linkTo('', 'remote.php') . '/dav'); - // $sWebDAV = \OCP\Util::linkToRemote('dav'); +// $sWebDAV = \OCP\Util::linkToRemote('dav'); $aResult['Nextcloud'] = [ 'UID' => $sUID, 'WebDAV' => $sWebDAV, 'CalDAV' => $this->Config()->Get('plugin', 'calendar', false) - // 'WebDAV_files' => $sWebDAV . '/files/' . $sUID +// 'WebDAV_files' => $sWebDAV . '/files/' . $sUID ]; if (empty($aResult['Auth'])) { $config = \OC::$server->getConfig(); @@ -320,9 +333,9 @@ public function FilterAppData($bAdmin, &$aResult): void } if (!$sEmail) { $sEmail = $ocUser->getEMailAddress(); - // ?: $ocUser->getPrimaryEMailAddress(); +// ?: $ocUser->getPrimaryEMailAddress(); } - /* +/* if ($config->getAppValue('snappymail', 'snappymail-autologin-oidc', false)) { if (\OC::$server->getSession()->get('is_oidc')) { $sEmail = "{$sUID}@nextcloud"; @@ -369,7 +382,7 @@ public function FilterAppData($bAdmin, &$aResult): void } } - public function FilterLanguage(&$sLanguage, $bAdmin): void + public function FilterLanguage(&$sLanguage, $bAdmin) : void { if (!\RainLoop\Api::Config()->Get('webmail', 'allow_languages_on_settings', true)) { $aResultLang = \SnappyMail\L10n::getLanguages($bAdmin); @@ -392,7 +405,7 @@ public function FilterLanguage(&$sLanguage, $bAdmin): void * * @return string return locale */ - private function determineLocale(string $langCode, array $languagesArray): ?string + private function determineLocale(string $langCode, array $languagesArray) : ?string { // Direct check for the language code if (\in_array($langCode, $languagesArray)) { @@ -429,20 +442,20 @@ public function MainFabrica(string $sName, &$mResult) } include_once __DIR__ . '/NextcloudContactsSuggestions.php'; $mResult[] = new NextcloudContactsSuggestions( - $this->Config()->Get('plugin', 'ignoreSystemAddressbook', true) + $this->Config()->Get('plugin', self::IGNORE_SYSTEM_ADDRESSBOOK_KEY, self::IGNORE_SYSTEM_ADDRESSBOOK_DEFAULT_VALUE) ); } - if ('address-book' === $sName && $this->Config()->Get('plugin', 'enableNcAddressbook', false)) { + if ('address-book' === $sName && $this->Config()->Get('plugin', self::ENABLE_NC_ADDRESSBOOK_KEY, self::ENABLE_NC_ADDRESSBOOK_DEFAULT_VALUE)) { if (!\is_array($mResult)) { $mResult = array(); } include_once __DIR__ . '/NextcloudAddressBook.php'; - $ignoreSystemAddressbook = $this->Config()->Get('plugin', 'ignoreSystemAddressbook', true); - $defaultName = $this->Config()->Get('plugin', 'defaultNCAddressbookName', self::DEFAULT_ADDRESSBOOK_NAME); - $defaultDescription = $this->Config()->Get('plugin', 'defaultNCAddressbookDescription', self::DEFAULT_ADDRESSBOOK_DESCRIPTION); - $defaultUri = $this->Config()->Get('plugin', 'defaultNCAddressbookUri', self::DEFAULT_ADDRESSBOOK_URI); + $ignoreSystemAddressbook = $this->Config()->Get('plugin', self::IGNORE_SYSTEM_ADDRESSBOOK_KEY, self::IGNORE_SYSTEM_ADDRESSBOOK_DEFAULT_VALUE); + $defaultName = $this->Config()->Get('plugin', self::DEFAULT_ADDRESSBOOK_NAME_KEY, self::DEFAULT_ADDRESSBOOK_NAME); + $defaultDescription = $this->Config()->Get('plugin', self::DEFAULT_ADDRESSBOOK_DESCRIPTION_KEY, self::DEFAULT_ADDRESSBOOK_DESCRIPTION); + $defaultUri = $this->Config()->Get('plugin', self::DEFAULT_ADDRESSBOOK_URI_KEY, self::DEFAULT_ADDRESSBOOK_URI); $mResult = new NextcloudAddressBook( $defaultUri, @@ -460,16 +473,16 @@ public function MainFabrica(string $sName, &$mResult) } } - protected function configMapping(): array + protected function configMapping() : array { return array( \RainLoop\Plugins\Property::NewInstance('suggestions')->SetLabel('Suggestions') ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetDefaultValue(true), - \RainLoop\Plugins\Property::NewInstance('ignoreSystemAddressbook')->SetLabel('Ignore system addressbook') + \RainLoop\Plugins\Property::NewInstance(self::IGNORE_SYSTEM_ADDRESSBOOK_KEY)->SetLabel('Ignore system addressbook') ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) - ->SetDefaultValue(true), - /* + ->SetDefaultValue(self::IGNORE_SYSTEM_ADDRESSBOOK_DEFAULT_VALUE), +/* \RainLoop\Plugins\Property::NewInstance('storage')->SetLabel('Use Nextcloud user ID in config storage path') ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetDefaultValue(false) @@ -478,29 +491,29 @@ protected function configMapping(): array ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetDefaultValue(false), - \RainLoop\Plugins\Property::NewInstance('enableNcAddressbook')->SetLabel('Enable User to choose Nextcloud addressbook for recipients') + \RainLoop\Plugins\Property::NewInstance(self::ENABLE_NC_ADDRESSBOOK_KEY)->SetLabel('Enable User to choose Nextcloud addressbook for recipients') ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) - ->SetDefaultValue(false), + ->SetDefaultValue(self::ENABLE_NC_ADDRESSBOOK_DEFAULT_VALUE), - \RainLoop\Plugins\Property::NewInstance('defaultNCAddressbookUri')->SetLabel('Default nextcloud addressbook URI for recipinets') + \RainLoop\Plugins\Property::NewInstance(self::DEFAULT_ADDRESSBOOK_URI_KEY)->SetLabel('Default nextcloud addressbook URI for recipinets') ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING) - ->SetDefaultValue('webmail'), + ->SetDefaultValue(self::DEFAULT_ADDRESSBOOK_URI), - \RainLoop\Plugins\Property::NewInstance('defaultNCAddressbookName')->SetLabel('Default nextcloud addressbook Name for recipinets') + \RainLoop\Plugins\Property::NewInstance(self::DEFAULT_ADDRESSBOOK_NAME_KEY)->SetLabel('Default nextcloud addressbook Name for recipinets') ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING) ->SetDefaultValue(self::DEFAULT_ADDRESSBOOK_NAME), - \RainLoop\Plugins\Property::NewInstance('defaultNCAddressbookDescription')->SetLabel('Default nextcloud addressbook description for recipinets') + \RainLoop\Plugins\Property::NewInstance(self::DEFAULT_ADDRESSBOOK_DESCRIPTION_KEY)->SetLabel('Default nextcloud addressbook description for recipinets') ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING) ->SetDefaultValue(self::DEFAULT_ADDRESSBOOK_DESCRIPTION), - \RainLoop\Plugins\Property::NewInstance('disableInhouseAddressbook')->SetLabel('Disable SnappyMail internal addressbook. This is recomended if nextcloud addressbook is being used.') + \RainLoop\Plugins\Property::NewInstance(self::DISABLE_INHOUSE_ADDRESSBOOK_KEY)->SetLabel('Disable SnappyMail internal addressbook. This is recomended if nextcloud addressbook is being used.') ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) - ->SetDefaultValue(false) + ->SetDefaultValue(self::DISABLE_INHOUSE_ADDRESSBOOK_DEFAULT_VALUE) ); } - private static function SmartFileExists(string $sFilePath, $oFiles): string + private static function SmartFileExists(string $sFilePath, $oFiles) : string { $sFilePath = \str_replace('\\', '/', \trim($sFilePath)); @@ -514,10 +527,11 @@ private static function SmartFileExists(string $sFilePath, $oFiles): string while (true) { ++$iIndex; - $sFilePathNew = $aFileInfo['dirname'] . '/' . - \preg_replace('/\(\d{1,2}\)$/', '', $aFileInfo['filename']) . - ' (' . $iIndex . ')' . - (empty($aFileInfo['extension']) ? '' : '.' . $aFileInfo['extension']); + $sFilePathNew = $aFileInfo['dirname'].'/'. + \preg_replace('/\(\d{1,2}\)$/', '', $aFileInfo['filename']). + ' ('.$iIndex.')'. + (empty($aFileInfo['extension']) ? '' : '.'.$aFileInfo['extension']) + ; if (!$oFiles->file_exists($sFilePathNew)) { return $sFilePathNew; } @@ -528,17 +542,17 @@ private static function SmartFileExists(string $sFilePath, $oFiles): string return $sFilePath; } - private function Account(): \RainLoop\Model\Account + private function Account() : \RainLoop\Model\Account { return \RainLoop\Api::Actions()->getAccountFromToken(); } - private function SettingsProvider(): \RainLoop\Providers\Settings + private function SettingsProvider() : \RainLoop\Providers\Settings { return \RainLoop\Api::Actions()->SettingsProvider(true); } - private function UserSettings(): \RainLoop\Settings + private function UserSettings() : \RainLoop\Settings { return $this->SettingsProvider()->Load($this->Account()); } diff --git a/plugins/nextcloud/js/addressbook.js b/plugins/nextcloud/js/addressbook.js deleted file mode 100644 index c871c0928a..0000000000 --- a/plugins/nextcloud/js/addressbook.js +++ /dev/null @@ -1,38 +0,0 @@ -(rl => { - if (rl) { - addEventListener('rl-view-model', e => { - if ('SettingsContacts' === e.detail.viewModelTemplateID) { - const container = e.detail.viewModelDom.querySelector('.form-horizontal'); - if (container) { - rl.pluginRemoteRequest((iError, oData) => { - if (!iError) { - const mainDivElement = Element.fromHTML('
' - + '' - + '
'); - - const selectElement = Element.fromHTML(''); - - const books = JSON.parse(oData.Result.addressbooks); - books.forEach(book => { - if (book.selected) { - selectElement.append(Element.fromHTML('')); - } else { - selectElement.append(Element.fromHTML('')); - } - }); - - selectElement.onchange = function() { - rl.pluginRemoteRequest(() => { }, 'NextcloudUpdateAddressBook', { - uri: selectElement.value - }); - } - - mainDivElement.append(selectElement); - container.append(mainDivElement); - } - }, "NextcloudGetAddressBooks"); - } - } - }); - } -})(window.rl); diff --git a/plugins/nextcloud/js/hideInhouseAddressbook.js b/plugins/nextcloud/js/hideInhouseAddressbook.js index ed8197e180..37feb7dc9d 100644 --- a/plugins/nextcloud/js/hideInhouseAddressbook.js +++ b/plugins/nextcloud/js/hideInhouseAddressbook.js @@ -13,14 +13,16 @@ addEventListener('rl-view-model', e => { if ('SystemDropDown' === e.detail.viewModelTemplateID) { const container = e.detail.viewModelDom.querySelector('.dropdown-menu'); - if (container) { - for (i = 0; i < container.children.length; i++) { - const element = container.children[i]; - const attr = element.getAttribute("data-bind"); - if (attr && attr.includes("visible: allowContacts")) { - element.remove(); - break; - } + if (!container) { + return; + } + + for (i = 0; i < container.children.length; i++) { + const element = container.children[i]; + const attr = element.getAttribute("data-bind"); + if (attr && attr.includes("visible: allowContacts")) { + element.remove(); + break; } } } @@ -29,14 +31,16 @@ addEventListener('rl-view-model', e => { if ('PopupsCompose' === e.detail.viewModelTemplateID) { const container = e.detail.viewModelDom.querySelector('.pull-right'); - if (container) { - for (i = 0; i < container.children.length; i++) { - const element = container.children[i]; - const attr = element.getAttribute("data-bind"); - if (attr && attr.includes("visible: allowContacts")) { - element.remove(); - break; - } + if(!container) { + return; + } + + for (i = 0; i < container.children.length; i++) { + const element = container.children[i]; + const attr = element.getAttribute("data-bind"); + if (attr && attr.includes("visible: allowContacts")) { + element.remove(); + break; } } } diff --git a/plugins/nextcloud/js/nextcloudAddressbook.js b/plugins/nextcloud/js/nextcloudAddressbook.js new file mode 100644 index 0000000000..0c3684ce0b --- /dev/null +++ b/plugins/nextcloud/js/nextcloudAddressbook.js @@ -0,0 +1,42 @@ +(rl => { + if (rl) { + addEventListener('rl-view-model', e => { + if ('SettingsContacts' === e.detail.viewModelTemplateID) { + const container = e.detail.viewModelDom.querySelector('.form-horizontal'); + if (!container) { + return; + } + + rl.pluginRemoteRequest((iError, oData) => { + if (iError) { + return; + } + + const mainDivElement = Element.fromHTML('
' + + '' + + '
'); + + const selectElement = Element.fromHTML(''); + + const addressbooks = JSON.parse(oData.Result.addressbooks); + addressbooks.forEach(addressbook => { + if (addressbook.selected) { + selectElement.append(Element.fromHTML('')); + } else { + selectElement.append(Element.fromHTML('')); + } + }); + + selectElement.onchange = function() { + rl.pluginRemoteRequest(() => { }, 'NextcloudUpdateAddressBook', { + uri: selectElement.value + }); + } + + mainDivElement.append(selectElement); + container.append(mainDivElement); + }, "NextcloudGetAddressBooks"); + } + }); + } +})(window.rl); From e5044ff10a5161a479577b790c8a9485434ed635 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 3 Sep 2024 13:07:29 +0000 Subject: [PATCH 24/28] Apply suggestions from code review Co-authored-by: Akhil Potukuchi --- plugins/nextcloud/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/nextcloud/index.php b/plugins/nextcloud/index.php index 28adf35fb9..5f419c7b2e 100644 --- a/plugins/nextcloud/index.php +++ b/plugins/nextcloud/index.php @@ -503,7 +503,7 @@ protected function configMapping() : array ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING) ->SetDefaultValue(self::DEFAULT_ADDRESSBOOK_NAME), - \RainLoop\Plugins\Property::NewInstance(self::DEFAULT_ADDRESSBOOK_DESCRIPTION_KEY)->SetLabel('Default nextcloud addressbook description for recipinets') + \RainLoop\Plugins\Property::NewInstance(self::DEFAULT_ADDRESSBOOK_DESCRIPTION_KEY)->SetLabel('Default nextcloud addressbook description for recipients') ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING) ->SetDefaultValue(self::DEFAULT_ADDRESSBOOK_DESCRIPTION), From dff305e64562385b9303a10a60d6dab68645cfa3 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 3 Sep 2024 19:15:19 +0600 Subject: [PATCH 25/28] refactor: remove repeated variable initialization --- plugins/nextcloud/NextcloudAddressBook.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index 90a8331fe3..5e9f27c877 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -8,11 +8,10 @@ class NextcloudAddressBook implements \RainLoop\Providers\AddressBook\AddressBoo private const SETTINGS_KEY = 'nextcloudAddressBookUri'; - private string $defaultUri = 'webmail'; - private string $defaultName = 'WebMail'; - private string $defaultDescription = 'Recipients from snappymail'; - private bool $ignoreSystemAddressBook = true; - + private string $defaultUri; + private string $defaultName; + private string $defaultDescription; + private bool $ignoreSystemAddressBook; private $contactsManager; function __construct(string $defaultUri = 'webmail', string $defaultName = 'WebMail', string $defaultDescription = 'Recipients from snappymail', bool $ignoreSystemAddressBook = true) From 943b2560c1a56f6a038c8873ef39cb578b1b2d7c Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 3 Sep 2024 19:36:37 +0600 Subject: [PATCH 26/28] chore: add Readme file for nextcloud plugin + fix typo --- plugins/nextcloud/README.md | 14 ++++++++++++++ plugins/nextcloud/index.php | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 plugins/nextcloud/README.md diff --git a/plugins/nextcloud/README.md b/plugins/nextcloud/README.md new file mode 100644 index 0000000000..fc2c6ed370 --- /dev/null +++ b/plugins/nextcloud/README.md @@ -0,0 +1,14 @@ +# SnappyMail plugin for nextcloud + +## Nextcloud Addressbook for recipients + +This plugin can let user to choose which nextcloud addressbook to use save recipients. This is opt-in feature (enabled by admin). After admin enable this, user will find a dropdown in his/her SnappyMail's `Contacts` section, containing all his/her addressbook. + +### Admin settings + +- `enableNcAddressbook` : Enable User to choose Nextcloud addressbook for recipients. Default value: `false` +- `disableSnappymailContactsUI` : Disable SnappyMail internal addressbook. This is recomended if nextcloud addressbook is being used. Default value: `false` +- `defaultNCAddressbookUri` : Default nextcloud addressbook URI for recipients. Default value: `webmail` +- `defaultNCAddressbookName` : Default nextcloud addressbook Name for recipients. Default value: `WebMail` +- `defaultNCAddressbookDescription` : Default nextcloud addressbook description for recipients. Default value: `Recipients from snappymail` + diff --git a/plugins/nextcloud/index.php b/plugins/nextcloud/index.php index 5f419c7b2e..5786043452 100644 --- a/plugins/nextcloud/index.php +++ b/plugins/nextcloud/index.php @@ -495,11 +495,11 @@ protected function configMapping() : array ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetDefaultValue(self::ENABLE_NC_ADDRESSBOOK_DEFAULT_VALUE), - \RainLoop\Plugins\Property::NewInstance(self::DEFAULT_ADDRESSBOOK_URI_KEY)->SetLabel('Default nextcloud addressbook URI for recipinets') + \RainLoop\Plugins\Property::NewInstance(self::DEFAULT_ADDRESSBOOK_URI_KEY)->SetLabel('Default nextcloud addressbook URI for recipients') ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING) ->SetDefaultValue(self::DEFAULT_ADDRESSBOOK_URI), - \RainLoop\Plugins\Property::NewInstance(self::DEFAULT_ADDRESSBOOK_NAME_KEY)->SetLabel('Default nextcloud addressbook Name for recipinets') + \RainLoop\Plugins\Property::NewInstance(self::DEFAULT_ADDRESSBOOK_NAME_KEY)->SetLabel('Default nextcloud addressbook Name for recipients') ->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING) ->SetDefaultValue(self::DEFAULT_ADDRESSBOOK_NAME), From cf870df3f88de1eefe971e94f804ff4f5a6c9554 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Thu, 5 Sep 2024 16:02:45 +0600 Subject: [PATCH 27/28] fix: remove Nextcloud contacts app direct dependency on nextcloud plugin NC contacts app is just frontend for contacts & addressbook of NC server. Nextcloud plugin `auto save recipients on addressbook` feature used to depends on contacts app directly. This commit update that logic. --- plugins/nextcloud/NextcloudAddressBook.php | 3 ++- plugins/nextcloud/README.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/nextcloud/NextcloudAddressBook.php b/plugins/nextcloud/NextcloudAddressBook.php index 5e9f27c877..e418c6dfe6 100644 --- a/plugins/nextcloud/NextcloudAddressBook.php +++ b/plugins/nextcloud/NextcloudAddressBook.php @@ -62,7 +62,8 @@ private function GetSavedAddressBookKey() : string public function IsSupported() : bool { // Maybe just return true, contacts app is just a frontend - return \OC::$server->getAppManager()->isEnabledForUser('contacts'); + // return \OC::$server->getAppManager()->isEnabledForUser('contacts'); + return true; } public function SetEmail(string $sEmail) : bool diff --git a/plugins/nextcloud/README.md b/plugins/nextcloud/README.md index fc2c6ed370..972e1cdc8e 100644 --- a/plugins/nextcloud/README.md +++ b/plugins/nextcloud/README.md @@ -2,7 +2,7 @@ ## Nextcloud Addressbook for recipients -This plugin can let user to choose which nextcloud addressbook to use save recipients. This is opt-in feature (enabled by admin). After admin enable this, user will find a dropdown in his/her SnappyMail's `Contacts` section, containing all his/her addressbook. + This plugin can let user to choose which nextcloud addressbook to use save recipients. This is opt-in feature (enabled by admin). After admin enable this, user will find a dropdown in his/her SnappyMail's `Contacts` section, containing all his/her addressbook. It works better with [Nextcloud Contacts App](https://github.com/nextcloud/contacts/) ### Admin settings From 8b6adb364802d34a79ca988981067ccc15e1a407 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 24 Sep 2024 16:29:34 +0000 Subject: [PATCH 28/28] Update README.md --- plugins/nextcloud/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/nextcloud/README.md b/plugins/nextcloud/README.md index 972e1cdc8e..7ba01008f4 100644 --- a/plugins/nextcloud/README.md +++ b/plugins/nextcloud/README.md @@ -1,14 +1,14 @@ # SnappyMail plugin for nextcloud -## Nextcloud Addressbook for recipients +## Nextcloud Addressbook to save recipients' contacts - This plugin can let user to choose which nextcloud addressbook to use save recipients. This is opt-in feature (enabled by admin). After admin enable this, user will find a dropdown in his/her SnappyMail's `Contacts` section, containing all his/her addressbook. It works better with [Nextcloud Contacts App](https://github.com/nextcloud/contacts/) + This plugin can let user to choose which nextcloud addressbook to use save recipients (requires enableing snappyMail contacts) . This is opt-in feature (enabled by admin). After admin enable this, user will find a dropdown in his/her SnappyMail's `Contacts` section, containing all his/her addressbook. It works better with [Nextcloud Contacts App](https://github.com/nextcloud/contacts/) ### Admin settings -- `enableNcAddressbook` : Enable User to choose Nextcloud addressbook for recipients. Default value: `false` -- `disableSnappymailContactsUI` : Disable SnappyMail internal addressbook. This is recomended if nextcloud addressbook is being used. Default value: `false` -- `defaultNCAddressbookUri` : Default nextcloud addressbook URI for recipients. Default value: `webmail` -- `defaultNCAddressbookName` : Default nextcloud addressbook Name for recipients. Default value: `WebMail` -- `defaultNCAddressbookDescription` : Default nextcloud addressbook description for recipients. Default value: `Recipients from snappymail` +- `enableNcAddressbook` : Enable: save recipient contacts into nextcloud addressbook feature. User will see a new section into her/his `Contacts` setting, so s/he can choose Nextcloud addressbook to save recipients' contacts. Default value: `false` +- `disableSnappymailContactsUI` : Hide SnappyMail internal addressbook accesspoint. This is recomended if nextcloud addressbook to save recipients contacts is being used. So, users won't be confused to having multiple addressbook options. Default value: `false` +- `defaultNCAddressbookUri` : Default nextcloud addressbook URI to save recipients' contacts. Ignored if `enableNcAddressbook` is set to false. User can change this value for her/his account. Default value: `webmail` +- `defaultNCAddressbookName` : Default nextcloud addressbook Name to save recipients' contacts. Ignored if `enableNcAddressbook` is set to false. User can change this value for her/his account. Default value: `WebMail` +- `defaultNCAddressbookDescription` : Default nextcloud addressbook description to save recipients' contacts. Ignored if `enableNcAddressbook` is set to false. User can change this value for her/his account. Default value: `Recipients from snappymail`