Skip to content

Commit 69d95d7

Browse files
committed
feat(php,vue): Create a new parameter
Signed-off-by: Baptiste Fotia <[email protected]>
1 parent fdc64ea commit 69d95d7

File tree

10 files changed

+86
-1
lines changed

10 files changed

+86
-1
lines changed

apps/settings/lib/Settings/Admin/Sharing.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public function getForm() {
6363
$excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
6464
$linksExcludedGroups = $this->config->getAppValue('core', 'shareapi_allow_links_exclude_groups', '');
6565
$excludedPasswordGroups = $this->config->getAppValue('core', 'shareapi_enforce_links_password_excluded_groups', '');
66+
$onlyShareWithGroupMembersExcludeGroupList = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', '');
6667

6768
$parameters = [
6869
// Built-In Sharing
@@ -83,6 +84,7 @@ public function getForm() {
8384
'passwordExcludedGroups' => json_decode($excludedPasswordGroups) ?? [],
8485
'passwordExcludedGroupsFeatureEnabled' => $this->config->getSystemValueBool('sharing.allow_disabled_password_enforcement_groups', false),
8586
'onlyShareWithGroupMembers' => $this->shareManager->shareWithGroupMembersOnly(),
87+
'onlyShareWithGroupMembersExcludeGroupList' => json_decode($onlyShareWithGroupMembersExcludeGroupList) ?? [],
8688
'defaultExpireDate' => $this->getHumanBooleanConfig('core', 'shareapi_default_expire_date'),
8789
'expireAfterNDays' => $this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7'),
8890
'enforceExpireDate' => $this->getHumanBooleanConfig('core', 'shareapi_enforce_expire_date'),

apps/settings/src/components/AdminSettingsSharingForm.vue

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@
3737
<NcCheckboxRadioSwitch :checked.sync="settings.onlyShareWithGroupMembers">
3838
{{ t('settings', 'Restrict users to only share with users in their groups') }}
3939
</NcCheckboxRadioSwitch>
40+
<div v-show="settings.onlyShareWithGroupMembers" id="settings-sharing-api-excluded-groups" class="sharing__labeled-entry sharing__input">
41+
<label for="settings-sharing-only-group-members-excluded-groups">{{ t('settings', 'Ignore the following groups when checking group membership') }}</label>
42+
<NcSettingsSelectGroup id="settings-sharing-only-group-members-excluded-groups"
43+
v-model="settings.onlyShareWithGroupMembersExcludeGroupList"
44+
:label="t('settings', 'Ignore the following groups when checking group membership')"
45+
style="width: 100%" />
46+
</div>
4047
</div>
4148

4249
<div v-show="settings.enabled" id="settings-sharing-api" class="sharing__section">
@@ -218,6 +225,7 @@ interface IShareSettings {
218225
passwordExcludedGroups: string[]
219226
passwordExcludedGroupsFeatureEnabled: boolean
220227
onlyShareWithGroupMembers: boolean
228+
onlyShareWithGroupMembersExcludeGroupList: string[]
221229
defaultExpireDate: boolean
222230
expireAfterNDays: string
223231
enforceExpireDate: boolean

apps/settings/tests/Settings/Admin/SharingTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ public function testGetFormWithoutExcludedGroups(): void {
163163
'allowLinksExcludeGroups' => [],
164164
'passwordExcludedGroups' => [],
165165
'passwordExcludedGroupsFeatureEnabled' => false,
166+
'onlyShareWithGroupMembersExcludeGroupList' => [],
166167
]
167168
],
168169
);
@@ -254,6 +255,7 @@ public function testGetFormWithExcludedGroups(): void {
254255
'allowLinksExcludeGroups' => [],
255256
'passwordExcludedGroups' => [],
256257
'passwordExcludedGroupsFeatureEnabled' => false,
258+
'onlyShareWithGroupMembersExcludeGroupList' => [],
257259
]
258260
],
259261
);

lib/private/Collaboration/Collaborators/GroupPlugin.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,16 @@ public function __construct(
4949
private IConfig $config,
5050
private IGroupManager $groupManager,
5151
private IUserSession $userSession,
52+
private mixed $shareWithGroupOnlyExcludeGroupsList = [],
5253
) {
5354
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
5455
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
5556
$this->shareeEnumerationInGroupOnly = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
5657
$this->groupSharingDisabled = $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'no';
58+
59+
if ($this->shareWithGroupOnly) {
60+
$this->shareWithGroupOnlyExcludeGroupsList = json_decode($this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', ''), true) ?? [];
61+
}
5762
}
5863

5964
public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
@@ -81,6 +86,9 @@ public function search($search, $limit, $offset, ISearchResult $searchResult): b
8186
return $group->getGID();
8287
}, $userGroups);
8388
$groupIds = array_intersect($groupIds, $userGroups);
89+
90+
// ShareWithGroupOnly filtering
91+
$groupIds = array_diff($groupIds, $this->shareWithGroupOnlyExcludeGroupsList);
8492
}
8593

8694
$lowerSearch = strtolower($search);

lib/private/Collaboration/Collaborators/MailPlugin.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,18 @@ public function __construct(
6161
private KnownUserService $knownUserService,
6262
private IUserSession $userSession,
6363
private IMailer $mailer,
64+
private mixed $shareWithGroupOnlyExcludeGroupsList = [],
6465
) {
6566
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
6667
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
6768
$this->shareeEnumerationInGroupOnly = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
6869
$this->shareeEnumerationPhone = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
6970
$this->shareeEnumerationFullMatch = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes') === 'yes';
7071
$this->shareeEnumerationFullMatchEmail = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes') === 'yes';
72+
73+
if ($this->shareWithGroupOnly) {
74+
$this->shareWithGroupOnlyExcludeGroupsList = json_decode($this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', ''), true) ?? [];
75+
}
7176
}
7277

7378
/**
@@ -127,6 +132,10 @@ public function search($search, $limit, $offset, ISearchResult $searchResult): b
127132
* Check if the user may share with the user associated with the e-mail of the just found contact
128133
*/
129134
$userGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser());
135+
136+
// ShareWithGroupOnly filtering
137+
$userGroups = array_diff($userGroups, $this->shareWithGroupOnlyExcludeGroupsList);
138+
130139
$found = false;
131140
foreach ($userGroups as $userGroup) {
132141
if ($this->groupManager->isInGroup($contact['UID'], $userGroup)) {

lib/private/Collaboration/Collaborators/UserPlugin.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public function __construct(
6767
private IUserSession $userSession,
6868
private KnownUserService $knownUserService,
6969
private IUserStatusManager $userStatusManager,
70+
private mixed $shareWithGroupOnlyExcludeGroupsList = [],
7071
) {
7172
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
7273
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
@@ -76,6 +77,10 @@ public function __construct(
7677
$this->shareeEnumerationFullMatchUserId = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_userid', 'yes') === 'yes';
7778
$this->shareeEnumerationFullMatchEmail = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes') === 'yes';
7879
$this->shareeEnumerationFullMatchIgnoreSecondDisplayName = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_dn', 'no') === 'yes';
80+
81+
if ($this->shareWithGroupOnly) {
82+
$this->shareWithGroupOnlyExcludeGroupsList = json_decode($this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', ''), true) ?? [];
83+
}
7984
}
8085

8186
public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
@@ -85,6 +90,10 @@ public function search($search, $limit, $offset, ISearchResult $searchResult): b
8590

8691
$currentUserId = $this->userSession->getUser()->getUID();
8792
$currentUserGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser());
93+
94+
// ShareWithGroupOnly filtering
95+
$currentUserGroups = array_diff($currentUserGroups, $this->shareWithGroupOnlyExcludeGroupsList);
96+
8897
if ($this->shareWithGroupOnly || $this->shareeEnumerationInGroupOnly) {
8998
// Search in all the groups this user is part of
9099
foreach ($currentUserGroups as $userGroupId) {

lib/private/Contacts/ContactsMenu/ContactsStore.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ public function getContacts(IUser $user, ?string $filter, ?int $limit = null, ?i
177177
* 3. if the `shareapi_only_share_with_group_members` config option is
178178
* enabled it will filter all users which doesn't have a common group
179179
* with the current user.
180+
* If enabled, the 'shareapi_only_share_with_group_members_exclude_group_list'
181+
* config option may specify some groups excluded from the principle of
182+
* belonging to the same group.
180183
*
181184
* @param Entry[] $entries
182185
* @return Entry[] the filtered contacts
@@ -210,6 +213,13 @@ private function filterContacts(
210213
}
211214
}
212215

216+
// ownGroupsOnly : some groups may be excluded
217+
if ($ownGroupsOnly) {
218+
$excludeGroupsFromOwnGroups = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', '');
219+
$excludeGroupsFromOwnGroupsList = json_decode($excludeGroupsFromOwnGroups, true) ?? [];
220+
$selfGroups = array_diff($selfGroups, $excludeGroupsFromOwnGroupsList);
221+
}
222+
213223
$selfUID = $self->getUID();
214224

215225
return array_values(array_filter($entries, function (IEntry $entry) use ($skipLocal, $ownGroupsOnly, $selfGroups, $selfUID, $disallowEnumeration, $restrictEnumerationGroup, $restrictEnumerationPhone, $allowEnumerationFullMatch, $filter) {

lib/private/Share20/Manager.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,11 @@ protected function userCreateChecks(IShare $share) {
548548
$this->groupManager->getUserGroupIds($sharedBy),
549549
$this->groupManager->getUserGroupIds($sharedWith)
550550
);
551+
552+
// optional excluded groups
553+
$excludedGroups = $this->shareWithGroupMembersOnlyExcludeGroupsList();
554+
$groups = array_diff($groups, $excludedGroups);
555+
551556
if (empty($groups)) {
552557
$message_t = $this->l->t('Sharing is only allowed with group members');
553558
throw new \Exception($message_t);
@@ -608,7 +613,10 @@ protected function groupCreateChecks(IShare $share) {
608613
if ($this->shareWithGroupMembersOnly()) {
609614
$sharedBy = $this->userManager->get($share->getSharedBy());
610615
$sharedWith = $this->groupManager->get($share->getSharedWith());
611-
if (is_null($sharedWith) || !$sharedWith->inGroup($sharedBy)) {
616+
617+
// optional excluded groups
618+
$excludedGroups = $this->shareWithGroupMembersOnlyExcludeGroupsList();
619+
if (is_null($sharedWith) || in_array($share->getSharedWith(), $excludedGroups) || !$sharedWith->inGroup($sharedBy)) {
612620
throw new \Exception('Sharing is only allowed within your own groups');
613621
}
614622
}
@@ -1938,6 +1946,21 @@ public function shareWithGroupMembersOnly() {
19381946
return $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
19391947
}
19401948

1949+
/**
1950+
* If shareWithGroupMembersOnly is enabled, return an optional
1951+
* list of groups that must be excluded from the principle of
1952+
* belonging to the same group.
1953+
*
1954+
* @return array
1955+
*/
1956+
public function shareWithGroupMembersOnlyExcludeGroupsList() {
1957+
if (!$this->shareWithGroupMembersOnly()) {
1958+
return [];
1959+
}
1960+
$excludeGroups = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', '');
1961+
return json_decode($excludeGroups, true) ?? [];
1962+
}
1963+
19411964
/**
19421965
* Check if users can share with groups
19431966
*

lib/public/Share/IManager.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,15 @@ public function shareApiLinkAllowPublicUpload();
415415
*/
416416
public function shareWithGroupMembersOnly();
417417

418+
/**
419+
* If shareWithGroupMembersOnly is enabled, return an optional
420+
* list of groups that must be excluded from the principle of
421+
* belonging to the same group.
422+
* @return array
423+
* @since 27.0.0
424+
*/
425+
public function shareWithGroupMembersOnlyExcludeGroupsList();
426+
418427
/**
419428
* Check if users can share with groups
420429
* @return bool

tests/lib/Share20/ManagerTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1569,6 +1569,7 @@ public function testUserCreateChecksShareWithGroupMembersOnlyDifferentGroups() {
15691569
->method('getAppValue')
15701570
->willReturnMap([
15711571
['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
1572+
['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
15721573
]);
15731574

15741575
self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
@@ -1602,6 +1603,7 @@ public function testUserCreateChecksShareWithGroupMembersOnlySharedGroup() {
16021603
->method('getAppValue')
16031604
->willReturnMap([
16041605
['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
1606+
['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
16051607
]);
16061608

16071609
$this->defaultProvider
@@ -1794,6 +1796,7 @@ public function testGroupCreateChecksShareWithGroupMembersOnlyNotInGroup() {
17941796
->willReturnMap([
17951797
['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
17961798
['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
1799+
['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
17971800
]);
17981801

17991802
self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
@@ -1817,6 +1820,7 @@ public function testGroupCreateChecksShareWithGroupMembersOnlyNullGroup() {
18171820
->willReturnMap([
18181821
['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
18191822
['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
1823+
['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
18201824
]);
18211825

18221826
$this->assertNull($this->invokePrivate($this->manager, 'groupCreateChecks', [$share]));
@@ -1846,6 +1850,7 @@ public function testGroupCreateChecksShareWithGroupMembersOnlyInGroup() {
18461850
->willReturnMap([
18471851
['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
18481852
['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
1853+
['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
18491854
]);
18501855

18511856
self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);

0 commit comments

Comments
 (0)