feat(php,vue): Create a new parameter

Signed-off-by: Baptiste Fotia <fotia.baptiste@hotmail.com>
pull/38173/head
Baptiste Fotia 5 months ago
parent 7cb7b8b6c3
commit 9af96d9f9a

@ -63,6 +63,7 @@ class Sharing implements IDelegatedSettings {
$excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
$linksExcludedGroups = $this->config->getAppValue('core', 'shareapi_allow_links_exclude_groups', '');
$excludedPasswordGroups = $this->config->getAppValue('core', 'shareapi_enforce_links_password_excluded_groups', '');
$onlyShareWithGroupMembersExcludeGroupList = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', '');
$parameters = [
// Built-In Sharing
@ -83,6 +84,7 @@ class Sharing implements IDelegatedSettings {
'passwordExcludedGroups' => json_decode($excludedPasswordGroups) ?? [],
'passwordExcludedGroupsFeatureEnabled' => $this->config->getSystemValueBool('sharing.allow_disabled_password_enforcement_groups', false),
'onlyShareWithGroupMembers' => $this->shareManager->shareWithGroupMembersOnly(),
'onlyShareWithGroupMembersExcludeGroupList' => json_decode($onlyShareWithGroupMembersExcludeGroupList) ?? [],
'defaultExpireDate' => $this->getHumanBooleanConfig('core', 'shareapi_default_expire_date'),
'expireAfterNDays' => $this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7'),
'enforceExpireDate' => $this->getHumanBooleanConfig('core', 'shareapi_enforce_expire_date'),

@ -37,6 +37,13 @@
<NcCheckboxRadioSwitch :checked.sync="settings.onlyShareWithGroupMembers">
{{ t('settings', 'Restrict users to only share with users in their groups') }}
</NcCheckboxRadioSwitch>
<div v-show="settings.onlyShareWithGroupMembers" id="settings-sharing-api-excluded-groups" class="sharing__labeled-entry sharing__input">
<label for="settings-sharing-only-group-members-excluded-groups">{{ t('settings', 'Ignore the following groups when checking group membership') }}</label>
<NcSettingsSelectGroup id="settings-sharing-only-group-members-excluded-groups"
v-model="settings.onlyShareWithGroupMembersExcludeGroupList"
:label="t('settings', 'Ignore the following groups when checking group membership')"
style="width: 100%" />
</div>
</div>
<div v-show="settings.enabled" id="settings-sharing-api" class="sharing__section">
@ -216,6 +223,7 @@ interface IShareSettings {
passwordExcludedGroups: string[]
passwordExcludedGroupsFeatureEnabled: boolean
onlyShareWithGroupMembers: boolean
onlyShareWithGroupMembersExcludeGroupList: string[]
defaultExpireDate: boolean
expireAfterNDays: string
enforceExpireDate: boolean

@ -163,6 +163,7 @@ class SharingTest extends TestCase {
'allowLinksExcludeGroups' => [],
'passwordExcludedGroups' => [],
'passwordExcludedGroupsFeatureEnabled' => false,
'onlyShareWithGroupMembersExcludeGroupList' => [],
]
],
);
@ -254,6 +255,7 @@ class SharingTest extends TestCase {
'allowLinksExcludeGroups' => [],
'passwordExcludedGroups' => [],
'passwordExcludedGroupsFeatureEnabled' => false,
'onlyShareWithGroupMembersExcludeGroupList' => [],
]
],
);

@ -49,11 +49,16 @@ class GroupPlugin implements ISearchPlugin {
private IConfig $config,
private IGroupManager $groupManager,
private IUserSession $userSession,
private mixed $shareWithGroupOnlyExcludeGroupsList = [],
) {
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
$this->shareeEnumerationInGroupOnly = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
$this->groupSharingDisabled = $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'no';
if ($this->shareWithGroupOnly) {
$this->shareWithGroupOnlyExcludeGroupsList = json_decode($this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', ''), true) ?? [];
}
}
public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
@ -81,6 +86,9 @@ class GroupPlugin implements ISearchPlugin {
return $group->getGID();
}, $userGroups);
$groupIds = array_intersect($groupIds, $userGroups);
// ShareWithGroupOnly filtering
$groupIds = array_diff($groupIds, $this->shareWithGroupOnlyExcludeGroupsList);
}
$lowerSearch = strtolower($search);

@ -61,6 +61,7 @@ class MailPlugin implements ISearchPlugin {
private KnownUserService $knownUserService,
private IUserSession $userSession,
private IMailer $mailer,
private mixed $shareWithGroupOnlyExcludeGroupsList = [],
) {
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
@ -68,6 +69,10 @@ class MailPlugin implements ISearchPlugin {
$this->shareeEnumerationPhone = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
$this->shareeEnumerationFullMatch = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes') === 'yes';
$this->shareeEnumerationFullMatchEmail = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes') === 'yes';
if ($this->shareWithGroupOnly) {
$this->shareWithGroupOnlyExcludeGroupsList = json_decode($this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', ''), true) ?? [];
}
}
/**
@ -127,6 +132,10 @@ class MailPlugin implements ISearchPlugin {
* Check if the user may share with the user associated with the e-mail of the just found contact
*/
$userGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser());
// ShareWithGroupOnly filtering
$userGroups = array_diff($userGroups, $this->shareWithGroupOnlyExcludeGroupsList);
$found = false;
foreach ($userGroups as $userGroup) {
if ($this->groupManager->isInGroup($contact['UID'], $userGroup)) {

@ -67,6 +67,7 @@ class UserPlugin implements ISearchPlugin {
private IUserSession $userSession,
private KnownUserService $knownUserService,
private IUserStatusManager $userStatusManager,
private mixed $shareWithGroupOnlyExcludeGroupsList = [],
) {
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
@ -76,6 +77,10 @@ class UserPlugin implements ISearchPlugin {
$this->shareeEnumerationFullMatchUserId = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_userid', 'yes') === 'yes';
$this->shareeEnumerationFullMatchEmail = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes') === 'yes';
$this->shareeEnumerationFullMatchIgnoreSecondDisplayName = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_dn', 'no') === 'yes';
if ($this->shareWithGroupOnly) {
$this->shareWithGroupOnlyExcludeGroupsList = json_decode($this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', ''), true) ?? [];
}
}
public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
@ -85,6 +90,10 @@ class UserPlugin implements ISearchPlugin {
$currentUserId = $this->userSession->getUser()->getUID();
$currentUserGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser());
// ShareWithGroupOnly filtering
$currentUserGroups = array_diff($currentUserGroups, $this->shareWithGroupOnlyExcludeGroupsList);
if ($this->shareWithGroupOnly || $this->shareeEnumerationInGroupOnly) {
// Search in all the groups this user is part of
foreach ($currentUserGroups as $userGroupId) {

@ -177,6 +177,9 @@ class ContactsStore implements IContactsStore {
* 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.
* If enabled, the 'shareapi_only_share_with_group_members_exclude_group_list'
* config option may specify some groups excluded from the principle of
* belonging to the same group.
*
* @param Entry[] $entries
* @return Entry[] the filtered contacts
@ -210,6 +213,13 @@ class ContactsStore implements IContactsStore {
}
}
// ownGroupsOnly : some groups may be excluded
if ($ownGroupsOnly) {
$excludeGroupsFromOwnGroups = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', '');
$excludeGroupsFromOwnGroupsList = json_decode($excludeGroupsFromOwnGroups, true) ?? [];
$selfGroups = array_diff($selfGroups, $excludeGroupsFromOwnGroupsList);
}
$selfUID = $self->getUID();
return array_values(array_filter($entries, function (IEntry $entry) use ($skipLocal, $ownGroupsOnly, $selfGroups, $selfUID, $disallowEnumeration, $restrictEnumerationGroup, $restrictEnumerationPhone, $allowEnumerationFullMatch, $filter) {

@ -548,6 +548,11 @@ class Manager implements IManager {
$this->groupManager->getUserGroupIds($sharedBy),
$this->groupManager->getUserGroupIds($sharedWith)
);
// optional excluded groups
$excludedGroups = $this->shareWithGroupMembersOnlyExcludeGroupsList();
$groups = array_diff($groups, $excludedGroups);
if (empty($groups)) {
$message_t = $this->l->t('Sharing is only allowed with group members');
throw new \Exception($message_t);
@ -608,7 +613,10 @@ class Manager implements IManager {
if ($this->shareWithGroupMembersOnly()) {
$sharedBy = $this->userManager->get($share->getSharedBy());
$sharedWith = $this->groupManager->get($share->getSharedWith());
if (is_null($sharedWith) || !$sharedWith->inGroup($sharedBy)) {
// optional excluded groups
$excludedGroups = $this->shareWithGroupMembersOnlyExcludeGroupsList();
if (is_null($sharedWith) || in_array($share->getSharedWith(), $excludedGroups) || !$sharedWith->inGroup($sharedBy)) {
throw new \Exception('Sharing is only allowed within your own groups');
}
}
@ -1938,6 +1946,21 @@ class Manager implements IManager {
return $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
}
/**
* If shareWithGroupMembersOnly is enabled, return an optional
* list of groups that must be excluded from the principle of
* belonging to the same group.
*
* @return array
*/
public function shareWithGroupMembersOnlyExcludeGroupsList() {
if (!$this->shareWithGroupMembersOnly()) {
return [];
}
$excludeGroups = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', '');
return json_decode($excludeGroups, true) ?? [];
}
/**
* Check if users can share with groups
*

@ -415,6 +415,15 @@ interface IManager {
*/
public function shareWithGroupMembersOnly();
/**
* If shareWithGroupMembersOnly is enabled, return an optional
* list of groups that must be excluded from the principle of
* belonging to the same group.
* @return array
* @since 27.0.0
*/
public function shareWithGroupMembersOnlyExcludeGroupsList();
/**
* Check if users can share with groups
* @return bool

@ -1569,6 +1569,7 @@ class ManagerTest extends \Test\TestCase {
->method('getAppValue')
->willReturnMap([
['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
]);
self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
@ -1602,6 +1603,7 @@ class ManagerTest extends \Test\TestCase {
->method('getAppValue')
->willReturnMap([
['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
]);
$this->defaultProvider
@ -1794,6 +1796,7 @@ class ManagerTest extends \Test\TestCase {
->willReturnMap([
['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
]);
self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
@ -1817,6 +1820,7 @@ class ManagerTest extends \Test\TestCase {
->willReturnMap([
['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
]);
$this->assertNull($this->invokePrivate($this->manager, 'groupCreateChecks', [$share]));
@ -1846,6 +1850,7 @@ class ManagerTest extends \Test\TestCase {
->willReturnMap([
['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
]);
self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);

Loading…
Cancel
Save