From bd2abfe132c3b1f762c03390383641399a713107 Mon Sep 17 00:00:00 2001 From: Michael Stilkerich Date: Sat, 19 Aug 2023 21:02:16 +0200 Subject: [PATCH] Support setting roundcube's default addressbook to an addressbook from a preset (Fixes #440) --- CHANGELOG.md | 1 + config.inc.php.dist | 12 ++++- doc/ADMIN-SETTINGS.md | 14 ++++-- src/Frontend/AdminSettings.php | 4 +- tests/Unit/AdminSettingsWithDataTest.php | 46 +++++-------------- .../data/adminSettingsTest/fullconfig.inc.php | 4 ++ .../data/adminSettingsTest/fullconfig.json | 4 ++ .../adminSettingsWithDataTest/matchBoth.php | 7 +++ .../matchMultiple.php | 5 ++ .../adminSettingsWithDataTest/noMatch.php | 6 +++ 10 files changed, 59 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4825ef24..c45e4b04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Allow to hide contacts without email also for user-defined addressbooks (Fixes #429) - Re-introduced option `preemptive_basic_auth` to send HTTP basic Authorization header with every request (Fixes #407) +- Support setting roundcube's default addressbook to an addressbook from a preset (Fixes #440) ## Version 5.0.1 (to 5.0.0) diff --git a/config.inc.php.dist b/config.inc.php.dist index 2cd9b946..3a98e242 100644 --- a/config.inc.php.dist +++ b/config.inc.php.dist @@ -29,8 +29,8 @@ $prefs['_GLOBAL']['loglevel'] = \Psr\Log\LogLevel::WARNING; $prefs['_GLOBAL']['loglevel_http'] = \Psr\Log\LogLevel::ERROR; -// Select addressbook from preset to use as Roundcube's collected recipients or collected/trusted senders addressbook, -// corresponding to the roundcube options of the same name available since roundcube 1.5. +// Select addressbook from preset to use as Roundcube's collected recipients, collected/trusted senders or default +// addressbook, corresponding to the roundcube options of the same name available since roundcube 1.5. // Note that only writeable addressbooks can be used for this. If you do not want to use these options, simply do not // define them // If no/several addressbooks match, the roundcube setting will not be changed @@ -50,6 +50,14 @@ $prefs['_GLOBAL']['loglevel_http'] = \Psr\Log\LogLevel::ERROR; // 'matchname' => '/collected recipients/i', // 'matchurl' => '#http://carddav.example.com/abooks/%u/CollectedRecipients#', //]; +//$prefs['_GLOBAL']['default_addressbook'] = [ +// // Key of the preset, i.e. whatever is used for in the template below +// 'preset' => '', +// // The placeholders that can be used in the url attribute can also be used inside these regular rexpressions +// // If both matchname and matchurl are given, both need to match for the addressbook to be used +// 'matchname' => '/collected recipients/i', +// 'matchurl' => '#http://carddav.example.com/abooks/%u/CollectedRecipients#', +//]; //// ** ACCOUNT PRESETS diff --git a/doc/ADMIN-SETTINGS.md b/doc/ADMIN-SETTINGS.md index 7a7dbf32..cfbbc286 100644 --- a/doc/ADMIN-SETTINGS.md +++ b/doc/ADMIN-SETTINGS.md @@ -304,15 +304,16 @@ Preconfigured addressbooks are processed when the user logs into roundcube. - If the user has addressbooks created from a preset that no longer exists (identified by the Presetname), the addressbooks are deleted from the database. -### Using presets for the roundcube trusted senders/collected recipients addressbooks +### Using presets for the roundcube trusted senders/collected recipients addressbooks and default addressbook Roundcube 1.5 and newer has two special internal addressbooks to automatically collect all addresses the user previously sent mail to (roundcube config option: `collected_recipients`) and to collect addresses of trusted senders (roundcube config option: `collected_senders`). -It is possible for a user to manually select CardDAV addressbooks for these two special purpose addressbooks using -the roundcube settings interface. When using preconfigured CardDAV addressbooks, the admin may want to also set these -special addressbooks by configuration, which is possible using the following configuration options: +It is possible for a user to manually select CardDAV addressbooks for these two special purpose addressbooks and the +roundcube default addressbook using the roundcube settings interface. When using preconfigured CardDAV addressbooks, the +admin may want to also set these special addressbooks or the default addressbook by configuration, which is possible +using the following configuration options: ```php $prefs['_GLOBAL']['collected_recipients'] = [ @@ -325,6 +326,9 @@ $prefs['_GLOBAL']['collected_recipients'] = [ $prefs['_GLOBAL']['collected_senders'] = [ // Configuration analog to collected recipients ]; +$prefs['_GLOBAL']['default_addressbook'] = [ + // Configuration analog to collected recipients +]; ``` Each of the above RCMCardDAV settings will cause the roundcube setting of the same name to be overridden in case a @@ -355,7 +359,7 @@ Configuration of these addressbooks by the user can be disabled using the follow roundcube (not RCMCardDAV) configuration: ```php -$config['dont_override'] = ['collected_recipients', 'collected_senders']; +$config['dont_override'] = ['collected_recipients', 'collected_senders', 'default_addressbook']; ``` When using the trusted senders addressbook, please also configure the roundcube options `show_images` and `mdn_requests` diff --git a/src/Frontend/AdminSettings.php b/src/Frontend/AdminSettings.php index 9a141e18..16fe0671 100644 --- a/src/Frontend/AdminSettings.php +++ b/src/Frontend/AdminSettings.php @@ -44,7 +44,7 @@ * @psalm-type ConfigurablePresetAttr = 'accountname'|'discovery_url'|'username'|'password'|'rediscover_time'| * 'active'|'refresh_time'|'use_categories'|'readonly'|'require_always_email'| * 'name'|'preemptive_basic_auth'|'ssl_noverify' - * @psalm-type SpecialAbookType = 'collected_recipients'|'collected_senders' + * @psalm-type SpecialAbookType = 'collected_recipients'|'collected_senders'|'default_addressbook' * @psalm-type SpecialAbookMatch = array{preset: string, matchname?: string, matchurl?: string} * * @psalm-type PresetExtraAbook = array{ @@ -258,7 +258,7 @@ public function __construct(string $configfile, LoggerInterface $logger, LoggerI } // Extract filter for special addressbooks - foreach ([ 'collected_recipients', 'collected_senders' ] as $setting) { + foreach ([ 'collected_recipients', 'collected_senders', 'default_addressbook' ] as $setting) { if (isset($gprefs[$setting]) && is_array($gprefs[$setting])) { $matchSettings = $gprefs[$setting]; diff --git a/tests/Unit/AdminSettingsWithDataTest.php b/tests/Unit/AdminSettingsWithDataTest.php index 3e59566d..b932b8d4 100644 --- a/tests/Unit/AdminSettingsWithDataTest.php +++ b/tests/Unit/AdminSettingsWithDataTest.php @@ -56,35 +56,38 @@ public function tearDown(): void } /** - * @return array + * @return array */ public function specialAbookTestProvider(): array { $base = 'tests/Unit/data/adminSettingsWithDataTest'; return [ - 'Two matchers, one match' => [ "$base/matchBoth.php", ['43', '43'] ], + 'Two matchers, one match' => [ "$base/matchBoth.php", ['43', '43', '43'] ], 'No matches (invalid preset, AND condition eval)' => [ "$base/noMatch.php", [ 'Setting for collected_recipients must include a valid preset attribute', - 'Cannot set special addressbook collected_senders, there are 0 candidates (need: 1)' + 'Cannot set special addressbook collected_senders, there are 0 candidates (need: 1)', + 'Cannot set special addressbook default_addressbook, there are 0 candidates (need: 1)' ] ], 'Multiple matches' => [ "$base/matchMultiple.php", [ 'Cannot set special addressbook collected_recipients, there are 2 candidates (need: 1)', - 'Cannot set special addressbook collected_senders, there are 2 candidates (need: 1)' + 'Cannot set special addressbook collected_senders, there are 2 candidates (need: 1)', + 'Cannot set special addressbook default_addressbook, there are 2 candidates (need: 1)' ] ], - 'Preset not yet in DB' => [ "$base/presetNotInDbYet.php", [null, null] ], + 'Preset not yet in DB' => [ "$base/presetNotInDbYet.php", [null, null, null] ], ]; } /** * @param string $admSettingsPath Path name of config.inc.php file - * @param list{?string,?string} $expIds Expected abook IDs for 0: collected_recipients, 1: collected_senders + * @param list{?string,?string,?string} $expIds Expected abook IDs for 0: collected_recipients, + * 1: collected_senders, 2: default_addressbook * @dataProvider specialAbookTestProvider */ public function testSpecialAddressbooksReturnedCorrectly(string $admSettingsPath, array $expIds): void @@ -100,7 +103,7 @@ public function testSpecialAddressbooksReturnedCorrectly(string $admSettingsPath $specialAbooks = $admPrefs->getSpecialAddressbooks($abMgr, $infra); $i = 0; - foreach (['collected_recipients', 'collected_senders'] as $abookType) { + foreach (['collected_recipients', 'collected_senders', 'default_addressbook'] as $abookType) { if (isset($expIds[$i])) { if (strpos($expIds[$i], ' ') === false) { $this->assertArrayHasKey($abookType, $specialAbooks); @@ -113,7 +116,7 @@ public function testSpecialAddressbooksReturnedCorrectly(string $admSettingsPath $this->assertArrayNotHasKey($abookType, $specialAbooks); } - $i = 1; + $i++; } } @@ -194,33 +197,6 @@ public function testTemplateAddressbookProvidedCorrectly(): void $this->assertArrayNotHasKey('template', $tmpl); } - /** - * @return array - */ - public function initPresetDataProvider(): array - { - $base = 'tests/Unit/data/adminSettingsWithDataTest'; - - return [ - 'Two matchers, one match' => [ "$base/matchBoth.php", ['43', '43'] ], - 'No matches (invalid preset, AND condition eval)' => [ - "$base/noMatch.php", - [ - 'Setting for collected_recipients must include a valid preset attribute', - 'Cannot set special addressbook collected_senders, there are 0 candidates (need: 1)' - ] - ], - 'Multiple matches' => [ - "$base/matchMultiple.php", - [ - 'Cannot set special addressbook collected_recipients, there are 2 candidates (need: 1)', - 'Cannot set special addressbook collected_senders, there are 2 candidates (need: 1)' - ] - ], - 'Preset not yet in DB' => [ "$base/presetNotInDbYet.php", [null, null] ], - ]; - } - /** * Tests that presets are initialized and updated properly by AdminSettings::initPresets(). * diff --git a/tests/Unit/data/adminSettingsTest/fullconfig.inc.php b/tests/Unit/data/adminSettingsTest/fullconfig.inc.php index 3d4e476e..d538d3d5 100644 --- a/tests/Unit/data/adminSettingsTest/fullconfig.inc.php +++ b/tests/Unit/data/adminSettingsTest/fullconfig.inc.php @@ -16,6 +16,10 @@ 'preset' => 'OnlyShared', 'matchname' => '/shared %d addressbook/i', ]; +$prefs['_GLOBAL']['default_addressbook'] = [ + 'preset' => 'Preset1', + 'matchurl' => '#.*\.example\.com/%d/%l/%u#', +]; $prefs['Preset1'] = [ 'accountname' => 'First Preset', diff --git a/tests/Unit/data/adminSettingsTest/fullconfig.json b/tests/Unit/data/adminSettingsTest/fullconfig.json index c3d8d110..c0682ce9 100644 --- a/tests/Unit/data/adminSettingsTest/fullconfig.json +++ b/tests/Unit/data/adminSettingsTest/fullconfig.json @@ -12,6 +12,10 @@ "collected_senders": { "preset": "OnlyShared", "matchname": "/shared example\\.com addressbook/i" + }, + "default_addressbook": { + "preset": "Preset1", + "matchurl": "#.*\\.example\\.com/example\\.com/user/user@example\\.com#" } }, "presets": { diff --git a/tests/Unit/data/adminSettingsWithDataTest/matchBoth.php b/tests/Unit/data/adminSettingsWithDataTest/matchBoth.php index 05296642..de84ca79 100644 --- a/tests/Unit/data/adminSettingsWithDataTest/matchBoth.php +++ b/tests/Unit/data/adminSettingsWithDataTest/matchBoth.php @@ -15,6 +15,13 @@ 'matchurl' => '#^https://carddav.example.com/books/%l/book43/$#', ]; +$prefs['_GLOBAL']['default_addressbook'] = [ + 'preset' => 'AdmPreset', + 'matchname' => '/Add/i', + 'matchurl' => '#^https://carddav.example.com/books/%l/book43/$#', +]; + + $prefs['AdmPreset'] = [ 'accountname' => 'Admin Preset', 'discovery_url' => 'https://carddav.example.com/', diff --git a/tests/Unit/data/adminSettingsWithDataTest/matchMultiple.php b/tests/Unit/data/adminSettingsWithDataTest/matchMultiple.php index c471f406..49ab5a8b 100644 --- a/tests/Unit/data/adminSettingsWithDataTest/matchMultiple.php +++ b/tests/Unit/data/adminSettingsWithDataTest/matchMultiple.php @@ -12,6 +12,11 @@ 'matchurl' => '/%u/', ]; +$prefs['_GLOBAL']['default_addressbook'] = [ + 'preset' => 'AdmPreset', + 'matchname' => '/Add/', +]; + $prefs['AdmPreset'] = [ 'accountname' => 'Admin Preset', 'discovery_url' => 'https://carddav.example.com/', diff --git a/tests/Unit/data/adminSettingsWithDataTest/noMatch.php b/tests/Unit/data/adminSettingsWithDataTest/noMatch.php index d4fa8207..13d52466 100644 --- a/tests/Unit/data/adminSettingsWithDataTest/noMatch.php +++ b/tests/Unit/data/adminSettingsWithDataTest/noMatch.php @@ -13,6 +13,12 @@ 'matchurl' => '#^https://carddav.example.com/books/%l/book43/$#', ]; +$prefs['_GLOBAL']['default_addressbook'] = [ + 'preset' => 'AdmPreset', + 'matchname' => '/Addr/i', + 'matchurl' => '#^https://carddav.example.com/books/%l/book43/$#', +]; + $prefs['AdmPreset'] = [ 'accountname' => 'Admin Preset', 'discovery_url' => 'https://carddav.example.com/',