From bb2ae5645741ab7eb9cb948f06094728db2ffe43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Calvi=C3=B1o=20S=C3=A1nchez?= Date: Tue, 9 Dec 2025 19:04:55 +0100 Subject: [PATCH] fix: Unify handling of exclude groups in contacts menu and sharing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the current user belongs to both one or more groups excluded from sharing and one or more groups not excluded from sharing the user is allowed to share. However, in the contacts menu, as soon as the current user belonged to a group excluded from sharing the user could not search for local contacts. This has been unified now with the sharing behaviour, so local contacts can still be searched if the user also belongs to a group not excluded from sharing (or to no group at all, which was also allowed before). Signed-off-by: Daniel Calviño Sánchez --- build/integration/features/contacts-menu.feature | 10 ++++++---- lib/private/Contacts/ContactsMenu/ContactsStore.php | 6 +++--- tests/lib/Contacts/ContactsMenu/ContactsStoreTest.php | 10 +++++----- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/build/integration/features/contacts-menu.feature b/build/integration/features/contacts-menu.feature index 7adbba7ee78..c771a3fe2f1 100644 --- a/build/integration/features/contacts-menu.feature +++ b/build/integration/features/contacts-menu.feature @@ -103,7 +103,7 @@ Feature: contacts-menu And searching for contacts matching with "test" Then the list of searched contacts has "0" contacts - Scenario: users can not be searched by display name when searcher belongs to both a group excluded from sharing and another group + Scenario: users can be searched by display name when searcher belongs to both a group excluded from sharing and another group Given user "user0" exists And group "ExcludedGroup" exists And user "user0" belongs to group "ExcludedGroup" @@ -118,9 +118,10 @@ Feature: contacts-menu | value | Test name | When Logging in using web as "user0" And searching for contacts matching with "test" - Then the list of searched contacts has "0" contacts + Then the list of searched contacts has "1" contacts + And searched contact "0" is named "Test name" - Scenario: users can not be searched by email when searcher belongs to both a group excluded from sharing and another group + Scenario: users can be searched by email when searcher belongs to both a group excluded from sharing and another group Given user "user0" exists And group "ExcludedGroup" exists And user "user0" belongs to group "ExcludedGroup" @@ -135,7 +136,8 @@ Feature: contacts-menu | value | test@example.com | When Logging in using web as "user0" And searching for contacts matching with "test" - Then the list of searched contacts has "0" contacts + Then the list of searched contacts has "1" contacts + And searched contact "0" is named "user1" Scenario: users can not be searched by display name when searcher does not belong to a group allowed to share Given user "user0" exists diff --git a/lib/private/Contacts/ContactsMenu/ContactsStore.php b/lib/private/Contacts/ContactsMenu/ContactsStore.php index 5fa25512c97..f34e10e85d1 100644 --- a/lib/private/Contacts/ContactsMenu/ContactsStore.php +++ b/lib/private/Contacts/ContactsMenu/ContactsStore.php @@ -149,7 +149,7 @@ class ContactsStore implements IContactsStore { * 1. if the `shareapi_allow_share_dialog_user_enumeration` config option is * enabled it will filter all local users * 2. if the `shareapi_exclude_groups` config option is enabled and the - * current user is in an excluded group it will filter all local users. + * current user is only in excluded groups it will filter all local users. * 3. if the `shareapi_only_share_with_group_members` config option is * enabled it will filter all users which doesn't have a common group * with the current user. @@ -184,8 +184,8 @@ class ContactsStore implements IContactsStore { $excludeGroupsList = $decodedExcludeGroups ?? []; if ($excludeGroups != 'allow') { - if (count(array_intersect($excludeGroupsList, $selfGroups)) !== 0) { - // a group of the current user is excluded -> filter all local users + if (count($selfGroups) > 0 && count(array_diff($selfGroups, $excludeGroupsList)) === 0) { + // all the groups of the current user are excluded -> filter all local users $skipLocal = true; } } else { diff --git a/tests/lib/Contacts/ContactsMenu/ContactsStoreTest.php b/tests/lib/Contacts/ContactsMenu/ContactsStoreTest.php index 55f69f19a78..795c2c808d7 100644 --- a/tests/lib/Contacts/ContactsMenu/ContactsStoreTest.php +++ b/tests/lib/Contacts/ContactsMenu/ContactsStoreTest.php @@ -195,8 +195,8 @@ class ContactsStoreTest extends TestCase { ['yes', '["excludedGroup1"]', ['anotherGroup1'], ['user123', 'user12345']], ['yes', '["excludedGroup1"]', ['anotherGroup1', 'anotherGroup2', 'anotherGroup3'], ['user123', 'user12345']], ['yes', '["excludedGroup1"]', ['excludedGroup1'], []], - ['yes', '["excludedGroup1"]', ['anotherGroup1', 'excludedGroup1'], []], - ['yes', '["excludedGroup1"]', ['excludedGroup1', 'anotherGroup1', 'anotherGroup2', 'anotherGroup3'], []], + ['yes', '["excludedGroup1"]', ['anotherGroup1', 'excludedGroup1'], ['user123', 'user12345']], + ['yes', '["excludedGroup1"]', ['excludedGroup1', 'anotherGroup1', 'anotherGroup2', 'anotherGroup3'], ['user123', 'user12345']], ['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', [], ['user123', 'user12345']], ['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', ['anotherGroup1'], ['user123', 'user12345']], ['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', ['anotherGroup1', 'anotherGroup2', 'anotherGroup3'], ['user123', 'user12345']], @@ -204,9 +204,9 @@ class ContactsStoreTest extends TestCase { ['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', ['excludedGroup2'], []], ['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', ['excludedGroup3'], []], ['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', ['excludedGroup1', 'excludedGroup2', 'excludedGroup3'], []], - ['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', ['anotherGroup1', 'excludedGroup1'], []], - ['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', ['anotherGroup1', 'excludedGroup2', 'anotherGroup2', 'anotherGroup3'], []], - ['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', ['excludedGroup3', 'anotherGroup1', 'anotherGroup2', 'anotherGroup3'], []], + ['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', ['anotherGroup1', 'excludedGroup1'], ['user123', 'user12345']], + ['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', ['anotherGroup1', 'excludedGroup2', 'anotherGroup2', 'anotherGroup3'], ['user123', 'user12345']], + ['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', ['excludedGroup3', 'anotherGroup1', 'anotherGroup2', 'anotherGroup3'], ['user123', 'user12345']], ['allow', '[]', [], []], ['allow', '["allowedGroup1"]', [], []], ['allow', '["allowedGroup1"]', ['anotherGroup1'], []],