aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/Collaboration/Collaborators
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private/Collaboration/Collaborators')
-rw-r--r--lib/private/Collaboration/Collaborators/GroupPlugin.php69
-rw-r--r--lib/private/Collaboration/Collaborators/LookupPlugin.php72
-rw-r--r--lib/private/Collaboration/Collaborators/MailPlugin.php146
-rw-r--r--lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php41
-rw-r--r--lib/private/Collaboration/Collaborators/RemotePlugin.php62
-rw-r--r--lib/private/Collaboration/Collaborators/Search.php55
-rw-r--r--lib/private/Collaboration/Collaborators/SearchResult.php40
-rw-r--r--lib/private/Collaboration/Collaborators/UserPlugin.php131
8 files changed, 210 insertions, 406 deletions
diff --git a/lib/private/Collaboration/Collaborators/GroupPlugin.php b/lib/private/Collaboration/Collaborators/GroupPlugin.php
index 75e52c19e0b..a59d5981825 100644
--- a/lib/private/Collaboration/Collaborators/GroupPlugin.php
+++ b/lib/private/Collaboration/Collaborators/GroupPlugin.php
@@ -1,29 +1,8 @@
<?php
+
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -37,34 +16,31 @@ use OCP\IUserSession;
use OCP\Share\IShare;
class GroupPlugin implements ISearchPlugin {
- /** @var bool */
- protected $shareeEnumeration;
- /** @var bool */
- protected $shareWithGroupOnly;
- /** @var bool */
- protected $shareeEnumerationInGroupOnly;
- /** @var bool */
- protected $groupSharingDisabled;
-
- /** @var IGroupManager */
- private $groupManager;
- /** @var IConfig */
- private $config;
- /** @var IUserSession */
- private $userSession;
-
- public function __construct(IConfig $config, IGroupManager $groupManager, IUserSession $userSession) {
- $this->groupManager = $groupManager;
- $this->config = $config;
- $this->userSession = $userSession;
+ protected bool $shareeEnumeration;
+
+ protected bool $shareWithGroupOnly;
+
+ protected bool $shareeEnumerationInGroupOnly;
+
+ protected bool $groupSharingDisabled;
+ public function __construct(
+ 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) {
+ public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
if ($this->groupSharingDisabled) {
return false;
}
@@ -89,6 +65,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);
diff --git a/lib/private/Collaboration/Collaborators/LookupPlugin.php b/lib/private/Collaboration/Collaborators/LookupPlugin.php
index 72cbfd4de4b..fb6b9f2e0e8 100644
--- a/lib/private/Collaboration/Collaborators/LookupPlugin.php
+++ b/lib/private/Collaboration/Collaborators/LookupPlugin.php
@@ -1,29 +1,8 @@
<?php
+
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author J0WI <J0WI@users.noreply.github.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -38,42 +17,33 @@ use OCP\Share\IShare;
use Psr\Log\LoggerInterface;
class LookupPlugin implements ISearchPlugin {
-
- /** @var IConfig */
- private $config;
- /** @var IClientService */
- private $clientService;
/** @var string remote part of the current user's cloud id */
- private $currentUserRemote;
- /** @var ICloudIdManager */
- private $cloudIdManager;
- /** @var LoggerInterface */
- private $logger;
+ private string $currentUserRemote;
- public function __construct(IConfig $config,
- IClientService $clientService,
- IUserSession $userSession,
- ICloudIdManager $cloudIdManager,
- LoggerInterface $logger) {
- $this->config = $config;
- $this->clientService = $clientService;
- $this->cloudIdManager = $cloudIdManager;
+ public function __construct(
+ private IConfig $config,
+ private IClientService $clientService,
+ IUserSession $userSession,
+ private ICloudIdManager $cloudIdManager,
+ private LoggerInterface $logger,
+ ) {
$currentUserCloudId = $userSession->getUser()->getCloudId();
$this->currentUserRemote = $cloudIdManager->resolveCloudId($currentUserCloudId)->getRemote();
- $this->logger = $logger;
}
- public function search($search, $limit, $offset, ISearchResult $searchResult) {
- $isGlobalScaleEnabled = $this->config->getSystemValue('gs.enabled', false);
- $isLookupServerEnabled = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'yes') === 'yes';
+ public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
+ $isGlobalScaleEnabled = $this->config->getSystemValueBool('gs.enabled', false);
+ $isLookupServerEnabled = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no') === 'yes';
$hasInternetConnection = $this->config->getSystemValueBool('has_internet_connection', true);
- // if case of Global Scale we always search the lookup server
- if (!$isGlobalScaleEnabled && (!$isLookupServerEnabled || !$hasInternetConnection)) {
+ // If case of Global Scale we always search the lookup server
+ // TODO: Reconsider using the lookup server for non-global scale
+ // if (!$isGlobalScaleEnabled && (!$isLookupServerEnabled || !$hasInternetConnection || $disableLookupServer)) {
+ if (!$isGlobalScaleEnabled) {
return false;
}
- $lookupServerUrl = $this->config->getSystemValue('lookup_server', 'https://lookup.nextcloud.com');
+ $lookupServerUrl = $this->config->getSystemValueString('lookup_server', 'https://lookup.nextcloud.com');
if (empty($lookupServerUrl)) {
return false;
}
@@ -96,7 +66,7 @@ class LookupPlugin implements ISearchPlugin {
try {
$remote = $this->cloudIdManager->resolveCloudId($lookup['federationId'])->getRemote();
} catch (\Exception $e) {
- $this->logger->error('Can not parse federated cloud ID "' . $lookup['federationId'] . '"', [
+ $this->logger->error('Can not parse federated cloud ID "' . $lookup['federationId'] . '"', [
'exception' => $e,
]);
continue;
@@ -104,7 +74,7 @@ class LookupPlugin implements ISearchPlugin {
if ($this->currentUserRemote === $remote) {
continue;
}
- $name = isset($lookup['name']['value']) ? $lookup['name']['value'] : '';
+ $name = $lookup['name']['value'] ?? '';
$label = empty($name) ? $lookup['federationId'] : $name . ' (' . $lookup['federationId'] . ')';
$result[] = [
'label' => $label,
diff --git a/lib/private/Collaboration/Collaborators/MailPlugin.php b/lib/private/Collaboration/Collaborators/MailPlugin.php
index aae6f305981..55e3945ace2 100644
--- a/lib/private/Collaboration/Collaborators/MailPlugin.php
+++ b/lib/private/Collaboration/Collaborators/MailPlugin.php
@@ -1,28 +1,8 @@
<?php
+
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Tobia De Koninck <tobia@ledfan.be>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -37,63 +17,58 @@ use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserSession;
-use OCP\Share\IShare;
use OCP\Mail\IMailer;
+use OCP\Share\IShare;
class MailPlugin implements ISearchPlugin {
- /* @var bool */
- protected $shareWithGroupOnly;
- /* @var bool */
- protected $shareeEnumeration;
- /* @var bool */
- protected $shareeEnumerationInGroupOnly;
- /* @var bool */
- protected $shareeEnumerationPhone;
- /* @var bool */
- protected $shareeEnumerationFullMatch;
-
- /** @var IManager */
- private $contactsManager;
- /** @var ICloudIdManager */
- private $cloudIdManager;
- /** @var IConfig */
- private $config;
-
- /** @var IGroupManager */
- private $groupManager;
- /** @var KnownUserService */
- private $knownUserService;
- /** @var IUserSession */
- private $userSession;
- /** @var IMailer */
- private $mailer;
-
- public function __construct(IManager $contactsManager,
- ICloudIdManager $cloudIdManager,
- IConfig $config,
- IGroupManager $groupManager,
- KnownUserService $knownUserService,
- IUserSession $userSession,
- IMailer $mailer) {
- $this->contactsManager = $contactsManager;
- $this->cloudIdManager = $cloudIdManager;
- $this->config = $config;
- $this->groupManager = $groupManager;
- $this->knownUserService = $knownUserService;
- $this->userSession = $userSession;
- $this->mailer = $mailer;
+ protected bool $shareWithGroupOnly;
+
+ protected bool $shareeEnumeration;
+
+ protected bool $shareeEnumerationInGroupOnly;
+ protected bool $shareeEnumerationPhone;
+
+ protected bool $shareeEnumerationFullMatch;
+
+ protected bool $shareeEnumerationFullMatchEmail;
+
+ public function __construct(
+ private IManager $contactsManager,
+ private ICloudIdManager $cloudIdManager,
+ private IConfig $config,
+ private IGroupManager $groupManager,
+ 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';
$this->shareeEnumerationInGroupOnly = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
$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) ?? [];
+ }
}
/**
* {@inheritdoc}
*/
- public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
+ if ($this->shareeEnumerationFullMatch && !$this->shareeEnumerationFullMatchEmail) {
+ return false;
+ }
+
+ // Extract the email address from "Foo Bar <foo.bar@example.tld>" and then search with "foo.bar@example.tld" instead
+ $result = preg_match('/<([^@]+@.+)>$/', $search, $matches);
+ if ($result && filter_var($matches[1], FILTER_VALIDATE_EMAIL)) {
+ return $this->search($matches[1], $limit, $offset, $searchResult);
+ }
+
$currentUserId = $this->userSession->getUser()->getUID();
$result = $userResults = ['wide' => [], 'exact' => []];
@@ -107,8 +82,8 @@ class MailPlugin implements ISearchPlugin {
[
'limit' => $limit,
'offset' => $offset,
- 'enumeration' => (bool) $this->shareeEnumeration,
- 'fullmatch' => (bool) $this->shareeEnumerationFullMatch,
+ 'enumeration' => $this->shareeEnumeration,
+ 'fullmatch' => $this->shareeEnumerationFullMatch,
]
);
$lowerSearch = strtolower($search);
@@ -126,6 +101,11 @@ class MailPlugin implements ISearchPlugin {
$emailAddress = $emailAddressData['value'];
$emailAddressType = $emailAddressData['type'];
}
+
+ if (!filter_var($emailAddress, FILTER_VALIDATE_EMAIL)) {
+ continue;
+ }
+
if (isset($contact['FN'])) {
$displayName = $contact['FN'] . ' (' . $emailAddress . ')';
}
@@ -137,6 +117,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)) {
@@ -150,7 +134,7 @@ class MailPlugin implements ISearchPlugin {
}
if ($exactEmailMatch && $this->shareeEnumerationFullMatch) {
try {
- $cloud = $this->cloudIdManager->resolveCloudId($contact['CLOUD'][0]);
+ $cloud = $this->cloudIdManager->resolveCloudId($contact['CLOUD'][0] ?? '');
} catch (\InvalidArgumentException $e) {
continue;
}
@@ -158,8 +142,8 @@ class MailPlugin implements ISearchPlugin {
if (!$this->isCurrentUser($cloud) && !$searchResult->hasResult($userType, $cloud->getUser())) {
$singleResult = [[
'label' => $displayName,
- 'uuid' => $contact['UID'],
- 'name' => $contact['FN'],
+ 'uuid' => $contact['UID'] ?? $emailAddress,
+ 'name' => $contact['FN'] ?? $displayName,
'value' => [
'shareType' => IShare::TYPE_USER,
'shareWith' => $cloud->getUser(),
@@ -175,7 +159,7 @@ class MailPlugin implements ISearchPlugin {
if ($this->shareeEnumeration) {
try {
- $cloud = $this->cloudIdManager->resolveCloudId($contact['CLOUD'][0]);
+ $cloud = $this->cloudIdManager->resolveCloudId($contact['CLOUD'][0] ?? '');
} catch (\InvalidArgumentException $e) {
continue;
}
@@ -198,8 +182,8 @@ class MailPlugin implements ISearchPlugin {
if ($addToWide && !$this->isCurrentUser($cloud) && !$searchResult->hasResult($userType, $cloud->getUser())) {
$userResults['wide'][] = [
'label' => $displayName,
- 'uuid' => $contact['UID'],
- 'name' => $contact['FN'],
+ 'uuid' => $contact['UID'] ?? $emailAddress,
+ 'name' => $contact['FN'] ?? $displayName,
'value' => [
'shareType' => IShare::TYPE_USER,
'shareWith' => $cloud->getUser(),
@@ -219,8 +203,8 @@ class MailPlugin implements ISearchPlugin {
}
$result['exact'][] = [
'label' => $displayName,
- 'uuid' => $contact['UID'],
- 'name' => $contact['FN'],
+ 'uuid' => $contact['UID'] ?? $emailAddress,
+ 'name' => $contact['FN'] ?? $displayName,
'type' => $emailAddressType ?? '',
'value' => [
'shareType' => IShare::TYPE_EMAIL,
@@ -230,8 +214,8 @@ class MailPlugin implements ISearchPlugin {
} else {
$result['wide'][] = [
'label' => $displayName,
- 'uuid' => $contact['UID'],
- 'name' => $contact['FN'],
+ 'uuid' => $contact['UID'] ?? $emailAddress,
+ 'name' => $contact['FN'] ?? $displayName,
'type' => $emailAddressType ?? '',
'value' => [
'shareType' => IShare::TYPE_EMAIL,
@@ -245,8 +229,8 @@ class MailPlugin implements ISearchPlugin {
$reachedEnd = true;
if ($this->shareeEnumeration) {
- $reachedEnd = (count($result['wide']) < $offset + $limit) &&
- (count($userResults['wide']) < $offset + $limit);
+ $reachedEnd = (count($result['wide']) < $offset + $limit)
+ && (count($userResults['wide']) < $offset + $limit);
$result['wide'] = array_slice($result['wide'], $offset, $limit);
$userResults['wide'] = array_slice($userResults['wide'], $offset, $limit);
@@ -273,6 +257,6 @@ class MailPlugin implements ISearchPlugin {
public function isCurrentUser(ICloudId $cloud): bool {
$currentUser = $this->userSession->getUser();
- return $currentUser instanceof IUser ? $currentUser->getUID() === $cloud->getUser() : false;
+ return $currentUser instanceof IUser && $currentUser->getUID() === $cloud->getUser();
}
}
diff --git a/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php b/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php
index 413799e52c6..f4c1793ea0a 100644
--- a/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php
+++ b/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php
@@ -1,26 +1,8 @@
<?php
+
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -33,14 +15,12 @@ use OCP\Share;
use OCP\Share\IShare;
class RemoteGroupPlugin implements ISearchPlugin {
- protected $shareeEnumeration;
-
- /** @var ICloudIdManager */
- private $cloudIdManager;
- /** @var bool */
- private $enabled = false;
+ private bool $enabled = false;
- public function __construct(ICloudFederationProviderManager $cloudFederationProviderManager, ICloudIdManager $cloudIdManager) {
+ public function __construct(
+ ICloudFederationProviderManager $cloudFederationProviderManager,
+ private ICloudIdManager $cloudIdManager,
+ ) {
try {
$fileSharingProvider = $cloudFederationProviderManager->getCloudFederationProvider('file');
$supportedShareTypes = $fileSharingProvider->getSupportedShareTypes();
@@ -50,10 +30,9 @@ class RemoteGroupPlugin implements ISearchPlugin {
} catch (\Exception $e) {
// do nothing, just don't enable federated group shares
}
- $this->cloudIdManager = $cloudIdManager;
}
- public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
$result = ['wide' => [], 'exact' => []];
$resultType = new SearchResultType('remote_groups');
@@ -83,7 +62,7 @@ class RemoteGroupPlugin implements ISearchPlugin {
* @return array [user, remoteURL]
* @throws \InvalidArgumentException
*/
- public function splitGroupRemote($address) {
+ public function splitGroupRemote($address): array {
try {
$cloudId = $this->cloudIdManager->resolveCloudId($address);
return [$cloudId->getUser(), $cloudId->getRemote()];
diff --git a/lib/private/Collaboration/Collaborators/RemotePlugin.php b/lib/private/Collaboration/Collaborators/RemotePlugin.php
index 7d7a013a38c..037c6f6cbea 100644
--- a/lib/private/Collaboration/Collaborators/RemotePlugin.php
+++ b/lib/private/Collaboration/Collaborators/RemotePlugin.php
@@ -1,28 +1,8 @@
<?php
+
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -37,32 +17,22 @@ use OCP\IUserSession;
use OCP\Share\IShare;
class RemotePlugin implements ISearchPlugin {
- protected $shareeEnumeration;
+ protected bool $shareeEnumeration;
- /** @var IManager */
- private $contactsManager;
- /** @var ICloudIdManager */
- private $cloudIdManager;
- /** @var IConfig */
- private $config;
- /** @var IUserManager */
- private $userManager;
- /** @var string */
- private $userId = '';
+ private string $userId;
- public function __construct(IManager $contactsManager, ICloudIdManager $cloudIdManager, IConfig $config, IUserManager $userManager, IUserSession $userSession) {
- $this->contactsManager = $contactsManager;
- $this->cloudIdManager = $cloudIdManager;
- $this->config = $config;
- $this->userManager = $userManager;
- $user = $userSession->getUser();
- if ($user !== null) {
- $this->userId = $user->getUID();
- }
+ public function __construct(
+ private IManager $contactsManager,
+ private ICloudIdManager $cloudIdManager,
+ private IConfig $config,
+ private IUserManager $userManager,
+ IUserSession $userSession,
+ ) {
+ $this->userId = $userSession->getUser()?->getUID() ?? '';
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
}
- public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
$result = ['wide' => [], 'exact' => []];
$resultType = new SearchResultType('remotes');
@@ -185,10 +155,10 @@ class RemotePlugin implements ISearchPlugin {
* @return array [user, remoteURL]
* @throws \InvalidArgumentException
*/
- public function splitUserRemote($address) {
+ public function splitUserRemote(string $address): array {
try {
$cloudId = $this->cloudIdManager->resolveCloudId($address);
- return [$cloudId->getUser(), $cloudId->getRemote()];
+ return [$cloudId->getUser(), $this->cloudIdManager->removeProtocolFromUrl($cloudId->getRemote(), true)];
} catch (\InvalidArgumentException $e) {
throw new \InvalidArgumentException('Invalid Federated Cloud ID', 0, $e);
}
diff --git a/lib/private/Collaboration/Collaborators/Search.php b/lib/private/Collaboration/Collaborators/Search.php
index b0ee09356af..ea39f885fc6 100644
--- a/lib/private/Collaboration/Collaborators/Search.php
+++ b/lib/private/Collaboration/Collaborators/Search.php
@@ -1,29 +1,8 @@
<?php
+
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author onehappycat <one.happy.cat@gmx.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -32,35 +11,31 @@ use OCP\Collaboration\Collaborators\ISearchPlugin;
use OCP\Collaboration\Collaborators\ISearchResult;
use OCP\Collaboration\Collaborators\SearchResultType;
use OCP\IContainer;
-use OCP\Share;
+use OCP\Share\IShare;
class Search implements ISearch {
- /** @var IContainer */
- private $c;
-
- protected $pluginList = [];
+ protected array $pluginList = [];
- public function __construct(IContainer $c) {
- $this->c = $c;
+ public function __construct(
+ private IContainer $container,
+ ) {
}
/**
* @param string $search
- * @param array $shareTypes
* @param bool $lookup
* @param int|null $limit
* @param int|null $offset
- * @return array
* @throws \OCP\AppFramework\QueryException
*/
- public function search($search, array $shareTypes, $lookup, $limit, $offset) {
+ public function search($search, array $shareTypes, $lookup, $limit, $offset): array {
$hasMoreResults = false;
// Trim leading and trailing whitespace characters, e.g. when query is copy-pasted
$search = trim($search);
/** @var ISearchResult $searchResult */
- $searchResult = $this->c->resolve(SearchResult::class);
+ $searchResult = $this->container->resolve(SearchResult::class);
foreach ($shareTypes as $type) {
if (!isset($this->pluginList[$type])) {
@@ -68,14 +43,14 @@ class Search implements ISearch {
}
foreach ($this->pluginList[$type] as $plugin) {
/** @var ISearchPlugin $searchPlugin */
- $searchPlugin = $this->c->resolve($plugin);
+ $searchPlugin = $this->container->resolve($plugin);
$hasMoreResults = $searchPlugin->search($search, $limit, $offset, $searchResult) || $hasMoreResults;
}
}
// Get from lookup server, not a separate share type
if ($lookup) {
- $searchPlugin = $this->c->resolve(LookupPlugin::class);
+ $searchPlugin = $this->container->resolve(LookupPlugin::class);
$hasMoreResults = $searchPlugin->search($search, $limit, $offset, $searchResult) || $hasMoreResults;
}
@@ -97,7 +72,7 @@ class Search implements ISearch {
// if we have an exact local user match with an email-a-like query,
// there is no need to show the remote and email matches.
$userType = new SearchResultType('users');
- if (strpos($search, '@') !== false && $searchResult->hasExactIdMatch($userType)) {
+ if (str_contains($search, '@') && $searchResult->hasExactIdMatch($userType)) {
$searchResult->unsetResult($remoteType);
$searchResult->unsetResult($emailType);
}
@@ -105,8 +80,8 @@ class Search implements ISearch {
return [$searchResult->asArray(), $hasMoreResults];
}
- public function registerPlugin(array $pluginInfo) {
- $shareType = constant(Share::class . '::' . $pluginInfo['shareType']);
+ public function registerPlugin(array $pluginInfo): void {
+ $shareType = constant(IShare::class . '::' . substr($pluginInfo['shareType'], strlen('SHARE_')));
if ($shareType === null) {
throw new \InvalidArgumentException('Provided ShareType is invalid');
}
diff --git a/lib/private/Collaboration/Collaborators/SearchResult.php b/lib/private/Collaboration/Collaborators/SearchResult.php
index 76d78c9c231..c9c2f032f36 100644
--- a/lib/private/Collaboration/Collaborators/SearchResult.php
+++ b/lib/private/Collaboration/Collaborators/SearchResult.php
@@ -1,26 +1,8 @@
<?php
+
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -28,13 +10,13 @@ use OCP\Collaboration\Collaborators\ISearchResult;
use OCP\Collaboration\Collaborators\SearchResultType;
class SearchResult implements ISearchResult {
- protected $result = [
+ protected array $result = [
'exact' => [],
];
- protected $exactIdMatches = [];
+ protected array $exactIdMatches = [];
- public function addResultSet(SearchResultType $type, array $matches, array $exactMatches = null) {
+ public function addResultSet(SearchResultType $type, array $matches, ?array $exactMatches = null): void {
$type = $type->getLabel();
if (!isset($this->result[$type])) {
$this->result[$type] = [];
@@ -47,15 +29,15 @@ class SearchResult implements ISearchResult {
}
}
- public function markExactIdMatch(SearchResultType $type) {
+ public function markExactIdMatch(SearchResultType $type): void {
$this->exactIdMatches[$type->getLabel()] = 1;
}
- public function hasExactIdMatch(SearchResultType $type) {
+ public function hasExactIdMatch(SearchResultType $type): bool {
return isset($this->exactIdMatches[$type->getLabel()]);
}
- public function hasResult(SearchResultType $type, $collaboratorId) {
+ public function hasResult(SearchResultType $type, $collaboratorId): bool {
$type = $type->getLabel();
if (!isset($this->result[$type])) {
return false;
@@ -73,11 +55,11 @@ class SearchResult implements ISearchResult {
return false;
}
- public function asArray() {
+ public function asArray(): array {
return $this->result;
}
- public function unsetResult(SearchResultType $type) {
+ public function unsetResult(SearchResultType $type): void {
$type = $type->getLabel();
$this->result[$type] = [];
if (isset($this->result['exact'][$type])) {
diff --git a/lib/private/Collaboration/Collaborators/UserPlugin.php b/lib/private/Collaboration/Collaborators/UserPlugin.php
index af4d8b2ccca..671181aea35 100644
--- a/lib/private/Collaboration/Collaborators/UserPlugin.php
+++ b/lib/private/Collaboration/Collaborators/UserPlugin.php
@@ -1,33 +1,8 @@
<?php
+
/**
- * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Citharel <nextcloud@tcit.fr>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Collaboration\Collaborators;
@@ -44,70 +19,62 @@ use OCP\Share\IShare;
use OCP\UserStatus\IManager as IUserStatusManager;
class UserPlugin implements ISearchPlugin {
- /* @var bool */
- protected $shareWithGroupOnly;
- /* @var bool */
- protected $shareeEnumeration;
- /* @var bool */
- protected $shareeEnumerationInGroupOnly;
- /* @var bool */
- protected $shareeEnumerationPhone;
- /* @var bool */
- protected $shareeEnumerationFullMatch;
- /* @var bool */
- protected $shareeEnumerationFullMatchUserId;
- /* @var bool */
- protected $shareeEnumerationFullMatchIgnoreSecondDisplayName;
-
- /** @var IConfig */
- private $config;
- /** @var IGroupManager */
- private $groupManager;
- /** @var IUserSession */
- private $userSession;
- /** @var IUserManager */
- private $userManager;
- /** @var KnownUserService */
- private $knownUserService;
- /** @var IUserStatusManager */
- private $userStatusManager;
-
- public function __construct(IConfig $config,
- IUserManager $userManager,
- IGroupManager $groupManager,
- IUserSession $userSession,
- KnownUserService $knownUserService,
- IUserStatusManager $userStatusManager) {
- $this->config = $config;
-
- $this->groupManager = $groupManager;
- $this->userSession = $userSession;
- $this->userManager = $userManager;
- $this->knownUserService = $knownUserService;
- $this->userStatusManager = $userStatusManager;
+ protected bool $shareWithGroupOnly;
+
+ protected bool $shareeEnumeration;
+
+ protected bool $shareeEnumerationInGroupOnly;
+
+ protected bool $shareeEnumerationPhone;
+
+ protected bool $shareeEnumerationFullMatch;
+
+ protected bool $shareeEnumerationFullMatchUserId;
+
+ protected bool $shareeEnumerationFullMatchEmail;
+ protected bool $shareeEnumerationFullMatchIgnoreSecondDisplayName;
+
+ public function __construct(
+ private IConfig $config,
+ private IUserManager $userManager,
+ private IGroupManager $groupManager,
+ 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';
$this->shareeEnumerationInGroupOnly = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
$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->shareeEnumerationFullMatchUserId = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_userid', 'yes') === 'yes';
- $this->shareeEnumerationFullMatchIgnoreSecondDisplayName = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_display_name', 'no') === '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) {
+ public function search($search, $limit, $offset, ISearchResult $searchResult): bool {
$result = ['wide' => [], 'exact' => []];
$users = [];
$hasMoreResults = false;
$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) {
$usersInGroup = $this->groupManager->displayNamesInGroup($userGroupId, $search, $limit, $offset);
foreach ($usersInGroup as $userId => $displayName) {
- $userId = (string) $userId;
+ $userId = (string)$userId;
$user = $this->userManager->get($userId);
if (!$user->isEnabled()) {
// Ignore disabled users
@@ -164,7 +131,7 @@ class UserPlugin implements ISearchPlugin {
foreach ($users as $uid => $user) {
$userDisplayName = $user->getDisplayName();
$userEmail = $user->getSystemEMailAddress();
- $uid = (string) $uid;
+ $uid = (string)$uid;
$status = [];
if (array_key_exists($uid, $userStatuses)) {
@@ -181,11 +148,11 @@ class UserPlugin implements ISearchPlugin {
if (
- $this->shareeEnumerationFullMatch &&
- $lowerSearch !== '' && (strtolower($uid) === $lowerSearch ||
- strtolower($userDisplayName) === $lowerSearch ||
- ($this->shareeEnumerationFullMatchIgnoreSecondDisplayName && trim(strtolower(preg_replace('/ \(.*\)$/', '', $userDisplayName))) === $lowerSearch) ||
- strtolower($userEmail ?? '') === $lowerSearch)
+ $this->shareeEnumerationFullMatch
+ && $lowerSearch !== '' && (strtolower($uid) === $lowerSearch
+ || strtolower($userDisplayName) === $lowerSearch
+ || ($this->shareeEnumerationFullMatchIgnoreSecondDisplayName && trim(strtolower(preg_replace('/ \(.*\)$/', '', $userDisplayName))) === $lowerSearch)
+ || ($this->shareeEnumerationFullMatchEmail && strtolower($userEmail ?? '') === $lowerSearch))
) {
if (strtolower($uid) === $lowerSearch) {
$foundUserById = true;
@@ -203,8 +170,8 @@ class UserPlugin implements ISearchPlugin {
];
} else {
$addToWideResults = false;
- if ($this->shareeEnumeration &&
- !($this->shareeEnumerationInGroupOnly || $this->shareeEnumerationPhone)) {
+ if ($this->shareeEnumeration
+ && !($this->shareeEnumerationInGroupOnly || $this->shareeEnumerationPhone)) {
$addToWideResults = true;
}
@@ -279,8 +246,6 @@ class UserPlugin implements ISearchPlugin {
}
}
-
-
$type = new SearchResultType('users');
$searchResult->addResultSet($type, $result['wide'], $result['exact']);
if (count($result['exact'])) {
@@ -290,7 +255,7 @@ class UserPlugin implements ISearchPlugin {
return $hasMoreResults;
}
- public function takeOutCurrentUser(array &$users) {
+ public function takeOutCurrentUser(array &$users): void {
$currentUser = $this->userSession->getUser();
if (!is_null($currentUser)) {
if (isset($users[$currentUser->getUID()])) {