aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoas Schilling <coding@schilljs.com>2021-03-09 21:48:48 +0100
committerJoas Schilling <coding@schilljs.com>2021-03-11 08:40:03 +0100
commitc7560ab3a934ccf0c6271dd223e2907bd7d57949 (patch)
tree98d55461c19ec167cb5a5a70330043f8d95a838e
parent52d43bf3cc5d9743bb2949ad2fdd6b419b21f7b3 (diff)
downloadnextcloud-server-c7560ab3a934ccf0c6271dd223e2907bd7d57949.tar.gz
nextcloud-server-c7560ab3a934ccf0c6271dd223e2907bd7d57949.zip
Restrict autocompletion also based on the phonebook known users
Signed-off-by: Joas Schilling <coding@schilljs.com>
-rw-r--r--apps/dav/appinfo/v1/caldav.php2
-rw-r--r--apps/dav/appinfo/v1/carddav.php2
-rw-r--r--apps/dav/lib/CardDAV/SystemAddressbook.php5
-rw-r--r--apps/dav/lib/Command/CreateCalendar.php2
-rw-r--r--apps/dav/lib/Connector/Sabre/Principal.php88
-rw-r--r--apps/dav/lib/RootCollection.php2
-rw-r--r--apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php2
-rw-r--r--apps/dav/tests/unit/CardDAV/CardDavBackendTest.php2
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php8
-rw-r--r--apps/files_versions/lib/AppInfo/Application.php2
-rw-r--r--lib/private/Collaboration/Collaborators/MailPlugin.php33
-rw-r--r--lib/private/Collaboration/Collaborators/UserPlugin.php29
-rw-r--r--lib/private/Contacts/ContactsMenu/ContactsStore.php106
-rw-r--r--lib/private/Share20/Manager.php5
-rw-r--r--lib/public/Share/IManager.php8
-rw-r--r--tests/lib/Collaboration/Collaborators/MailPluginTest.php14
-rw-r--r--tests/lib/Collaboration/Collaborators/UserPluginTest.php7
-rw-r--r--tests/lib/Contacts/ContactsMenu/ContactsStoreTest.php379
18 files changed, 556 insertions, 140 deletions
diff --git a/apps/dav/appinfo/v1/caldav.php b/apps/dav/appinfo/v1/caldav.php
index e04653ddea1..236d81f66f8 100644
--- a/apps/dav/appinfo/v1/caldav.php
+++ b/apps/dav/appinfo/v1/caldav.php
@@ -27,6 +27,7 @@
*/
// Backends
+use OC\KnownUser\KnownUserService;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\Connector\LegacyDAVACL;
use OCA\DAV\CalDAV\CalendarRoot;
@@ -50,6 +51,7 @@ $principalBackend = new Principal(
\OC::$server->getUserSession(),
\OC::$server->getAppManager(),
\OC::$server->query(\OCA\DAV\CalDAV\Proxy\ProxyMapper::class),
+ \OC::$server->get(KnownUserService::class),
\OC::$server->getConfig(),
'principals/'
);
diff --git a/apps/dav/appinfo/v1/carddav.php b/apps/dav/appinfo/v1/carddav.php
index dbab1ae9681..bb766bbaeca 100644
--- a/apps/dav/appinfo/v1/carddav.php
+++ b/apps/dav/appinfo/v1/carddav.php
@@ -27,6 +27,7 @@
*/
// Backends
+use OC\KnownUser\KnownUserService;
use OCA\DAV\AppInfo\PluginManager;
use OCA\DAV\CardDAV\AddressBookRoot;
use OCA\DAV\CardDAV\CardDavBackend;
@@ -53,6 +54,7 @@ $principalBackend = new Principal(
\OC::$server->getUserSession(),
\OC::$server->getAppManager(),
\OC::$server->query(\OCA\DAV\CalDAV\Proxy\ProxyMapper::class),
+ \OC::$server->get(KnownUserService::class),
\OC::$server->getConfig(),
'principals/'
);
diff --git a/apps/dav/lib/CardDAV/SystemAddressbook.php b/apps/dav/lib/CardDAV/SystemAddressbook.php
index c7190c81319..5b952152711 100644
--- a/apps/dav/lib/CardDAV/SystemAddressbook.php
+++ b/apps/dav/lib/CardDAV/SystemAddressbook.php
@@ -43,8 +43,9 @@ class SystemAddressbook extends AddressBook {
public function getChildren() {
$shareEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
- $restrictShareEnumeration = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
- if (!$shareEnumeration || ($shareEnumeration && $restrictShareEnumeration)) {
+ $shareEnumerationGroup = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
+ $shareEnumerationPhone = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
+ if (!$shareEnumeration || $shareEnumerationGroup || $shareEnumerationPhone) {
return [];
}
diff --git a/apps/dav/lib/Command/CreateCalendar.php b/apps/dav/lib/Command/CreateCalendar.php
index 58c6a8c63fb..1d543c71bc2 100644
--- a/apps/dav/lib/Command/CreateCalendar.php
+++ b/apps/dav/lib/Command/CreateCalendar.php
@@ -27,6 +27,7 @@
namespace OCA\DAV\Command;
+use OC\KnownUser\KnownUserService;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\Proxy\ProxyMapper;
use OCA\DAV\Connector\Sabre\Principal;
@@ -86,6 +87,7 @@ class CreateCalendar extends Command {
\OC::$server->getUserSession(),
\OC::$server->getAppManager(),
\OC::$server->query(ProxyMapper::class),
+ \OC::$server->get(KnownUserService::class),
\OC::$server->getConfig()
);
$random = \OC::$server->getSecureRandom();
diff --git a/apps/dav/lib/Connector/Sabre/Principal.php b/apps/dav/lib/Connector/Sabre/Principal.php
index c1b1dc1b2d1..94302a12b49 100644
--- a/apps/dav/lib/Connector/Sabre/Principal.php
+++ b/apps/dav/lib/Connector/Sabre/Principal.php
@@ -36,6 +36,7 @@
namespace OCA\DAV\Connector\Sabre;
+use OC\KnownUser\KnownUserService;
use OCA\Circles\Exceptions\CircleDoesNotExistException;
use OCA\DAV\CalDAV\Proxy\ProxyMapper;
use OCA\DAV\Traits\PrincipalProxyTrait;
@@ -82,27 +83,19 @@ class Principal implements BackendInterface {
/** @var ProxyMapper */
private $proxyMapper;
+ /** @var KnownUserService */
+ private $knownUserService;
+
/** @var IConfig */
private $config;
- /**
- * Principal constructor.
- *
- * @param IUserManager $userManager
- * @param IGroupManager $groupManager
- * @param IShareManager $shareManager
- * @param IUserSession $userSession
- * @param IAppManager $appManager
- * @param ProxyMapper $proxyMapper
- * @param IConfig $config
- * @param string $principalPrefix
- */
public function __construct(IUserManager $userManager,
IGroupManager $groupManager,
IShareManager $shareManager,
IUserSession $userSession,
IAppManager $appManager,
ProxyMapper $proxyMapper,
+ KnownUserService $knownUserService,
IConfig $config,
string $principalPrefix = 'principals/users/') {
$this->userManager = $userManager;
@@ -113,6 +106,7 @@ class Principal implements BackendInterface {
$this->principalPrefix = trim($principalPrefix, '/');
$this->hasGroups = $this->hasCircles = ($principalPrefix === 'principals/users/');
$this->proxyMapper = $proxyMapper;
+ $this->knownUserService = $knownUserService;
$this->config = $config;
}
@@ -267,24 +261,24 @@ class Principal implements BackendInterface {
}
$allowEnumeration = $this->shareManager->allowEnumeration();
- $limitEnumeration = $this->shareManager->limitEnumerationToGroups();
+ $limitEnumerationGroup = $this->shareManager->limitEnumerationToGroups();
+ $limitEnumerationPhone = $this->shareManager->limitEnumerationToPhone();
// If sharing is restricted to group members only,
// return only members that have groups in common
$restrictGroups = false;
+ $currentUser = $this->userSession->getUser();
if ($this->shareManager->shareWithGroupMembersOnly()) {
- $user = $this->userSession->getUser();
- if (!$user) {
+ if (!$currentUser instanceof IUser) {
return [];
}
- $restrictGroups = $this->groupManager->getUserGroupIds($user);
+ $restrictGroups = $this->groupManager->getUserGroupIds($currentUser);
}
$currentUserGroups = [];
- if ($limitEnumeration) {
- $currentUser = $this->userSession->getUser();
- if ($currentUser) {
+ if ($limitEnumerationGroup) {
+ if ($currentUser instanceof IUser) {
$currentUserGroups = $this->groupManager->getUserGroupIds($currentUser);
}
}
@@ -302,14 +296,28 @@ class Principal implements BackendInterface {
$users = \array_filter($users, static function (IUser $user) use ($value) {
return $user->getEMailAddress() === $value;
});
- }
+ } else {
+ $users = \array_filter($users, function (IUser $user) use ($currentUser, $value, $limitEnumerationPhone, $limitEnumerationGroup, $currentUserGroups) {
+ if ($user->getEMailAddress() === $value) {
+ return true;
+ }
- if ($limitEnumeration) {
- $users = \array_filter($users, function (IUser $user) use ($currentUserGroups, $value) {
- return !empty(array_intersect(
- $this->groupManager->getUserGroupIds($user),
- $currentUserGroups
- )) || $user->getEMailAddress() === $value;
+ if ($limitEnumerationPhone
+ && $currentUser instanceof IUser
+ && $this->knownUserService->isKnownToUser($currentUser->getUID(), $user->getUID())) {
+ // Synced phonebook match
+ return true;
+ }
+
+ if (!$limitEnumerationGroup) {
+ // No limitation on enumeration, all allowed
+ return true;
+ }
+
+ return !empty($currentUserGroups) && !empty(array_intersect(
+ $this->groupManager->getUserGroupIds($user),
+ $currentUserGroups
+ ));
});
}
@@ -334,14 +342,28 @@ class Principal implements BackendInterface {
$users = \array_filter($users, static function (IUser $user) use ($value) {
return $user->getDisplayName() === $value;
});
- }
+ } else {
+ $users = \array_filter($users, function (IUser $user) use ($currentUser, $value, $limitEnumerationPhone, $limitEnumerationGroup, $currentUserGroups) {
+ if ($user->getDisplayName() === $value) {
+ return true;
+ }
+
+ if ($limitEnumerationPhone
+ && $currentUser instanceof IUser
+ && $this->knownUserService->isKnownToUser($currentUser->getUID(), $user->getUID())) {
+ // Synced phonebook match
+ return true;
+ }
+
+ if (!$limitEnumerationGroup) {
+ // No limitation on enumeration, all allowed
+ return true;
+ }
- if ($limitEnumeration) {
- $users = \array_filter($users, function (IUser $user) use ($currentUserGroups, $value) {
- return !empty(array_intersect(
- $this->groupManager->getUserGroupIds($user),
- $currentUserGroups
- )) || $user->getDisplayName() === $value;
+ return !empty($currentUserGroups) && !empty(array_intersect(
+ $this->groupManager->getUserGroupIds($user),
+ $currentUserGroups
+ ));
});
}
diff --git a/apps/dav/lib/RootCollection.php b/apps/dav/lib/RootCollection.php
index 18874ecf748..16a209a98f0 100644
--- a/apps/dav/lib/RootCollection.php
+++ b/apps/dav/lib/RootCollection.php
@@ -28,6 +28,7 @@
namespace OCA\DAV;
+use OC\KnownUser\KnownUserService;
use OCA\DAV\AppInfo\PluginManager;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\CalendarRoot;
@@ -70,6 +71,7 @@ class RootCollection extends SimpleCollection {
\OC::$server->getUserSession(),
\OC::$server->getAppManager(),
$proxyMapper,
+ \OC::$server->get(KnownUserService::class),
\OC::$server->getConfig()
);
$groupPrincipalBackend = new GroupPrincipalBackend($groupManager, $userSession, $shareManager, $config);
diff --git a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php
index 85efd0fd369..51ba8c1867a 100644
--- a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php
+++ b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php
@@ -27,6 +27,7 @@
namespace OCA\DAV\Tests\unit\CalDAV;
+use OC\KnownUser\KnownUserService;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\Proxy\ProxyMapper;
use OCA\DAV\Connector\Sabre\Principal;
@@ -92,6 +93,7 @@ abstract class AbstractCalDavBackend extends TestCase {
$this->createMock(IUserSession::class),
$this->createMock(IAppManager::class),
$this->createMock(ProxyMapper::class),
+ $this->createMock(KnownUserService::class),
$this->createMock(IConfig::class),
])
->setMethods(['getPrincipalByPath', 'getGroupMembership'])
diff --git a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
index a8c7a781724..60f46ce8fac 100644
--- a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
+++ b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
@@ -33,6 +33,7 @@
namespace OCA\DAV\Tests\unit\CardDAV;
+use OC\KnownUser\KnownUserService;
use OCA\DAV\CalDAV\Proxy\ProxyMapper;
use OCA\DAV\CardDAV\AddressBook;
use OCA\DAV\CardDAV\CardDavBackend;
@@ -139,6 +140,7 @@ class CardDavBackendTest extends TestCase {
$this->createMock(IUserSession::class),
$this->createMock(IAppManager::class),
$this->createMock(ProxyMapper::class),
+ $this->createMock(KnownUserService::class),
$this->createMock(IConfig::class),
])
->setMethods(['getPrincipalByPath', 'getGroupMembership'])
diff --git a/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php b/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php
index 117707eaf2a..33c1ec1b587 100644
--- a/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php
@@ -30,6 +30,7 @@
namespace OCA\DAV\Tests\unit\Connector\Sabre;
+use OC\KnownUser\KnownUserService;
use OC\User\User;
use OCA\DAV\CalDAV\Proxy\Proxy;
use OCA\DAV\CalDAV\Proxy\ProxyMapper;
@@ -41,6 +42,7 @@ use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Share\IManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\PropPatch;
use Test\TestCase;
@@ -67,6 +69,8 @@ class PrincipalTest extends TestCase {
/** @var ProxyMapper | \PHPUnit\Framework\MockObject\MockObject */
private $proxyMapper;
+ /** @var KnownUserService|MockObject */
+ private $knownUserService;
/** @var IConfig | \PHPUnit\Framework\MockObject\MockObject */
private $config;
@@ -77,6 +81,7 @@ class PrincipalTest extends TestCase {
$this->userSession = $this->createMock(IUserSession::class);
$this->appManager = $this->createMock(IAppManager::class);
$this->proxyMapper = $this->createMock(ProxyMapper::class);
+ $this->knownUserService = $this->createMock(KnownUserService::class);
$this->config = $this->createMock(IConfig::class);
$this->connector = new \OCA\DAV\Connector\Sabre\Principal(
@@ -86,6 +91,7 @@ class PrincipalTest extends TestCase {
$this->userSession,
$this->appManager,
$this->proxyMapper,
+ $this->knownUserService,
$this->config
);
parent::setUp();
@@ -442,7 +448,7 @@ class PrincipalTest extends TestCase {
if ($groupsOnly) {
$user = $this->createMock(IUser::class);
- $this->userSession->expects($this->once())
+ $this->userSession->expects($this->atLeastOnce())
->method('getUser')
->willReturn($user);
diff --git a/apps/files_versions/lib/AppInfo/Application.php b/apps/files_versions/lib/AppInfo/Application.php
index afbd42ffc3f..e09ad7e90ae 100644
--- a/apps/files_versions/lib/AppInfo/Application.php
+++ b/apps/files_versions/lib/AppInfo/Application.php
@@ -27,6 +27,7 @@
namespace OCA\Files_Versions\AppInfo;
+use OC\KnownUser\KnownUserService;
use OCA\DAV\CalDAV\Proxy\ProxyMapper;
use OCA\DAV\Connector\Sabre\Principal;
use OCA\Files\Event\LoadAdditionalScriptsEvent;
@@ -72,6 +73,7 @@ class Application extends App implements IBootstrap {
$server->getUserSession(),
$server->getAppManager(),
$server->get(ProxyMapper::class),
+ $server->get(KnownUserService::class),
$server->getConfig()
);
});
diff --git a/lib/private/Collaboration/Collaborators/MailPlugin.php b/lib/private/Collaboration/Collaborators/MailPlugin.php
index 7bdd29afc4e..7da8cede6aa 100644
--- a/lib/private/Collaboration/Collaborators/MailPlugin.php
+++ b/lib/private/Collaboration/Collaborators/MailPlugin.php
@@ -27,6 +27,7 @@
namespace OC\Collaboration\Collaborators;
+use OC\KnownUser\KnownUserService;
use OCP\Collaboration\Collaborators\ISearchPlugin;
use OCP\Collaboration\Collaborators\ISearchResult;
use OCP\Collaboration\Collaborators\SearchResultType;
@@ -40,8 +41,14 @@ use OCP\IUserSession;
use OCP\Share\IShare;
class MailPlugin implements ISearchPlugin {
- protected $shareeEnumeration;
+ /* @var bool */
protected $shareWithGroupOnly;
+ /* @var bool */
+ protected $shareeEnumeration;
+ /* @var bool */
+ protected $shareeEnumerationInGroupOnly;
+ /* @var bool */
+ protected $shareeEnumerationPhone;
/** @var IManager */
private $contactsManager;
@@ -52,20 +59,28 @@ class MailPlugin implements ISearchPlugin {
/** @var IGroupManager */
private $groupManager;
-
+ /** @var KnownUserService */
+ private $knownUserService;
/** @var IUserSession */
private $userSession;
- public function __construct(IManager $contactsManager, ICloudIdManager $cloudIdManager, IConfig $config, IGroupManager $groupManager, IUserSession $userSession) {
+ public function __construct(IManager $contactsManager,
+ ICloudIdManager $cloudIdManager,
+ IConfig $config,
+ IGroupManager $groupManager,
+ KnownUserService $knownUserService,
+ IUserSession $userSession) {
$this->contactsManager = $contactsManager;
$this->cloudIdManager = $cloudIdManager;
$this->config = $config;
$this->groupManager = $groupManager;
+ $this->knownUserService = $knownUserService;
$this->userSession = $userSession;
$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';
}
/**
@@ -77,6 +92,8 @@ class MailPlugin implements ISearchPlugin {
* @since 13.0.0
*/
public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ $currentUserId = $this->userSession->getUser()->getUID();
+
$result = $userResults = ['wide' => [], 'exact' => []];
$userType = new SearchResultType('users');
$emailType = new SearchResultType('emails');
@@ -152,8 +169,12 @@ class MailPlugin implements ISearchPlugin {
continue;
}
- $addToWide = !$this->shareeEnumerationInGroupOnly;
- if ($this->shareeEnumerationInGroupOnly) {
+ $addToWide = !($this->shareeEnumerationInGroupOnly || $this->shareeEnumerationPhone);
+ if (!$addToWide && $this->shareeEnumerationPhone && $this->knownUserService->isKnownToUser($currentUserId, $contact['UID'])) {
+ $addToWide = true;
+ }
+
+ if (!$addToWide && $this->shareeEnumerationInGroupOnly) {
$addToWide = false;
$userGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser());
foreach ($userGroups as $userGroup) {
@@ -181,7 +202,7 @@ class MailPlugin implements ISearchPlugin {
}
if ($exactEmailMatch
- || isset($contact['FN']) && strtolower($contact['FN']) === $lowerSearch) {
+ || (isset($contact['FN']) && strtolower($contact['FN']) === $lowerSearch)) {
if ($exactEmailMatch) {
$searchResult->markExactIdMatch($emailType);
}
diff --git a/lib/private/Collaboration/Collaborators/UserPlugin.php b/lib/private/Collaboration/Collaborators/UserPlugin.php
index d832a42000c..5114ccd8eb5 100644
--- a/lib/private/Collaboration/Collaborators/UserPlugin.php
+++ b/lib/private/Collaboration/Collaborators/UserPlugin.php
@@ -32,6 +32,7 @@
namespace OC\Collaboration\Collaborators;
+use OC\KnownUser\KnownUserService;
use OCP\Collaboration\Collaborators\ISearchPlugin;
use OCP\Collaboration\Collaborators\ISearchResult;
use OCP\Collaboration\Collaborators\SearchResultType;
@@ -46,8 +47,12 @@ 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 IConfig */
private $config;
@@ -57,33 +62,29 @@ class UserPlugin implements ISearchPlugin {
private $userSession;
/** @var IUserManager */
private $userManager;
+ /** @var KnownUserService */
+ private $knownUserService;
/** @var IUserStatusManager */
private $userStatusManager;
- /**
- * UserPlugin constructor.
- *
- * @param IConfig $config
- * @param IUserManager $userManager
- * @param IGroupManager $groupManager
- * @param IUserSession $userSession
- * @param IUserStatusManager $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;
$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';
}
public function search($search, $limit, $offset, ISearchResult $searchResult) {
@@ -91,6 +92,7 @@ class UserPlugin implements ISearchPlugin {
$users = [];
$hasMoreResults = false;
+ $currentUserId = $this->userSession->getUser()->getUID();
$currentUserGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser());
if ($this->shareWithGroupOnly) {
// Search in all the groups this user is part of
@@ -168,11 +170,16 @@ class UserPlugin implements ISearchPlugin {
];
} else {
$addToWideResults = false;
- if ($this->shareeEnumeration && !$this->shareeEnumerationInGroupOnly) {
+ if ($this->shareeEnumeration &&
+ !($this->shareeEnumerationInGroupOnly || $this->shareeEnumerationPhone)) {
+ $addToWideResults = true;
+ }
+
+ if ($this->shareeEnumerationPhone && $this->knownUserService->isKnownToUser($currentUserId, $user->getUID())) {
$addToWideResults = true;
}
- if ($this->shareeEnumerationInGroupOnly) {
+ if (!$addToWideResults && $this->shareeEnumerationInGroupOnly) {
$commonGroups = array_intersect($currentUserGroups, $this->groupManager->getUserGroupIds($user));
if (!empty($commonGroups)) {
$addToWideResults = true;
diff --git a/lib/private/Contacts/ContactsMenu/ContactsStore.php b/lib/private/Contacts/ContactsMenu/ContactsStore.php
index e2bd7edc63d..852765506c0 100644
--- a/lib/private/Contacts/ContactsMenu/ContactsStore.php
+++ b/lib/private/Contacts/ContactsMenu/ContactsStore.php
@@ -31,6 +31,7 @@
namespace OC\Contacts\ContactsMenu;
+use OC\KnownUser\KnownUserService;
use OCP\Contacts\ContactsMenu\IContactsStore;
use OCP\Contacts\ContactsMenu\IEntry;
use OCP\Contacts\IManager;
@@ -53,20 +54,19 @@ class ContactsStore implements IContactsStore {
/** @var IGroupManager */
private $groupManager;
- /**
- * @param IManager $contactsManager
- * @param IConfig $config
- * @param IUserManager $userManager
- * @param IGroupManager $groupManager
- */
+ /** @var KnownUserService */
+ private $knownUserService;
+
public function __construct(IManager $contactsManager,
IConfig $config,
IUserManager $userManager,
- IGroupManager $groupManager) {
+ IGroupManager $groupManager,
+ KnownUserService $knownUserService) {
$this->contactsManager = $contactsManager;
$this->config = $config;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
+ $this->knownUserService = $knownUserService;
}
/**
@@ -103,7 +103,7 @@ class ContactsStore implements IContactsStore {
}
/**
- * Filters the contacts. Applies 3 filters:
+ * Filters the contacts. Applied filters:
* 1. filter the current user
* 2. if the `shareapi_allow_share_dialog_user_enumeration` config option is
* enabled it will filter all local users
@@ -122,20 +122,21 @@ class ContactsStore implements IContactsStore {
array $entries,
$filter) {
$disallowEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') !== 'yes';
- $restrictEnumeration = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
+ $restrictEnumerationGroup = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
+ $restrictEnumerationPhone = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
$excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes';
// whether to filter out local users
$skipLocal = false;
- // whether to filter out all users which doesn't have the same group as the current user
- $ownGroupsOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes' || $restrictEnumeration;
+ // whether to filter out all users which don't have a common group as the current user
+ $ownGroupsOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
$selfGroups = $this->groupManager->getUserGroupIds($self);
if ($excludedGroups) {
$excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
$decodedExcludeGroups = json_decode($excludedGroups, true);
- $excludeGroupsList = ($decodedExcludeGroups !== null) ? $decodedExcludeGroups : [];
+ $excludeGroupsList = $decodedExcludeGroups ?? [];
if (count(array_intersect($excludeGroupsList, $selfGroups)) !== 0) {
// a group of the current user is excluded -> filter all local users
@@ -145,47 +146,76 @@ class ContactsStore implements IContactsStore {
$selfUID = $self->getUID();
- return array_values(array_filter($entries, function (IEntry $entry) use ($self, $skipLocal, $ownGroupsOnly, $selfGroups, $selfUID, $disallowEnumeration, $filter) {
- if ($skipLocal && $entry->getProperty('isLocalSystemBook') === true) {
+ return array_values(array_filter($entries, function (IEntry $entry) use ($skipLocal, $ownGroupsOnly, $selfGroups, $selfUID, $disallowEnumeration, $restrictEnumerationGroup, $restrictEnumerationPhone, $filter) {
+ if ($entry->getProperty('UID') === $selfUID) {
return false;
}
- // Prevent enumerating local users
- if ($disallowEnumeration && $entry->getProperty('isLocalSystemBook')) {
- $filterUser = true;
+ if ($entry->getProperty('isLocalSystemBook')) {
+ if ($skipLocal) {
+ return false;
+ }
+
+ $checkedCommonGroupAlready = false;
+
+ // Prevent enumerating local users
+ if ($disallowEnumeration) {
+ $filterUser = true;
- $mailAddresses = $entry->getEMailAddresses();
- foreach ($mailAddresses as $mailAddress) {
- if ($mailAddress === $filter) {
+ $mailAddresses = $entry->getEMailAddresses();
+ foreach ($mailAddresses as $mailAddress) {
+ if ($mailAddress === $filter) {
+ $filterUser = false;
+ break;
+ }
+ }
+
+ if ($entry->getProperty('UID') && $entry->getProperty('UID') === $filter) {
$filterUser = false;
- break;
}
- }
- if ($entry->getProperty('UID') && $entry->getProperty('UID') === $filter) {
- $filterUser = false;
- }
+ if ($filterUser) {
+ return false;
+ }
+ } elseif ($restrictEnumerationPhone || $restrictEnumerationGroup) {
+ $canEnumerate = false;
+ if ($restrictEnumerationPhone) {
+ $canEnumerate = $this->knownUserService->isKnownToUser($selfUID, $entry->getProperty('UID'));
+ }
- if ($filterUser) {
- return false;
- }
- }
+ if (!$canEnumerate && $restrictEnumerationGroup) {
+ $user = $this->userManager->get($entry->getProperty('UID'));
- if ($ownGroupsOnly && $entry->getProperty('isLocalSystemBook') === true) {
- $uid = $this->userManager->get($entry->getProperty('UID'));
+ if ($user === null) {
+ return false;
+ }
- if ($uid === null) {
- return false;
+ $contactGroups = $this->groupManager->getUserGroupIds($user);
+ $canEnumerate = !empty(array_intersect($contactGroups, $selfGroups));
+ $checkedCommonGroupAlready = true;
+ }
+
+ if (!$canEnumerate) {
+ return false;
+ }
}
- $contactGroups = $this->groupManager->getUserGroupIds($uid);
- if (count(array_intersect($contactGroups, $selfGroups)) === 0) {
- // no groups in common, so shouldn't see the contact
- return false;
+ if ($ownGroupsOnly && !$checkedCommonGroupAlready) {
+ $user = $this->userManager->get($entry->getProperty('UID'));
+
+ if ($user === null) {
+ return false;
+ }
+
+ $contactGroups = $this->groupManager->getUserGroupIds($user);
+ if (empty(array_intersect($contactGroups, $selfGroups))) {
+ // no groups in common, so shouldn't see the contact
+ return false;
+ }
}
}
- return $entry->getProperty('UID') !== $selfUID;
+ return true;
}));
}
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index 9a2b413896b..d7105873dfd 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -1822,6 +1822,11 @@ class Manager implements IManager {
$this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
}
+ public function limitEnumerationToPhone(): bool {
+ return $this->allowEnumeration() &&
+ $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
+ }
+
/**
* Copied from \OC_Util::isSharingDisabledForUser
*
diff --git a/lib/public/Share/IManager.php b/lib/public/Share/IManager.php
index 635ccc1483d..0c8732b4b15 100644
--- a/lib/public/Share/IManager.php
+++ b/lib/public/Share/IManager.php
@@ -385,6 +385,14 @@ interface IManager {
public function limitEnumerationToGroups(): bool;
/**
+ * Check if user enumeration is limited to the phonebook matches
+ *
+ * @return bool
+ * @since 21.0.1
+ */
+ public function limitEnumerationToPhone(): bool;
+
+ /**
* Check if sharing is disabled for the given user
*
* @param string $userId
diff --git a/tests/lib/Collaboration/Collaborators/MailPluginTest.php b/tests/lib/Collaboration/Collaborators/MailPluginTest.php
index 141d4b680b7..3128231a108 100644
--- a/tests/lib/Collaboration/Collaborators/MailPluginTest.php
+++ b/tests/lib/Collaboration/Collaborators/MailPluginTest.php
@@ -26,6 +26,7 @@ namespace Test\Collaboration\Collaborators;
use OC\Collaboration\Collaborators\MailPlugin;
use OC\Collaboration\Collaborators\SearchResult;
use OC\Federation\CloudIdManager;
+use OC\KnownUser\KnownUserService;
use OCP\Collaboration\Collaborators\SearchResultType;
use OCP\Contacts\IManager;
use OCP\Federation\ICloudIdManager;
@@ -55,6 +56,9 @@ class MailPluginTest extends TestCase {
/** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject */
protected $groupManager;
+ /** @var KnownUserService|\PHPUnit\Framework\MockObject\MockObject */
+ protected $knownUserService;
+
/** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
protected $userSession;
@@ -64,6 +68,7 @@ class MailPluginTest extends TestCase {
$this->config = $this->createMock(IConfig::class);
$this->contactsManager = $this->createMock(IManager::class);
$this->groupManager = $this->createMock(IGroupManager::class);
+ $this->knownUserService = $this->createMock(KnownUserService::class);
$this->userSession = $this->createMock(IUserSession::class);
$this->cloudIdManager = new CloudIdManager($this->contactsManager);
@@ -71,7 +76,14 @@ class MailPluginTest extends TestCase {
}
public function instantiatePlugin() {
- $this->plugin = new MailPlugin($this->contactsManager, $this->cloudIdManager, $this->config, $this->groupManager, $this->userSession);
+ $this->plugin = new MailPlugin(
+ $this->contactsManager,
+ $this->cloudIdManager,
+ $this->config,
+ $this->groupManager,
+ $this->knownUserService,
+ $this->userSession
+ );
}
/**
diff --git a/tests/lib/Collaboration/Collaborators/UserPluginTest.php b/tests/lib/Collaboration/Collaborators/UserPluginTest.php
index 2806540d00e..f2e0e7e274b 100644
--- a/tests/lib/Collaboration/Collaborators/UserPluginTest.php
+++ b/tests/lib/Collaboration/Collaborators/UserPluginTest.php
@@ -25,6 +25,7 @@ namespace Test\Collaboration\Collaborators;
use OC\Collaboration\Collaborators\SearchResult;
use OC\Collaboration\Collaborators\UserPlugin;
+use OC\KnownUser\KnownUserService;
use OCP\Collaboration\Collaborators\ISearchResult;
use OCP\IConfig;
use OCP\IGroup;
@@ -49,6 +50,9 @@ class UserPluginTest extends TestCase {
/** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
protected $session;
+ /** @var KnownUserService|\PHPUnit\Framework\MockObject\MockObject */
+ protected $knownUserService;
+
/** @var IUserStatusManager|\PHPUnit\Framework\MockObject\MockObject */
protected $userStatusManager;
@@ -78,6 +82,8 @@ class UserPluginTest extends TestCase {
$this->session = $this->createMock(IUserSession::class);
+ $this->knownUserService = $this->createMock(KnownUserService::class);
+
$this->userStatusManager = $this->createMock(IUserStatusManager::class);
$this->searchResult = new SearchResult();
@@ -93,6 +99,7 @@ class UserPluginTest extends TestCase {
$this->userManager,
$this->groupManager,
$this->session,
+ $this->knownUserService,
$this->userStatusManager
);
}
diff --git a/tests/lib/Contacts/ContactsMenu/ContactsStoreTest.php b/tests/lib/Contacts/ContactsMenu/ContactsStoreTest.php
index acfe83ac558..ad83178096e 100644
--- a/tests/lib/Contacts/ContactsMenu/ContactsStoreTest.php
+++ b/tests/lib/Contacts/ContactsMenu/ContactsStoreTest.php
@@ -26,11 +26,13 @@
namespace Tests\Contacts\ContactsMenu;
use OC\Contacts\ContactsMenu\ContactsStore;
+use OC\KnownUser\KnownUserService;
use OCP\Contacts\IManager;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ContactsStoreTest extends TestCase {
@@ -44,6 +46,8 @@ class ContactsStoreTest extends TestCase {
private $groupManager;
/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
private $config;
+ /** @var KnownUserService|MockObject */
+ private $knownUserService;
protected function setUp(): void {
parent::setUp();
@@ -52,7 +56,14 @@ class ContactsStoreTest extends TestCase {
$this->userManager = $this->createMock(IUserManager::class);
$this->groupManager = $this->createMock(IGroupManager::class);
$this->config = $this->createMock(IConfig::class);
- $this->contactsStore = new ContactsStore($this->contactsManager, $this->config, $this->userManager, $this->groupManager);
+ $this->knownUserService = $this->createMock(KnownUserService::class);
+ $this->contactsStore = new ContactsStore(
+ $this->contactsManager,
+ $this->config,
+ $this->userManager,
+ $this->groupManager,
+ $this->knownUserService
+ );
}
public function testGetContactsWithoutFilter() {
@@ -171,29 +182,16 @@ class ContactsStoreTest extends TestCase {
}
public function testGetContactsWhenUserIsInExcludeGroups() {
- $this->config->expects($this->at(0))->method('getAppValue')
- ->with($this->equalTo('core'), $this->equalTo('shareapi_allow_share_dialog_user_enumeration'), $this->equalTo('yes'))
- ->willReturn('yes');
-
- $this->config->expects($this->at(1))
+ $this->config
->method('getAppValue')
- ->with($this->equalTo('core'), $this->equalTo('shareapi_restrict_user_enumeration_to_group'), $this->equalTo('no'))
- ->willReturn('no');
-
- $this->config->expects($this->at(2))
- ->method('getAppValue')
- ->with($this->equalTo('core'), $this->equalTo('shareapi_exclude_groups'), $this->equalTo('no'))
- ->willReturn('yes');
-
- $this->config->expects($this->at(3))
- ->method('getAppValue')
- ->with($this->equalTo('core'), $this->equalTo('shareapi_only_share_with_group_members'), $this->equalTo('no'))
- ->willReturn('yes');
-
- $this->config->expects($this->at(4))
- ->method('getAppValue')
- ->with($this->equalTo('core'), $this->equalTo('shareapi_exclude_groups_list'), $this->equalTo(''))
- ->willReturn('["group1", "group5", "group6"]');
+ ->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', 'yes'],
+ ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
+ ['core', 'shareapi_exclude_groups_list', '', '["group1", "group5", "group6"]'],
+ ]);
/** @var IUser|\PHPUnit\Framework\MockObject\MockObject $currentUser */
$currentUser = $this->createMock(IUser::class);
@@ -228,22 +226,94 @@ class ContactsStoreTest extends TestCase {
}
public function testGetContactsOnlyShareIfInTheSameGroup() {
- $this->config->expects($this->at(0))->method('getAppValue')
- ->with($this->equalTo('core'), $this->equalTo('shareapi_allow_share_dialog_user_enumeration'), $this->equalTo('yes'))
- ->willReturn('yes');
+ $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', 'no'],
+ ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
+ ]);
- $this->config->expects($this->at(1)) ->method('getAppValue')
- ->with($this->equalTo('core'), $this->equalTo('shareapi_restrict_user_enumeration_to_group'), $this->equalTo('no'))
- ->willReturn('no');
+ /** @var IUser|\PHPUnit\Framework\MockObject\MockObject $currentUser */
+ $currentUser = $this->createMock(IUser::class);
+ $currentUser->expects($this->once())
+ ->method('getUID')
+ ->willReturn('user001');
- $this->config->expects($this->at(2)) ->method('getAppValue')
- ->with($this->equalTo('core'), $this->equalTo('shareapi_exclude_groups'), $this->equalTo('no'))
- ->willReturn('no');
+ $this->groupManager->expects($this->at(0))
+ ->method('getUserGroupIds')
+ ->with($this->equalTo($currentUser))
+ ->willReturn(['group1', 'group2', 'group3']);
+
+ $user1 = $this->createMock(IUser::class);
+ $this->userManager->expects($this->at(0))
+ ->method('get')
+ ->with('user1')
+ ->willReturn($user1);
+ $this->groupManager->expects($this->at(1))
+ ->method('getUserGroupIds')
+ ->with($this->equalTo($user1))
+ ->willReturn(['group1']);
+ $user2 = $this->createMock(IUser::class);
+ $this->userManager->expects($this->at(1))
+ ->method('get')
+ ->with('user2')
+ ->willReturn($user2);
+ $this->groupManager->expects($this->at(2))
+ ->method('getUserGroupIds')
+ ->with($this->equalTo($user2))
+ ->willReturn(['group2', 'group3']);
+ $user3 = $this->createMock(IUser::class);
+ $this->userManager->expects($this->at(2))
+ ->method('get')
+ ->with('user3')
+ ->willReturn($user3);
+ $this->groupManager->expects($this->at(3))
+ ->method('getUserGroupIds')
+ ->with($this->equalTo($user3))
+ ->willReturn(['group8', 'group9']);
+
+ $this->contactsManager->expects($this->once())
+ ->method('search')
+ ->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL']))
+ ->willReturn([
+ [
+ 'UID' => 'user1',
+ 'isLocalSystemBook' => true
+ ],
+ [
+ 'UID' => 'user2',
+ 'isLocalSystemBook' => true
+ ],
+ [
+ 'UID' => 'user3',
+ 'isLocalSystemBook' => true
+ ],
+ [
+ 'UID' => 'contact',
+ ],
+ ]);
+
+ $entries = $this->contactsStore->getContacts($currentUser, '');
+
+ $this->assertCount(3, $entries);
+ $this->assertEquals('user1', $entries[0]->getProperty('UID'));
+ $this->assertEquals('user2', $entries[1]->getProperty('UID'));
+ $this->assertEquals('contact', $entries[2]->getProperty('UID'));
+ }
- $this->config->expects($this->at(3))
+ public function testGetContactsOnlyEnumerateIfInTheSameGroup() {
+ $this->config
->method('getAppValue')
- ->with($this->equalTo('core'), $this->equalTo('shareapi_only_share_with_group_members'), $this->equalTo('no'))
- ->willReturn('yes');
+ ->willReturnMap([
+ ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
+ ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'yes'],
+ ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'],
+ ['core', 'shareapi_exclude_groups', 'no', 'no'],
+ ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
+ ]);
/** @var IUser|\PHPUnit\Framework\MockObject\MockObject $currentUser */
$currentUser = $this->createMock(IUser::class);
@@ -313,23 +383,229 @@ class ContactsStoreTest extends TestCase {
$this->assertEquals('contact', $entries[2]->getProperty('UID'));
}
- public function testGetContactsOnlyEnumerateIfInTheSameGroup() {
- $this->config->expects($this->at(0))->method('getAppValue')
- ->with($this->equalTo('core'), $this->equalTo('shareapi_allow_share_dialog_user_enumeration'), $this->equalTo('yes'))
- ->willReturn('yes');
+ public function testGetContactsOnlyEnumerateIfPhoneBookMatch() {
+ $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', 'yes'],
+ ['core', 'shareapi_exclude_groups', 'no', 'no'],
+ ['core', 'shareapi_only_share_with_group_members', 'no', 'no'],
+ ]);
- $this->config->expects($this->at(1)) ->method('getAppValue')
- ->with($this->equalTo('core'), $this->equalTo('shareapi_restrict_user_enumeration_to_group'), $this->equalTo('no'))
- ->willReturn('yes');
+ /** @var IUser|\PHPUnit\Framework\MockObject\MockObject $currentUser */
+ $currentUser = $this->createMock(IUser::class);
+ $currentUser->expects($this->once())
+ ->method('getUID')
+ ->willReturn('user001');
- $this->config->expects($this->at(2)) ->method('getAppValue')
- ->with($this->equalTo('core'), $this->equalTo('shareapi_exclude_groups'), $this->equalTo('no'))
- ->willReturn('no');
+ $this->groupManager->expects($this->at(0))
+ ->method('getUserGroupIds')
+ ->with($this->equalTo($currentUser))
+ ->willReturn(['group1', 'group2', 'group3']);
+
+ $this->knownUserService->method('isKnownToUser')
+ ->willReturnMap([
+ ['user001', 'user1', true],
+ ['user001', 'user2', true],
+ ['user001', 'user3', false],
+ ]);
+
+ $this->contactsManager->expects($this->once())
+ ->method('search')
+ ->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL']))
+ ->willReturn([
+ [
+ 'UID' => 'user1',
+ 'isLocalSystemBook' => true
+ ],
+ [
+ 'UID' => 'user2',
+ 'isLocalSystemBook' => true
+ ],
+ [
+ 'UID' => 'user3',
+ 'isLocalSystemBook' => true
+ ],
+ [
+ 'UID' => 'contact',
+ ],
+ ]);
+
+ $entries = $this->contactsStore->getContacts($currentUser, '');
+
+ $this->assertCount(3, $entries);
+ $this->assertEquals('user1', $entries[0]->getProperty('UID'));
+ $this->assertEquals('user2', $entries[1]->getProperty('UID'));
+ $this->assertEquals('contact', $entries[2]->getProperty('UID'));
+ }
- $this->config->expects($this->at(3))
+ public function testGetContactsOnlyEnumerateIfPhoneBookMatchWithOwnGroupsOnly() {
+ $this->config
->method('getAppValue')
- ->with($this->equalTo('core'), $this->equalTo('shareapi_only_share_with_group_members'), $this->equalTo('no'))
- ->willReturn('no');
+ ->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', 'yes'],
+ ['core', 'shareapi_exclude_groups', 'no', 'no'],
+ ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
+ ]);
+
+ /** @var IUser|\PHPUnit\Framework\MockObject\MockObject $currentUser */
+ $currentUser = $this->createMock(IUser::class);
+ $currentUser->expects($this->once())
+ ->method('getUID')
+ ->willReturn('user001');
+
+ $this->groupManager->expects($this->at(0))
+ ->method('getUserGroupIds')
+ ->with($this->equalTo($currentUser))
+ ->willReturn(['group1', 'group2', 'group3']);
+
+ $user1 = $this->createMock(IUser::class);
+ $this->userManager->expects($this->at(0))
+ ->method('get')
+ ->with('user1')
+ ->willReturn($user1);
+ $this->groupManager->expects($this->at(1))
+ ->method('getUserGroupIds')
+ ->with($this->equalTo($user1))
+ ->willReturn(['group1']);
+ $user2 = $this->createMock(IUser::class);
+ $this->userManager->expects($this->at(1))
+ ->method('get')
+ ->with('user2')
+ ->willReturn($user2);
+ $this->groupManager->expects($this->at(2))
+ ->method('getUserGroupIds')
+ ->with($this->equalTo($user2))
+ ->willReturn(['group2', 'group3']);
+ $user3 = $this->createMock(IUser::class);
+ $this->userManager->expects($this->at(2))
+ ->method('get')
+ ->with('user3')
+ ->willReturn($user3);
+ $this->groupManager->expects($this->at(3))
+ ->method('getUserGroupIds')
+ ->with($this->equalTo($user3))
+ ->willReturn(['group8', 'group9']);
+
+ $this->knownUserService->method('isKnownToUser')
+ ->willReturnMap([
+ ['user001', 'user1', true],
+ ['user001', 'user2', true],
+ ['user001', 'user3', true],
+ ]);
+
+ $this->contactsManager->expects($this->once())
+ ->method('search')
+ ->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL']))
+ ->willReturn([
+ [
+ 'UID' => 'user1',
+ 'isLocalSystemBook' => true
+ ],
+ [
+ 'UID' => 'user2',
+ 'isLocalSystemBook' => true
+ ],
+ [
+ 'UID' => 'user3',
+ 'isLocalSystemBook' => true
+ ],
+ [
+ 'UID' => 'contact',
+ ],
+ ]);
+
+ $entries = $this->contactsStore->getContacts($currentUser, '');
+
+ $this->assertCount(3, $entries);
+ $this->assertEquals('user1', $entries[0]->getProperty('UID'));
+ $this->assertEquals('user2', $entries[1]->getProperty('UID'));
+ $this->assertEquals('contact', $entries[2]->getProperty('UID'));
+ }
+
+ public function testGetContactsOnlyEnumerateIfPhoneBookOrSameGroup() {
+ $this->config
+ ->method('getAppValue')
+ ->willReturnMap([
+ ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
+ ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'yes'],
+ ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'yes'],
+ ['core', 'shareapi_exclude_groups', 'no', 'no'],
+ ['core', 'shareapi_only_share_with_group_members', 'no', 'no'],
+ ]);
+
+ /** @var IUser|\PHPUnit\Framework\MockObject\MockObject $currentUser */
+ $currentUser = $this->createMock(IUser::class);
+ $currentUser->expects($this->once())
+ ->method('getUID')
+ ->willReturn('user001');
+
+ $this->groupManager->expects($this->at(0))
+ ->method('getUserGroupIds')
+ ->with($this->equalTo($currentUser))
+ ->willReturn(['group1', 'group2', 'group3']);
+
+ $user1 = $this->createMock(IUser::class);
+ $this->userManager->expects($this->at(0))
+ ->method('get')
+ ->with('user1')
+ ->willReturn($user1);
+ $this->groupManager->expects($this->at(1))
+ ->method('getUserGroupIds')
+ ->with($this->equalTo($user1))
+ ->willReturn(['group1']);
+
+ $this->knownUserService->method('isKnownToUser')
+ ->willReturnMap([
+ ['user001', 'user1', false],
+ ['user001', 'user2', true],
+ ['user001', 'user3', true],
+ ]);
+
+ $this->contactsManager->expects($this->once())
+ ->method('search')
+ ->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL']))
+ ->willReturn([
+ [
+ 'UID' => 'user1',
+ 'isLocalSystemBook' => true
+ ],
+ [
+ 'UID' => 'user2',
+ 'isLocalSystemBook' => true
+ ],
+ [
+ 'UID' => 'user3',
+ 'isLocalSystemBook' => true
+ ],
+ [
+ 'UID' => 'contact',
+ ],
+ ]);
+
+ $entries = $this->contactsStore->getContacts($currentUser, '');
+
+ $this->assertCount(4, $entries);
+ $this->assertEquals('user1', $entries[0]->getProperty('UID'));
+ $this->assertEquals('user2', $entries[1]->getProperty('UID'));
+ $this->assertEquals('user3', $entries[2]->getProperty('UID'));
+ $this->assertEquals('contact', $entries[3]->getProperty('UID'));
+ }
+
+ public function testGetContactsOnlyEnumerateIfPhoneBookOrSameGroupInOwnGroupsOnly() {
+ $this->config
+ ->method('getAppValue')
+ ->willReturnMap([
+ ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
+ ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'yes'],
+ ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'yes'],
+ ['core', 'shareapi_exclude_groups', 'no', 'no'],
+ ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
+ ]);
/** @var IUser|\PHPUnit\Framework\MockObject\MockObject $currentUser */
$currentUser = $this->createMock(IUser::class);
@@ -370,6 +646,13 @@ class ContactsStoreTest extends TestCase {
->with($this->equalTo($user3))
->willReturn(['group8', 'group9']);
+ $this->knownUserService->method('isKnownToUser')
+ ->willReturnMap([
+ ['user001', 'user1', false],
+ ['user001', 'user2', true],
+ ['user001', 'user3', true],
+ ]);
+
$this->contactsManager->expects($this->once())
->method('search')
->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL']))