mirror of
https://github.com/nextcloud/server.git
synced 2026-05-28 04:32:30 -04:00
Merge pull request #57416 from nextcloud/backport/56938/stable32
This commit is contained in:
commit
d9c8ea6dd6
6 changed files with 304 additions and 4 deletions
|
|
@ -25,5 +25,7 @@ class FeatureContext implements Context, SnippetAcceptingContext {
|
|||
$this->deleteServerConfig('bruteForce', 'whitelist_0');
|
||||
$this->deleteServerConfig('bruteForce', 'whitelist_1');
|
||||
$this->deleteServerConfig('bruteforcesettings', 'apply_allowlist_to_ratelimit');
|
||||
$this->deleteServerConfig('core', 'shareapi_exclude_groups');
|
||||
$this->deleteServerConfig('core', 'shareapi_exclude_groups_list');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,5 +22,7 @@ class ShareesContext implements Context, SnippetAcceptingContext {
|
|||
$this->deleteServerConfig('core', 'shareapi_only_share_with_group_members');
|
||||
$this->deleteServerConfig('core', 'shareapi_allow_share_dialog_user_enumeration');
|
||||
$this->deleteServerConfig('core', 'shareapi_allow_group_sharing');
|
||||
$this->deleteServerConfig('core', 'shareapi_exclude_groups');
|
||||
$this->deleteServerConfig('core', 'shareapi_exclude_groups_list');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,6 +71,140 @@ Feature: contacts-menu
|
|||
And searched contact "1" is named "Test name"
|
||||
And searched contact "2" is named "user2"
|
||||
|
||||
|
||||
|
||||
Scenario: users can not be searched by display name when searcher belongs to a group excluded from sharing
|
||||
Given user "user0" exists
|
||||
And group "ExcludedGroup" exists
|
||||
And user "user0" belongs to group "ExcludedGroup"
|
||||
And parameter "shareapi_exclude_groups" of app "core" is set to "yes"
|
||||
And parameter "shareapi_exclude_groups_list" of app "core" is set to "ExcludedGroup"
|
||||
And user "user1" exists
|
||||
And As an "admin"
|
||||
And sending "PUT" to "/cloud/users/user1" with
|
||||
| key | displayname |
|
||||
| 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
|
||||
|
||||
Scenario: users can not be searched by email when searcher belongs to a group excluded from sharing
|
||||
Given user "user0" exists
|
||||
And group "ExcludedGroup" exists
|
||||
And user "user0" belongs to group "ExcludedGroup"
|
||||
And parameter "shareapi_exclude_groups" of app "core" is set to "yes"
|
||||
And parameter "shareapi_exclude_groups_list" of app "core" is set to "ExcludedGroup"
|
||||
And user "user1" exists
|
||||
And As an "admin"
|
||||
And sending "PUT" to "/cloud/users/user1" with
|
||||
| key | email |
|
||||
| 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
|
||||
|
||||
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"
|
||||
And group "AnotherGroup" exists
|
||||
And user "user0" belongs to group "AnotherGroup"
|
||||
And parameter "shareapi_exclude_groups" of app "core" is set to "yes"
|
||||
And parameter "shareapi_exclude_groups_list" of app "core" is set to "ExcludedGroup"
|
||||
And user "user1" exists
|
||||
And As an "admin"
|
||||
And sending "PUT" to "/cloud/users/user1" with
|
||||
| key | displayname |
|
||||
| value | Test name |
|
||||
When Logging in using web as "user0"
|
||||
And searching for contacts matching with "test"
|
||||
Then the list of searched contacts has "1" contacts
|
||||
And searched contact "0" is named "Test name"
|
||||
|
||||
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"
|
||||
And group "AnotherGroup" exists
|
||||
And user "user0" belongs to group "AnotherGroup"
|
||||
And parameter "shareapi_exclude_groups" of app "core" is set to "yes"
|
||||
And parameter "shareapi_exclude_groups_list" of app "core" is set to "ExcludedGroup"
|
||||
And user "user1" exists
|
||||
And As an "admin"
|
||||
And sending "PUT" to "/cloud/users/user1" with
|
||||
| key | email |
|
||||
| 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 "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
|
||||
And group "AllowedGroup" exists
|
||||
And parameter "shareapi_exclude_groups" of app "core" is set to "allow"
|
||||
And parameter "shareapi_exclude_groups_list" of app "core" is set to "AllowedGroup"
|
||||
And user "user1" exists
|
||||
And As an "admin"
|
||||
And sending "PUT" to "/cloud/users/user1" with
|
||||
| key | displayname |
|
||||
| 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
|
||||
|
||||
Scenario: users can not be searched by email when searcher does not belong to a group allowed to share
|
||||
Given user "user0" exists
|
||||
And group "AllowedGroup" exists
|
||||
And parameter "shareapi_exclude_groups" of app "core" is set to "allow"
|
||||
And parameter "shareapi_exclude_groups_list" of app "core" is set to "AllowedGroup"
|
||||
And user "user1" exists
|
||||
And As an "admin"
|
||||
And sending "PUT" to "/cloud/users/user1" with
|
||||
| key | email |
|
||||
| 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
|
||||
|
||||
Scenario: users can be searched by display name when searcher belongs to both a group allowed to share and another group
|
||||
Given user "user0" exists
|
||||
And group "AllowedGroup" exists
|
||||
And user "user0" belongs to group "AllowedGroup"
|
||||
And group "AnotherGroup" exists
|
||||
And user "user0" belongs to group "AnotherGroup"
|
||||
And parameter "shareapi_exclude_groups" of app "core" is set to "allow"
|
||||
And parameter "shareapi_exclude_groups_list" of app "core" is set to "AllowedGroup"
|
||||
And user "user1" exists
|
||||
And As an "admin"
|
||||
And sending "PUT" to "/cloud/users/user1" with
|
||||
| key | displayname |
|
||||
| value | Test name |
|
||||
When Logging in using web as "user0"
|
||||
And searching for contacts matching with "test"
|
||||
Then the list of searched contacts has "1" contacts
|
||||
And searched contact "0" is named "Test name"
|
||||
|
||||
Scenario: users can be searched by email when searcher belongs to both a group allowed to share and another group
|
||||
Given user "user0" exists
|
||||
And group "AllowedGroup" exists
|
||||
And user "user0" belongs to group "AllowedGroup"
|
||||
And group "AnotherGroup" exists
|
||||
And user "user0" belongs to group "AnotherGroup"
|
||||
And parameter "shareapi_exclude_groups" of app "core" is set to "allow"
|
||||
And parameter "shareapi_exclude_groups_list" of app "core" is set to "AllowedGroup"
|
||||
And user "user1" exists
|
||||
And As an "admin"
|
||||
And sending "PUT" to "/cloud/users/user1" with
|
||||
| key | email |
|
||||
| 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 "1" contacts
|
||||
And searched contact "0" is named "user1"
|
||||
|
||||
|
||||
|
||||
Scenario: users can not be found by display name if visibility is private
|
||||
Given user "user0" exists
|
||||
And user "user1" exists
|
||||
|
|
|
|||
|
|
@ -117,6 +117,81 @@ Feature: sharees
|
|||
And "exact remotes" sharees returned is empty
|
||||
And "remotes" sharees returned is empty
|
||||
|
||||
Scenario: Search when belonging to a group excluded from sharing
|
||||
Given As an "test"
|
||||
And parameter "shareapi_exclude_groups" of app "core" is set to "yes"
|
||||
And parameter "shareapi_exclude_groups_list" of app "core" is set to "ShareeGroup"
|
||||
When getting sharees for
|
||||
| search | sharee |
|
||||
| itemType | file |
|
||||
Then the OCS status code should be "100"
|
||||
And the HTTP status code should be "200"
|
||||
And "exact users" sharees returned is empty
|
||||
And "users" sharees returned is empty
|
||||
And "exact groups" sharees returned is empty
|
||||
And "groups" sharees returned is empty
|
||||
And "exact remotes" sharees returned is empty
|
||||
And "remotes" sharees returned is empty
|
||||
|
||||
Scenario: Search when belonging to both a group excluded from sharing and another group
|
||||
Given As an "test"
|
||||
And group "AnotherGroup" exists
|
||||
And user "test" belongs to group "AnotherGroup"
|
||||
And parameter "shareapi_exclude_groups" of app "core" is set to "yes"
|
||||
And parameter "shareapi_exclude_groups_list" of app "core" is set to "ShareeGroup"
|
||||
When getting sharees for
|
||||
| search | sharee |
|
||||
| itemType | file |
|
||||
Then the OCS status code should be "100"
|
||||
And the HTTP status code should be "200"
|
||||
And "exact users" sharees returned is empty
|
||||
And "users" sharees returned are
|
||||
| Sharee1 | 0 | Sharee1 | Sharee1 |
|
||||
| Sharee2 | 0 | Sharee2 | sharee2@system.com |
|
||||
And "exact groups" sharees returned is empty
|
||||
And "groups" sharees returned are
|
||||
| ShareeGroup | 1 | ShareeGroup |
|
||||
And "exact remotes" sharees returned is empty
|
||||
And "remotes" sharees returned is empty
|
||||
|
||||
Scenario: Search when not belonging to a group allowed to share
|
||||
Given As an "test"
|
||||
And group "AnotherGroup" exists
|
||||
And parameter "shareapi_exclude_groups" of app "core" is set to "allow"
|
||||
And parameter "shareapi_exclude_groups_list" of app "core" is set to "AnotherGroup"
|
||||
When getting sharees for
|
||||
| search | sharee |
|
||||
| itemType | file |
|
||||
Then the OCS status code should be "100"
|
||||
And the HTTP status code should be "200"
|
||||
And "exact users" sharees returned is empty
|
||||
And "users" sharees returned is empty
|
||||
And "exact groups" sharees returned is empty
|
||||
And "groups" sharees returned is empty
|
||||
And "exact remotes" sharees returned is empty
|
||||
And "remotes" sharees returned is empty
|
||||
|
||||
Scenario: Search when belonging to both a group allowed to share and another group
|
||||
Given As an "test"
|
||||
And group "AnotherGroup" exists
|
||||
And user "test" belongs to group "AnotherGroup"
|
||||
And parameter "shareapi_exclude_groups" of app "core" is set to "allow"
|
||||
And parameter "shareapi_exclude_groups_list" of app "core" is set to "AnotherGroup"
|
||||
When getting sharees for
|
||||
| search | sharee |
|
||||
| itemType | file |
|
||||
Then the OCS status code should be "100"
|
||||
And the HTTP status code should be "200"
|
||||
And "exact users" sharees returned is empty
|
||||
And "users" sharees returned are
|
||||
| Sharee1 | 0 | Sharee1 | Sharee1 |
|
||||
| Sharee2 | 0 | Sharee2 | sharee2@system.com |
|
||||
And "exact groups" sharees returned is empty
|
||||
And "groups" sharees returned are
|
||||
| ShareeGroup | 1 | ShareeGroup |
|
||||
And "exact remotes" sharees returned is empty
|
||||
And "remotes" sharees returned is empty
|
||||
|
||||
Scenario: Search without exact match no iteration allowed
|
||||
Given As an "test"
|
||||
And parameter "shareapi_allow_share_dialog_user_enumeration" of app "core" is set to "no"
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -188,7 +188,94 @@ class ContactsStoreTest extends TestCase {
|
|||
$this->assertEquals('https://photo', $entries[1]->getAvatar());
|
||||
}
|
||||
|
||||
public function testGetContactsWhenUserIsInExcludeGroups(): void {
|
||||
public static function dataGetContactsWhenUserIsInExcludeGroups(): array {
|
||||
return [
|
||||
['yes', '[]', [], ['user123', 'user12345']],
|
||||
['yes', '["excludedGroup1"]', [], ['user123', 'user12345']],
|
||||
['yes', '["excludedGroup1"]', ['anotherGroup1'], ['user123', 'user12345']],
|
||||
['yes', '["excludedGroup1"]', ['anotherGroup1', 'anotherGroup2', 'anotherGroup3'], ['user123', 'user12345']],
|
||||
['yes', '["excludedGroup1"]', ['excludedGroup1'], []],
|
||||
['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']],
|
||||
['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', ['excludedGroup1'], []],
|
||||
['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', ['excludedGroup2'], []],
|
||||
['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', ['excludedGroup3'], []],
|
||||
['yes', '["excludedGroup1", "excludedGroup2", "excludedGroup3"]', ['excludedGroup1', 'excludedGroup2', 'excludedGroup3'], []],
|
||||
['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'], []],
|
||||
['allow', '["allowedGroup1"]', ['anotherGroup1', 'anotherGroup2', 'anotherGroup3'], []],
|
||||
['allow', '["allowedGroup1"]', ['allowedGroup1'], ['user123', 'user12345']],
|
||||
['allow', '["allowedGroup1"]', ['anotherGroup1', 'allowedGroup1'], ['user123', 'user12345']],
|
||||
['allow', '["allowedGroup1"]', ['allowedGroup1', 'anotherGroup1', 'anotherGroup2', 'anotherGroup3'], ['user123', 'user12345']],
|
||||
['allow', '["allowedGroup1", "allowedGroup2", "allowedGroup3"]', [], []],
|
||||
['allow', '["allowedGroup1", "allowedGroup2", "allowedGroup3"]', ['anotherGroup1'], []],
|
||||
['allow', '["allowedGroup1", "allowedGroup2", "allowedGroup3"]', ['anotherGroup1', 'anotherGroup2', 'anotherGroup3'], []],
|
||||
['allow', '["allowedGroup1", "allowedGroup2", "allowedGroup3"]', ['allowedGroup1'], ['user123', 'user12345']],
|
||||
['allow', '["allowedGroup1", "allowedGroup2", "allowedGroup3"]', ['allowedGroup2'], ['user123', 'user12345']],
|
||||
['allow', '["allowedGroup1", "allowedGroup2", "allowedGroup3"]', ['allowedGroup3'], ['user123', 'user12345']],
|
||||
['allow', '["allowedGroup1", "allowedGroup2", "allowedGroup3"]', ['allowedGroup1', 'allowedGroup2', 'allowedGroup3'], ['user123', 'user12345']],
|
||||
['allow', '["allowedGroup1", "allowedGroup2", "allowedGroup3"]', ['anotherGroup1', 'allowedGroup1'], ['user123', 'user12345']],
|
||||
['allow', '["allowedGroup1", "allowedGroup2", "allowedGroup3"]', ['anotherGroup1', 'allowedGroup2', 'anotherGroup2', 'anotherGroup3'], ['user123', 'user12345']],
|
||||
['allow', '["allowedGroup1", "allowedGroup2", "allowedGroup3"]', ['allowedGroup3', 'anotherGroup1', 'anotherGroup2', 'anotherGroup3'], ['user123', 'user12345']],
|
||||
];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataGetContactsWhenUserIsInExcludeGroups')]
|
||||
public function testGetContactsWhenUserIsInExcludeGroups(string $excludeGroups, string $excludeGroupsList, array $currentUserGroupIds, array $expectedUids): void {
|
||||
$this->config
|
||||
->method('getAppValue')
|
||||
->willReturnMap([
|
||||
['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
|
||||
['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'],
|
||||
['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'],
|
||||
['core', 'shareapi_exclude_groups', 'no', $excludeGroups],
|
||||
['core', 'shareapi_only_share_with_group_members', 'no', 'no'],
|
||||
['core', 'shareapi_exclude_groups_list', '', $excludeGroupsList],
|
||||
['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
|
||||
]);
|
||||
|
||||
/** @var IUser|MockObject $currentUser */
|
||||
$currentUser = $this->createMock(IUser::class);
|
||||
$currentUser->expects($this->exactly(2))
|
||||
->method('getUID')
|
||||
->willReturn('user001');
|
||||
|
||||
$this->groupManager->expects($this->once())
|
||||
->method('getUserGroupIds')
|
||||
->with($this->equalTo($currentUser))
|
||||
->willReturn($currentUserGroupIds);
|
||||
|
||||
$this->contactsManager->expects($this->once())
|
||||
->method('search')
|
||||
->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL']))
|
||||
->willReturn([
|
||||
[
|
||||
'UID' => 'user123',
|
||||
'isLocalSystemBook' => true
|
||||
],
|
||||
[
|
||||
'UID' => 'user12345',
|
||||
'isLocalSystemBook' => true
|
||||
],
|
||||
]);
|
||||
|
||||
|
||||
$entries = $this->contactsStore->getContacts($currentUser, '');
|
||||
|
||||
$this->assertCount(count($expectedUids), $entries);
|
||||
for ($i = 0; $i < count($expectedUids); $i++) {
|
||||
$this->assertEquals($expectedUids[$i], $entries[$i]->getProperty('UID'));
|
||||
}
|
||||
}
|
||||
|
||||
public function testGetContactsOnlyShareIfInTheSameGroupWhenUserIsInExcludeGroups(): void {
|
||||
$this->config
|
||||
->method('getAppValue')
|
||||
->willReturnMap([
|
||||
|
|
|
|||
Loading…
Reference in a new issue