summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorblizzz <blizzz@arthur-schiwon.de>2017-10-04 15:43:44 +0200
committerGitHub <noreply@github.com>2017-10-04 15:43:44 +0200
commit2d62f97f1bf1e7848e23ff0417915c3ab9e03e9a (patch)
treef1a67d6f764999fa802aa7034711321af684ddb9
parent5412c239f2ca128760c8d12de3bcd01384ddfd3f (diff)
parenta579f8aa375bf02f9763892ce725713f08526a1a (diff)
downloadnextcloud-server-2d62f97f1bf1e7848e23ff0417915c3ab9e03e9a.tar.gz
nextcloud-server-2d62f97f1bf1e7848e23ff0417915c3ab9e03e9a.zip
Merge pull request #6328 from nextcloud/split-sharees-api-logic
Splits off the logic from sharees endpoint thus making it available from within Nc/via PHP.
-rw-r--r--apps/files_sharing/lib/Controller/ShareesAPIController.php614
-rw-r--r--apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php1597
-rw-r--r--lib/composer/composer/autoload_classmap.php11
-rw-r--r--lib/composer/composer/autoload_static.php11
-rw-r--r--lib/private/App/InfoParser.php6
-rw-r--r--lib/private/Collaboration/Collaborators/GroupPlugin.php124
-rw-r--r--lib/private/Collaboration/Collaborators/LookupPlugin.php85
-rw-r--r--lib/private/Collaboration/Collaborators/MailPlugin.php164
-rw-r--r--lib/private/Collaboration/Collaborators/RemotePlugin.php137
-rw-r--r--lib/private/Collaboration/Collaborators/Search.php89
-rw-r--r--lib/private/Collaboration/Collaborators/SearchResult.php86
-rw-r--r--lib/private/Collaboration/Collaborators/UserPlugin.php149
-rw-r--r--lib/private/Server.php25
-rw-r--r--lib/private/legacy/app.php14
-rw-r--r--lib/public/Collaboration/Collaborators/ISearch.php50
-rw-r--r--lib/public/Collaboration/Collaborators/ISearchPlugin.php42
-rw-r--r--lib/public/Collaboration/Collaborators/ISearchResult.php73
-rw-r--r--lib/public/Collaboration/Collaborators/SearchResultType.php73
-rw-r--r--tests/lib/Collaboration/Collaborators/GroupPluginTest.php491
-rw-r--r--tests/lib/Collaboration/Collaborators/LookupPluginTest.php180
-rw-r--r--tests/lib/Collaboration/Collaborators/MailPluginTest.php336
-rw-r--r--tests/lib/Collaboration/Collaborators/RemotePluginTest.php388
-rw-r--r--tests/lib/Collaboration/Collaborators/SearchTest.php219
-rw-r--r--tests/lib/Collaboration/Collaborators/UserPluginTest.php445
24 files changed, 3286 insertions, 2123 deletions
diff --git a/apps/files_sharing/lib/Controller/ShareesAPIController.php b/apps/files_sharing/lib/Controller/ShareesAPIController.php
index 94a4854dbde..dcecf2c8e08 100644
--- a/apps/files_sharing/lib/Controller/ShareesAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareesAPIController.php
@@ -6,6 +6,7 @@
* @author Joas Schilling <coding@schilljs.com>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Müller <thomas.mueller@tmit.eu>
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @license AGPL-3.0
*
@@ -27,52 +28,23 @@ namespace OCA\Files_Sharing\Controller;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSBadRequestException;
use OCP\AppFramework\OCSController;
-use OCP\Contacts\IManager;
-use OCP\Federation\ICloudIdManager;
-use OCP\Http\Client\IClientService;
-use OCP\IGroup;
-use OCP\IGroupManager;
-use OCP\ILogger;
+use OCP\Collaboration\Collaborators\ISearch;
use OCP\IRequest;
-use OCP\IUser;
-use OCP\IUserManager;
use OCP\IConfig;
-use OCP\IUserSession;
use OCP\IURLGenerator;
use OCP\Share;
+use OCP\Share\IManager;
class ShareesAPIController extends OCSController {
-
- /** @var IGroupManager */
- protected $groupManager;
-
- /** @var IUserManager */
- protected $userManager;
-
- /** @var IManager */
- protected $contactsManager;
-
/** @var IConfig */
protected $config;
- /** @var IUserSession */
- protected $userSession;
-
/** @var IURLGenerator */
protected $urlGenerator;
- /** @var ILogger */
- protected $logger;
-
- /** @var \OCP\Share\IManager */
+ /** @var IManager */
protected $shareManager;
- /** @var IClientService */
- protected $clientService;
-
- /** @var ICloudIdManager */
- protected $cloudIdManager;
-
/** @var bool */
protected $shareWithGroupOnly = false;
@@ -103,326 +75,31 @@ class ShareesAPIController extends OCSController {
];
protected $reachedEndFor = [];
+ /** @var ISearch */
+ private $collaboratorSearch;
/**
* @param string $appName
* @param IRequest $request
- * @param IGroupManager $groupManager
- * @param IUserManager $userManager
- * @param IManager $contactsManager
* @param IConfig $config
- * @param IUserSession $userSession
* @param IURLGenerator $urlGenerator
- * @param ILogger $logger
- * @param \OCP\Share\IManager $shareManager
- * @param IClientService $clientService
- * @param ICloudIdManager $cloudIdManager
+ * @param IManager $shareManager
+ * @param ISearch $collaboratorSearch
*/
- public function __construct($appName,
- IRequest $request,
- IGroupManager $groupManager,
- IUserManager $userManager,
- IManager $contactsManager,
- IConfig $config,
- IUserSession $userSession,
- IURLGenerator $urlGenerator,
- ILogger $logger,
- \OCP\Share\IManager $shareManager,
- IClientService $clientService,
- ICloudIdManager $cloudIdManager
+ public function __construct(
+ $appName,
+ IRequest $request,
+ IConfig $config,
+ IURLGenerator $urlGenerator,
+ IManager $shareManager,
+ ISearch $collaboratorSearch
) {
parent::__construct($appName, $request);
- $this->groupManager = $groupManager;
- $this->userManager = $userManager;
- $this->contactsManager = $contactsManager;
$this->config = $config;
- $this->userSession = $userSession;
$this->urlGenerator = $urlGenerator;
- $this->logger = $logger;
$this->shareManager = $shareManager;
- $this->clientService = $clientService;
- $this->cloudIdManager = $cloudIdManager;
- }
-
- /**
- * @param string $search
- */
- protected function getUsers($search) {
- $this->result['users'] = $this->result['exact']['users'] = $users = [];
-
- $userGroups = [];
- if ($this->shareWithGroupOnly) {
- // Search in all the groups this user is part of
- $userGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser());
- foreach ($userGroups as $userGroup) {
- $usersTmp = $this->groupManager->displayNamesInGroup($userGroup, $search, $this->limit, $this->offset);
- foreach ($usersTmp as $uid => $userDisplayName) {
- $users[$uid] = $userDisplayName;
- }
- }
- } else {
- // Search in all users
- $usersTmp = $this->userManager->searchDisplayName($search, $this->limit, $this->offset);
-
- foreach ($usersTmp as $user) {
- $users[$user->getUID()] = $user->getDisplayName();
- }
- }
-
- if (!$this->shareeEnumeration || sizeof($users) < $this->limit) {
- $this->reachedEndFor[] = 'users';
- }
-
- $foundUserById = false;
- $lowerSearch = strtolower($search);
- foreach ($users as $uid => $userDisplayName) {
- if (strtolower($uid) === $lowerSearch || strtolower($userDisplayName) === $lowerSearch) {
- if (strtolower($uid) === $lowerSearch) {
- $foundUserById = true;
- }
- $this->result['exact']['users'][] = [
- 'label' => $userDisplayName,
- 'value' => [
- 'shareType' => Share::SHARE_TYPE_USER,
- 'shareWith' => $uid,
- ],
- ];
- } else {
- $this->result['users'][] = [
- 'label' => $userDisplayName,
- 'value' => [
- 'shareType' => Share::SHARE_TYPE_USER,
- 'shareWith' => $uid,
- ],
- ];
- }
- }
-
- if ($this->offset === 0 && !$foundUserById) {
- // On page one we try if the search result has a direct hit on the
- // user id and if so, we add that to the exact match list
- $user = $this->userManager->get($search);
- if ($user instanceof IUser) {
- $addUser = true;
-
- if ($this->shareWithGroupOnly) {
- // Only add, if we have a common group
- $commonGroups = array_intersect($userGroups, $this->groupManager->getUserGroupIds($user));
- $addUser = !empty($commonGroups);
- }
-
- if ($addUser) {
- array_push($this->result['exact']['users'], [
- 'label' => $user->getDisplayName(),
- 'value' => [
- 'shareType' => Share::SHARE_TYPE_USER,
- 'shareWith' => $user->getUID(),
- ],
- ]);
- }
- }
- }
-
- if (!$this->shareeEnumeration) {
- $this->result['users'] = [];
- }
- }
-
- /**
- * @param string $search
- */
- protected function getGroups($search) {
- $this->result['groups'] = $this->result['exact']['groups'] = [];
-
- $groups = $this->groupManager->search($search, $this->limit, $this->offset);
- $groupIds = array_map(function (IGroup $group) { return $group->getGID(); }, $groups);
-
- if (!$this->shareeEnumeration || sizeof($groups) < $this->limit) {
- $this->reachedEndFor[] = 'groups';
- }
-
- $userGroups = [];
- if (!empty($groups) && $this->shareWithGroupOnly) {
- // Intersect all the groups that match with the groups this user is a member of
- $userGroups = $this->groupManager->getUserGroups($this->userSession->getUser());
- $userGroups = array_map(function (IGroup $group) { return $group->getGID(); }, $userGroups);
- $groupIds = array_intersect($groupIds, $userGroups);
- }
-
- $lowerSearch = strtolower($search);
- foreach ($groups as $group) {
- // FIXME: use a more efficient approach
- $gid = $group->getGID();
- if (!in_array($gid, $groupIds)) {
- continue;
- }
- if (strtolower($gid) === $lowerSearch || strtolower($group->getDisplayName()) === $lowerSearch) {
- $this->result['exact']['groups'][] = [
- 'label' => $group->getDisplayName(),
- 'value' => [
- 'shareType' => Share::SHARE_TYPE_GROUP,
- 'shareWith' => $gid,
- ],
- ];
- } else {
- $this->result['groups'][] = [
- 'label' => $group->getDisplayName(),
- 'value' => [
- 'shareType' => Share::SHARE_TYPE_GROUP,
- 'shareWith' => $gid,
- ],
- ];
- }
- }
-
- if ($this->offset === 0 && empty($this->result['exact']['groups'])) {
- // On page one we try if the search result has a direct hit on the
- // user id and if so, we add that to the exact match list
- $group = $this->groupManager->get($search);
- if ($group instanceof IGroup && (!$this->shareWithGroupOnly || in_array($group->getGID(), $userGroups))) {
- array_push($this->result['exact']['groups'], [
- 'label' => $group->getDisplayName(),
- 'value' => [
- 'shareType' => Share::SHARE_TYPE_GROUP,
- 'shareWith' => $group->getGID(),
- ],
- ]);
- }
- }
-
- if (!$this->shareeEnumeration) {
- $this->result['groups'] = [];
- }
- }
-
-
- /**
- * @param string $search
- * @suppress PhanUndeclaredClassMethod
- */
- protected function getCircles($search) {
- $this->result['circles'] = $this->result['exact']['circles'] = [];
-
- $result = \OCA\Circles\Api\Sharees::search($search, $this->limit, $this->offset);
- if (array_key_exists('circles', $result['exact'])) {
- $this->result['exact']['circles'] = $result['exact']['circles'];
- }
- if (array_key_exists('circles', $result)) {
- $this->result['circles'] = $result['circles'];
- }
- }
-
-
- /**
- * @param string $search
- * @return array
- */
- protected function getRemote($search) {
- $result = ['results' => [], 'exact' => []];
-
- // Search in contacts
- //@todo Pagination missing
- $addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN']);
- $result['exactIdMatch'] = false;
- foreach ($addressBookContacts as $contact) {
- if (isset($contact['isLocalSystemBook'])) {
- continue;
- }
- if (isset($contact['CLOUD'])) {
- $cloudIds = $contact['CLOUD'];
- if (!is_array($cloudIds)) {
- $cloudIds = [$cloudIds];
- }
- $lowerSearch = strtolower($search);
- foreach ($cloudIds as $cloudId) {
- try {
- list(, $serverUrl) = $this->splitUserRemote($cloudId);
- } catch (\InvalidArgumentException $e) {
- continue;
- }
-
- if (strtolower($contact['FN']) === $lowerSearch || strtolower($cloudId) === $lowerSearch) {
- if (strtolower($cloudId) === $lowerSearch) {
- $result['exactIdMatch'] = true;
- }
- $result['exact'][] = [
- 'label' => $contact['FN'] . " ($cloudId)",
- 'value' => [
- 'shareType' => Share::SHARE_TYPE_REMOTE,
- 'shareWith' => $cloudId,
- 'server' => $serverUrl,
- ],
- ];
- } else {
- $result['results'][] = [
- 'label' => $contact['FN'] . " ($cloudId)",
- 'value' => [
- 'shareType' => Share::SHARE_TYPE_REMOTE,
- 'shareWith' => $cloudId,
- 'server' => $serverUrl,
- ],
- ];
- }
- }
- }
- }
-
- if (!$this->shareeEnumeration) {
- $result['results'] = [];
- }
-
- if (!$result['exactIdMatch'] && $this->cloudIdManager->isValidCloudId($search) && $this->offset === 0) {
- $result['exact'][] = [
- 'label' => $search,
- 'value' => [
- 'shareType' => Share::SHARE_TYPE_REMOTE,
- 'shareWith' => $search,
- ],
- ];
- }
-
- $this->reachedEndFor[] = 'remotes';
-
- return $result;
- }
-
- /**
- * split user and remote from federated cloud id
- *
- * @param string $address federated share address
- * @return array [user, remoteURL]
- * @throws \InvalidArgumentException
- */
- public function splitUserRemote($address) {
- try {
- $cloudId = $this->cloudIdManager->resolveCloudId($address);
- return [$cloudId->getUser(), $cloudId->getRemote()];
- } catch (\InvalidArgumentException $e) {
- throw new \InvalidArgumentException('Invalid Federated Cloud ID', 0, $e);
- }
- }
-
- /**
- * Strips away a potential file names and trailing slashes:
- * - http://localhost
- * - http://localhost/
- * - http://localhost/index.php
- * - http://localhost/index.php/s/{shareToken}
- *
- * all return: http://localhost
- *
- * @param string $remote
- * @return string
- */
- protected function fixRemoteURL($remote) {
- $remote = str_replace('\\', '/', $remote);
- if ($fileNamePosition = strpos($remote, '/index.php')) {
- $remote = substr($remote, 0, $fileNamePosition);
- }
- $remote = rtrim($remote, '/');
-
- return $remote;
+ $this->collaboratorSearch = $collaboratorSearch;
}
/**
@@ -461,7 +138,9 @@ class ShareesAPIController extends OCSController {
Share::SHARE_TYPE_USER,
];
- if ($itemType === 'file' || $itemType === 'folder') {
+ if ($itemType === null) {
+ throw new OCSBadRequestException('Missing itemType');
+ } elseif ($itemType === 'file' || $itemType === 'folder') {
if ($this->shareManager->allowGroupSharing()) {
$shareTypes[] = Share::SHARE_TYPE_GROUP;
}
@@ -478,6 +157,7 @@ class ShareesAPIController extends OCSController {
$shareTypes[] = Share::SHARE_TYPE_EMAIL;
}
+ // FIXME: DI
if (\OC::$server->getAppManager()->isEnabledForUser('circles') && class_exists('\OCA\Circles\ShareByCircleProvider')) {
$shareTypes[] = Share::SHARE_TYPE_CIRCLE;
}
@@ -495,94 +175,16 @@ class ShareesAPIController extends OCSController {
$this->limit = (int) $perPage;
$this->offset = $perPage * ($page - 1);
- return $this->searchSharees($search, $itemType, $shareTypes, $page, $perPage, $lookup);
- }
-
- /**
- * Method to get out the static call for better testing
- *
- * @param string $itemType
- * @return bool
- */
- protected function isRemoteSharingAllowed($itemType) {
- try {
- $backend = \OC\Share\Share::getBackend($itemType);
- return $backend->isShareTypeAllowed(Share::SHARE_TYPE_REMOTE);
- } catch (\Exception $e) {
- return false;
- }
- }
-
- /**
- * Testable search function that does not need globals
- *
- * @param string $search
- * @param string $itemType
- * @param array $shareTypes
- * @param int $page
- * @param int $perPage
- * @param bool $lookup
- * @return DataResponse
- * @throws OCSBadRequestException
- */
- protected function searchSharees($search, $itemType, array $shareTypes, $page, $perPage, $lookup) {
- // Verify arguments
- if ($itemType === null) {
- throw new OCSBadRequestException('Missing itemType');
- }
-
- // Get users
- if (in_array(Share::SHARE_TYPE_USER, $shareTypes)) {
- $this->getUsers($search);
- }
-
- // Get groups
- if (in_array(Share::SHARE_TYPE_GROUP, $shareTypes)) {
- $this->getGroups($search);
- }
-
- // Get circles
- if (in_array(Share::SHARE_TYPE_CIRCLE, $shareTypes)) {
- $this->getCircles($search);
- }
-
-
- // Get remote
- $remoteResults = ['results' => [], 'exact' => [], 'exactIdMatch' => false];
- if (in_array(Share::SHARE_TYPE_REMOTE, $shareTypes)) {
- $remoteResults = $this->getRemote($search);
- }
-
- // Get emails
- $mailResults = ['results' => [], 'exact' => [], 'exactIdMatch' => false];
- if (in_array(Share::SHARE_TYPE_EMAIL, $shareTypes)) {
- $mailResults = $this->getEmail($search);
- }
-
- // Get from lookup server
- if ($lookup) {
- $this->getLookup($search);
- }
+ list($result, $hasMoreResults) = $this->collaboratorSearch->search($search, $shareTypes, $lookup, $this->limit, $this->offset);
- // if we have a exact match, either for the federated cloud id or for the
- // email address we only return the exact match. It is highly unlikely
- // that the exact same email address and federated cloud id exists
- if ($mailResults['exactIdMatch'] && !$remoteResults['exactIdMatch']) {
- $this->result['emails'] = $mailResults['results'];
- $this->result['exact']['emails'] = $mailResults['exact'];
- } else if (!$mailResults['exactIdMatch'] && $remoteResults['exactIdMatch']) {
- $this->result['remotes'] = $remoteResults['results'];
- $this->result['exact']['remotes'] = $remoteResults['exact'];
- } else {
- $this->result['remotes'] = $remoteResults['results'];
- $this->result['exact']['remotes'] = $remoteResults['exact'];
- $this->result['emails'] = $mailResults['results'];
- $this->result['exact']['emails'] = $mailResults['exact'];
+ // extra treatment for 'exact' subarray, with a single merge expected keys might be lost
+ if(isset($result['exact'])) {
+ $result['exact'] = array_merge($this->result['exact'], $result['exact']);
}
-
+ $this->result = array_merge($this->result, $result);
$response = new DataResponse($this->result);
- if (sizeof($this->reachedEndFor) < 3) {
+ if ($hasMoreResults) {
$response->addHeader('Link', $this->getPaginationLink($page, [
'search' => $search,
'itemType' => $itemType,
@@ -595,166 +197,22 @@ class ShareesAPIController extends OCSController {
}
/**
- * @param string $search
- * @return array
- */
- protected function getEmail($search) {
- $result = ['results' => [], 'exact' => [], 'exactIdMatch' => false];
-
- // Search in contacts
- //@todo Pagination missing
- $addressBookContacts = $this->contactsManager->search($search, ['EMAIL', 'FN']);
- $lowerSearch = strtolower($search);
- foreach ($addressBookContacts as $contact) {
- if (isset($contact['EMAIL'])) {
- $emailAddresses = $contact['EMAIL'];
- if (!is_array($emailAddresses)) {
- $emailAddresses = [$emailAddresses];
- }
- foreach ($emailAddresses as $emailAddress) {
- $exactEmailMatch = strtolower($emailAddress) === $lowerSearch;
-
- if (isset($contact['isLocalSystemBook'])) {
- if ($exactEmailMatch) {
- try {
- $cloud = $this->cloudIdManager->resolveCloudId($contact['CLOUD'][0]);
- } catch (\InvalidArgumentException $e) {
- continue;
- }
-
- if (!$this->hasUserInResult($cloud->getUser())) {
- $this->result['exact']['users'][] = [
- 'label' => $contact['FN'] . " ($emailAddress)",
- 'value' => [
- 'shareType' => Share::SHARE_TYPE_USER,
- 'shareWith' => $cloud->getUser(),
- ],
- ];
- }
- return ['results' => [], 'exact' => [], 'exactIdMatch' => true];
- }
-
- if ($this->shareeEnumeration) {
- try {
- $cloud = $this->cloudIdManager->resolveCloudId($contact['CLOUD'][0]);
- } catch (\InvalidArgumentException $e) {
- continue;
- }
-
- if (!$this->hasUserInResult($cloud->getUser())) {
- $this->result['users'][] = [
- 'label' => $contact['FN'] . " ($emailAddress)",
- 'value' => [
- 'shareType' => Share::SHARE_TYPE_USER,
- 'shareWith' => $cloud->getUser(),
- ],
- ];
- }
- }
- continue;
- }
-
- if ($exactEmailMatch || strtolower($contact['FN']) === $lowerSearch) {
- if ($exactEmailMatch) {
- $result['exactIdMatch'] = true;
- }
- $result['exact'][] = [
- 'label' => $contact['FN'] . " ($emailAddress)",
- 'value' => [
- 'shareType' => Share::SHARE_TYPE_EMAIL,
- 'shareWith' => $emailAddress,
- ],
- ];
- } else {
- $result['results'][] = [
- 'label' => $contact['FN'] . " ($emailAddress)",
- 'value' => [
- 'shareType' => Share::SHARE_TYPE_EMAIL,
- 'shareWith' => $emailAddress,
- ],
- ];
- }
- }
- }
- }
-
- if (!$this->shareeEnumeration) {
- $result['results'] = [];
- }
-
- if (!$result['exactIdMatch'] && filter_var($search, FILTER_VALIDATE_EMAIL)) {
- $result['exact'][] = [
- 'label' => $search,
- 'value' => [
- 'shareType' => Share::SHARE_TYPE_EMAIL,
- 'shareWith' => $search,
- ],
- ];
- }
-
- $this->reachedEndFor[] = 'emails';
-
- return $result;
- }
-
- protected function getLookup($search) {
- $isEnabled = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no');
- $lookupServerUrl = $this->config->getSystemValue('lookup_server', 'https://lookup.nextcloud.com');
- $lookupServerUrl = rtrim($lookupServerUrl, '/');
- $result = [];
-
- if($isEnabled === 'yes') {
- try {
- $client = $this->clientService->newClient();
- $response = $client->get(
- $lookupServerUrl . '/users?search=' . urlencode($search),
- [
- 'timeout' => 10,
- 'connect_timeout' => 3,
- ]
- );
-
- $body = json_decode($response->getBody(), true);
-
- $result = [];
- foreach ($body as $lookup) {
- $result[] = [
- 'label' => $lookup['federationId'],
- 'value' => [
- 'shareType' => Share::SHARE_TYPE_REMOTE,
- 'shareWith' => $lookup['federationId'],
- ],
- 'extra' => $lookup,
- ];
- }
- } catch (\Exception $e) {}
- }
-
- $this->result['lookup'] = $result;
- }
-
- /**
- * Check if a given user is already part of the result
+ * Method to get out the static call for better testing
*
- * @param string $userId
+ * @param string $itemType
* @return bool
*/
- protected function hasUserInResult($userId) {
- foreach ($this->result['exact']['users'] as $result) {
- if ($result['value']['shareWith'] === $userId) {
- return true;
- }
- }
-
- foreach ($this->result['users'] as $result) {
- if ($result['value']['shareWith'] === $userId) {
- return true;
- }
+ protected function isRemoteSharingAllowed($itemType) {
+ try {
+ // FIXME: static foo makes unit testing unnecessarily difficult
+ $backend = \OC\Share\Share::getBackend($itemType);
+ return $backend->isShareTypeAllowed(Share::SHARE_TYPE_REMOTE);
+ } catch (\Exception $e) {
+ return false;
}
-
- return false;
}
+
/**
* Generates a bunch of pagination links for the current page
*
diff --git a/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php
index e027d0751cb..2b919f4849d 100644
--- a/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareesAPIControllerTest.php
@@ -25,14 +25,16 @@
namespace OCA\Files_Sharing\Tests\Controller;
-use OC\Federation\CloudIdManager;
use OCA\Files_Sharing\Controller\ShareesAPIController;
use OCA\Files_Sharing\Tests\TestCase;
use OCP\AppFramework\Http;
use OCP\AppFramework\OCS\OCSBadRequestException;
-use OCP\Federation\ICloudIdManager;
-use OCP\Http\Client\IClientService;
+use OCP\Collaboration\Collaborators\ISearch;
+use OCP\IConfig;
+use OCP\IRequest;
+use OCP\IURLGenerator;
use OCP\Share;
+use OCP\Share\IManager;
/**
* Class ShareesTest
@@ -45,1251 +47,39 @@ class ShareesAPIControllerTest extends TestCase {
/** @var ShareesAPIController */
protected $sharees;
- /** @var \OCP\IUserManager|\PHPUnit_Framework_MockObject_MockObject */
- protected $userManager;
-
- /** @var \OCP\IGroupManager|\PHPUnit_Framework_MockObject_MockObject */
- protected $groupManager;
-
- /** @var \OCP\Contacts\IManager|\PHPUnit_Framework_MockObject_MockObject */
- protected $contactsManager;
-
- /** @var \OCP\IUserSession|\PHPUnit_Framework_MockObject_MockObject */
- protected $session;
-
- /** @var \OCP\IRequest|\PHPUnit_Framework_MockObject_MockObject */
+ /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */
protected $request;
- /** @var \OCP\Share\IManager|\PHPUnit_Framework_MockObject_MockObject */
+ /** @var IManager|\PHPUnit_Framework_MockObject_MockObject */
protected $shareManager;
- /** @var IClientService|\PHPUnit_Framework_MockObject_MockObject */
- private $clientService;
-
- /** @var ICloudIdManager */
- private $cloudIdManager;
+ /** @var ISearch|\PHPUnit_Framework_MockObject_MockObject */
+ protected $collaboratorSearch;
protected function setUp() {
parent::setUp();
- $this->userManager = $this->getMockBuilder('OCP\IUserManager')
- ->disableOriginalConstructor()
- ->getMock();
+ $this->request = $this->createMock(IRequest::class);
+ $this->shareManager = $this->createMock(IManager::class);
- $this->groupManager = $this->getMockBuilder('OCP\IGroupManager')
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject $configMock */
+ $configMock = $this->createMock(IConfig::class);
- $this->contactsManager = $this->getMockBuilder('OCP\Contacts\IManager')
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject $urlGeneratorMock */
+ $urlGeneratorMock = $this->createMock(IURLGenerator::class);
- $this->session = $this->getMockBuilder('OCP\IUserSession')
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->request = $this->getMockBuilder('OCP\IRequest')
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->shareManager = $this->getMockBuilder('OCP\Share\IManager')
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->clientService = $this->createMock(IClientService::class);
-
- $this->cloudIdManager = new CloudIdManager();
+ $this->collaboratorSearch = $this->createMock(ISearch::class);
$this->sharees = new ShareesAPIController(
'files_sharing',
$this->request,
- $this->groupManager,
- $this->userManager,
- $this->contactsManager,
- $this->getMockBuilder('OCP\IConfig')->disableOriginalConstructor()->getMock(),
- $this->session,
- $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(),
- $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(),
+ $configMock,
+ $urlGeneratorMock,
$this->shareManager,
- $this->clientService,
- $this->cloudIdManager
+ $this->collaboratorSearch
);
}
- /**
- * @param string $uid
- * @param string $displayName
- * @return \OCP\IUser|\PHPUnit_Framework_MockObject_MockObject
- */
- protected function getUserMock($uid, $displayName) {
- $user = $this->getMockBuilder('OCP\IUser')
- ->disableOriginalConstructor()
- ->getMock();
-
- $user->expects($this->any())
- ->method('getUID')
- ->willReturn($uid);
-
- $user->expects($this->any())
- ->method('getDisplayName')
- ->willReturn($displayName);
-
- return $user;
- }
-
- /**
- * @param string $gid
- * @return \OCP\IGroup|\PHPUnit_Framework_MockObject_MockObject
- */
- protected function getGroupMock($gid, $displayName = null) {
- $group = $this->getMockBuilder('OCP\IGroup')
- ->disableOriginalConstructor()
- ->getMock();
-
- $group->expects($this->any())
- ->method('getGID')
- ->willReturn($gid);
-
- if (is_null($displayName)) {
- // note: this is how the Group class behaves
- $displayName = $gid;
- }
-
- $group->expects($this->any())
- ->method('getDisplayName')
- ->willReturn($displayName);
-
- return $group;
- }
-
- public function dataGetUsers() {
- return [
- ['test', false, true, [], [], [], [], true, false],
- ['test', false, false, [], [], [], [], true, false],
- ['test', true, true, [], [], [], [], true, false],
- ['test', true, false, [], [], [], [], true, false],
- [
- 'test', false, true, [], [],
- [
- ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
- ], [], true, $this->getUserMock('test', 'Test')
- ],
- [
- 'test', false, false, [], [],
- [
- ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
- ], [], true, $this->getUserMock('test', 'Test')
- ],
- [
- 'test', true, true, [], [],
- [], [], true, $this->getUserMock('test', 'Test')
- ],
- [
- 'test', true, false, [], [],
- [], [], true, $this->getUserMock('test', 'Test')
- ],
- [
- 'test', true, true, ['test-group'], [['test-group', 'test', 2, 0, []]],
- [
- ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
- ], [], true, $this->getUserMock('test', 'Test')
- ],
- [
- 'test', true, false, ['test-group'], [['test-group', 'test', 2, 0, []]],
- [
- ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
- ], [], true, $this->getUserMock('test', 'Test')
- ],
- [
- 'test',
- false,
- true,
- [],
- [
- $this->getUserMock('test1', 'Test One'),
- ],
- [],
- [
- ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
- ],
- true,
- false,
- ],
- [
- 'test',
- false,
- false,
- [],
- [
- $this->getUserMock('test1', 'Test One'),
- ],
- [],
- [],
- true,
- false,
- ],
- [
- 'test',
- false,
- true,
- [],
- [
- $this->getUserMock('test1', 'Test One'),
- $this->getUserMock('test2', 'Test Two'),
- ],
- [],
- [
- ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
- ['label' => 'Test Two', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
- ],
- false,
- false,
- ],
- [
- 'test',
- false,
- false,
- [],
- [
- $this->getUserMock('test1', 'Test One'),
- $this->getUserMock('test2', 'Test Two'),
- ],
- [],
- [],
- true,
- false,
- ],
- [
- 'test',
- false,
- true,
- [],
- [
- $this->getUserMock('test0', 'Test'),
- $this->getUserMock('test1', 'Test One'),
- $this->getUserMock('test2', 'Test Two'),
- ],
- [
- ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test0']],
- ],
- [
- ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
- ['label' => 'Test Two', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
- ],
- false,
- false,
- ],
- [
- 'test',
- false,
- false,
- [],
- [
- $this->getUserMock('test0', 'Test'),
- $this->getUserMock('test1', 'Test One'),
- $this->getUserMock('test2', 'Test Two'),
- ],
- [
- ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test0']],
- ],
- [],
- true,
- false,
- ],
- [
- 'test',
- true,
- true,
- ['abc', 'xyz'],
- [
- ['abc', 'test', 2, 0, ['test1' => 'Test One']],
- ['xyz', 'test', 2, 0, []],
- ],
- [],
- [
- ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
- ],
- true,
- false,
- ],
- [
- 'test',
- true,
- false,
- ['abc', 'xyz'],
- [
- ['abc', 'test', 2, 0, ['test1' => 'Test One']],
- ['xyz', 'test', 2, 0, []],
- ],
- [],
- [],
- true,
- false,
- ],
- [
- 'test',
- true,
- true,
- ['abc', 'xyz'],
- [
- ['abc', 'test', 2, 0, [
- 'test1' => 'Test One',
- 'test2' => 'Test Two',
- ]],
- ['xyz', 'test', 2, 0, [
- 'test1' => 'Test One',
- 'test2' => 'Test Two',
- ]],
- ],
- [],
- [
- ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
- ['label' => 'Test Two', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
- ],
- false,
- false,
- ],
- [
- 'test',
- true,
- false,
- ['abc', 'xyz'],
- [
- ['abc', 'test', 2, 0, [
- 'test1' => 'Test One',
- 'test2' => 'Test Two',
- ]],
- ['xyz', 'test', 2, 0, [
- 'test1' => 'Test One',
- 'test2' => 'Test Two',
- ]],
- ],
- [],
- [],
- true,
- false,
- ],
- [
- 'test',
- true,
- true,
- ['abc', 'xyz'],
- [
- ['abc', 'test', 2, 0, [
- 'test' => 'Test One',
- ]],
- ['xyz', 'test', 2, 0, [
- 'test2' => 'Test Two',
- ]],
- ],
- [
- ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
- ],
- [
- ['label' => 'Test Two', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
- ],
- false,
- false,
- ],
- [
- 'test',
- true,
- false,
- ['abc', 'xyz'],
- [
- ['abc', 'test', 2, 0, [
- 'test' => 'Test One',
- ]],
- ['xyz', 'test', 2, 0, [
- 'test2' => 'Test Two',
- ]],
- ],
- [
- ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
- ],
- [],
- true,
- false,
- ],
- ];
- }
-
- /**
- * @dataProvider dataGetUsers
- *
- * @param string $searchTerm
- * @param bool $shareWithGroupOnly
- * @param bool $shareeEnumeration
- * @param array $groupResponse
- * @param array $userResponse
- * @param array $exactExpected
- * @param array $expected
- * @param bool $reachedEnd
- * @param mixed $singleUser
- */
- public function testGetUsers($searchTerm, $shareWithGroupOnly, $shareeEnumeration, $groupResponse, $userResponse, $exactExpected, $expected, $reachedEnd, $singleUser) {
- $this->invokePrivate($this->sharees, 'limit', [2]);
- $this->invokePrivate($this->sharees, 'offset', [0]);
- $this->invokePrivate($this->sharees, 'shareWithGroupOnly', [$shareWithGroupOnly]);
- $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]);
-
- $user = $this->getUserMock('admin', 'Administrator');
- $this->session->expects($this->any())
- ->method('getUser')
- ->willReturn($user);
-
- if (!$shareWithGroupOnly) {
- $this->userManager->expects($this->once())
- ->method('searchDisplayName')
- ->with($searchTerm, $this->invokePrivate($this->sharees, 'limit'), $this->invokePrivate($this->sharees, 'offset'))
- ->willReturn($userResponse);
- } else {
- if ($singleUser !== false) {
- $this->groupManager->expects($this->exactly(2))
- ->method('getUserGroupIds')
- ->withConsecutive(
- $user,
- $singleUser
- )
- ->willReturn($groupResponse);
- } else {
- $this->groupManager->expects($this->once())
- ->method('getUserGroupIds')
- ->with($user)
- ->willReturn($groupResponse);
- }
-
- $this->groupManager->expects($this->exactly(sizeof($groupResponse)))
- ->method('displayNamesInGroup')
- ->with($this->anything(), $searchTerm, $this->invokePrivate($this->sharees, 'limit'), $this->invokePrivate($this->sharees, 'offset'))
- ->willReturnMap($userResponse);
- }
-
- if ($singleUser !== false) {
- $this->userManager->expects($this->once())
- ->method('get')
- ->with($searchTerm)
- ->willReturn($singleUser);
- }
-
- $this->invokePrivate($this->sharees, 'getUsers', [$searchTerm]);
- $result = $this->invokePrivate($this->sharees, 'result');
-
- $this->assertEquals($exactExpected, $result['exact']['users']);
- $this->assertEquals($expected, $result['users']);
- $this->assertCount((int) $reachedEnd, $this->invokePrivate($this->sharees, 'reachedEndFor'));
- }
-
- public function dataGetGroups() {
- return [
- ['test', false, true, [], [], [], [], true, false],
- ['test', false, false, [], [], [], [], true, false],
- // group without display name
- [
- 'test', false, true,
- [$this->getGroupMock('test1')],
- [],
- [],
- [['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
- true,
- false,
- ],
- // group with display name, search by id
- [
- 'test', false, true,
- [$this->getGroupMock('test1', 'Test One')],
- [],
- [],
- [['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
- true,
- false,
- ],
- // group with display name, search by display name
- [
- 'one', false, true,
- [$this->getGroupMock('test1', 'Test One')],
- [],
- [],
- [['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
- true,
- false,
- ],
- // group with display name, search by display name, exact expected
- [
- 'Test One', false, true,
- [$this->getGroupMock('test1', 'Test One')],
- [],
- [['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
- [],
- true,
- false,
- ],
- [
- 'test', false, false,
- [$this->getGroupMock('test1')],
- [],
- [],
- [],
- true,
- false,
- ],
- [
- 'test', false, true,
- [
- $this->getGroupMock('test'),
- $this->getGroupMock('test1'),
- ],
- [],
- [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
- [['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
- false,
- false,
- ],
- [
- 'test', false, false,
- [
- $this->getGroupMock('test'),
- $this->getGroupMock('test1'),
- ],
- [],
- [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
- [],
- true,
- false,
- ],
- [
- 'test', false, true,
- [
- $this->getGroupMock('test0'),
- $this->getGroupMock('test1'),
- ],
- [],
- [],
- [
- ['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
- ['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
- ],
- false,
- null,
- ],
- [
- 'test', false, false,
- [
- $this->getGroupMock('test0'),
- $this->getGroupMock('test1'),
- ],
- [],
- [],
- [],
- true,
- null,
- ],
- [
- 'test', false, true,
- [
- $this->getGroupMock('test0'),
- $this->getGroupMock('test1'),
- ],
- [],
- [
- ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
- ],
- [
- ['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
- ['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
- ],
- false,
- $this->getGroupMock('test'),
- ],
- [
- 'test', false, false,
- [
- $this->getGroupMock('test0'),
- $this->getGroupMock('test1'),
- ],
- [],
- [
- ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
- ],
- [],
- true,
- $this->getGroupMock('test'),
- ],
- ['test', true, true, [], [], [], [], true, false],
- ['test', true, false, [], [], [], [], true, false],
- [
- 'test', true, true,
- [
- $this->getGroupMock('test1'),
- $this->getGroupMock('test2'),
- ],
- [$this->getGroupMock('test1')],
- [],
- [['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
- false,
- false,
- ],
- [
- 'test', true, false,
- [
- $this->getGroupMock('test1'),
- $this->getGroupMock('test2'),
- ],
- [$this->getGroupMock('test1')],
- [],
- [],
- true,
- false,
- ],
- [
- 'test', true, true,
- [
- $this->getGroupMock('test'),
- $this->getGroupMock('test1'),
- ],
- [$this->getGroupMock('test')],
- [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
- [],
- false,
- false,
- ],
- [
- 'test', true, false,
- [
- $this->getGroupMock('test'),
- $this->getGroupMock('test1'),
- ],
- [$this->getGroupMock('test')],
- [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
- [],
- true,
- false,
- ],
- [
- 'test', true, true,
- [
- $this->getGroupMock('test'),
- $this->getGroupMock('test1'),
- ],
- [$this->getGroupMock('test1')],
- [],
- [['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
- false,
- false,
- ],
- [
- 'test', true, false,
- [
- $this->getGroupMock('test'),
- $this->getGroupMock('test1'),
- ],
- [$this->getGroupMock('test1')],
- [],
- [],
- true,
- false,
- ],
- [
- 'test', true, true,
- [
- $this->getGroupMock('test'),
- $this->getGroupMock('test1'),
- ],
- [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
- [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
- [['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
- false,
- false,
- ],
- [
- 'test', true, false,
- [
- $this->getGroupMock('test'),
- $this->getGroupMock('test1'),
- ],
- [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
- [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
- [],
- true,
- false,
- ],
- [
- 'test', true, true,
- [
- $this->getGroupMock('test0'),
- $this->getGroupMock('test1'),
- ],
- [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
- [],
- [
- ['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
- ['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
- ],
- false,
- null,
- ],
- [
- 'test', true, false,
- [
- $this->getGroupMock('test0'),
- $this->getGroupMock('test1'),
- ],
- [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
- [],
- [],
- true,
- null,
- ],
- [
- 'test', true, true,
- [
- $this->getGroupMock('test0'),
- $this->getGroupMock('test1'),
- ],
- [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
- [
- ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
- ],
- [
- ['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
- ['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
- ],
- false,
- $this->getGroupMock('test'),
- ],
- [
- 'test', true, false,
- [
- $this->getGroupMock('test0'),
- $this->getGroupMock('test1'),
- ],
- [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
- [
- ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
- ],
- [],
- true,
- $this->getGroupMock('test'),
- ],
- ];
- }
-
- /**
- * @dataProvider dataGetGroups
- *
- * @param string $searchTerm
- * @param bool $shareWithGroupOnly
- * @param bool $shareeEnumeration
- * @param array $groupResponse
- * @param array $userGroupsResponse
- * @param array $exactExpected
- * @param array $expected
- * @param bool $reachedEnd
- * @param mixed $singleGroup
- */
- public function testGetGroups($searchTerm, $shareWithGroupOnly, $shareeEnumeration, $groupResponse, $userGroupsResponse, $exactExpected, $expected, $reachedEnd, $singleGroup) {
- $this->invokePrivate($this->sharees, 'limit', [2]);
- $this->invokePrivate($this->sharees, 'offset', [0]);
- $this->invokePrivate($this->sharees, 'shareWithGroupOnly', [$shareWithGroupOnly]);
- $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]);
-
- $this->groupManager->expects($this->once())
- ->method('search')
- ->with($searchTerm, $this->invokePrivate($this->sharees, 'limit'), $this->invokePrivate($this->sharees, 'offset'))
- ->willReturn($groupResponse);
-
- if ($singleGroup !== false) {
- $this->groupManager->expects($this->once())
- ->method('get')
- ->with($searchTerm)
- ->willReturn($singleGroup);
- }
-
- if ($shareWithGroupOnly) {
- $user = $this->getUserMock('admin', 'Administrator');
- $this->session->expects($this->any())
- ->method('getUser')
- ->willReturn($user);
-
- $numGetUserGroupsCalls = empty($groupResponse) ? 0 : 1;
- $this->groupManager->expects($this->exactly($numGetUserGroupsCalls))
- ->method('getUserGroups')
- ->with($user)
- ->willReturn($userGroupsResponse);
- }
-
- $this->invokePrivate($this->sharees, 'getGroups', [$searchTerm]);
- $result = $this->invokePrivate($this->sharees, 'result');
-
- $this->assertEquals($exactExpected, $result['exact']['groups']);
- $this->assertEquals($expected, $result['groups']);
- $this->assertCount((int) $reachedEnd, $this->invokePrivate($this->sharees, 'reachedEndFor'));
- }
-
- /**
- * @dataProvider dataGetRemote
- *
- * @param string $searchTerm
- * @param array $contacts
- * @param bool $shareeEnumeration
- * @param array $expected
- * @param bool $reachedEnd
- */
- public function testGetRemote($searchTerm, $contacts, $shareeEnumeration, $expected, $reachedEnd) {
- $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]);
- $this->contactsManager->expects($this->any())
- ->method('search')
- ->with($searchTerm, ['CLOUD', 'FN'])
- ->willReturn($contacts);
-
- $result = $this->invokePrivate($this->sharees, 'getRemote', [$searchTerm]);
-
- $this->assertEquals($expected, $result);
- $this->assertCount((int) $reachedEnd, $this->invokePrivate($this->sharees, 'reachedEndFor'));
- }
-
- public function dataGetRemote() {
- return [
- ['test', [], true, ['results' => [], 'exact' => [], 'exactIdMatch' => false], true],
- ['test', [], false, ['results' => [], 'exact' => [], 'exactIdMatch' => false], true],
- [
- 'test@remote',
- [],
- true,
- ['results' => [], 'exact' => [['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']]], 'exactIdMatch' => false],
- true,
- ],
- [
- 'test@remote',
- [],
- false,
- ['results' => [], 'exact' => [['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']]], 'exactIdMatch' => false],
- true,
- ],
- [
- 'test',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'CLOUD' => [
- ],
- ],
- [
- 'FN' => 'User @ Localhost',
- 'CLOUD' => [
- 'username@localhost',
- ],
- ],
- ],
- true,
- ['results' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exact' => [], 'exactIdMatch' => false],
- true,
- ],
- [
- 'test',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'CLOUD' => [
- ],
- ],
- [
- 'FN' => 'User @ Localhost',
- 'CLOUD' => [
- 'username@localhost',
- ],
- ],
- ],
- false,
- ['results' => [], 'exact' => [], 'exactIdMatch' => false],
- true,
- ],
- [
- 'test@remote',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'CLOUD' => [
- ],
- ],
- [
- 'FN' => 'User @ Localhost',
- 'CLOUD' => [
- 'username@localhost',
- ],
- ],
- ],
- true,
- ['results' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exact' => [['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']]], 'exactIdMatch' => false],
- true,
- ],
- [
- 'test@remote',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'CLOUD' => [
- ],
- ],
- [
- 'FN' => 'User @ Localhost',
- 'CLOUD' => [
- 'username@localhost',
- ],
- ],
- ],
- false,
- ['results' => [], 'exact' => [['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']]], 'exactIdMatch' => false],
- true,
- ],
- [
- 'username@localhost',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'CLOUD' => [
- ],
- ],
- [
- 'FN' => 'User @ Localhost',
- 'CLOUD' => [
- 'username@localhost',
- ],
- ],
- ],
- true,
- ['results' => [], 'exact' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exactIdMatch' => true],
- true,
- ],
- [
- 'username@localhost',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'CLOUD' => [
- ],
- ],
- [
- 'FN' => 'User @ Localhost',
- 'CLOUD' => [
- 'username@localhost',
- ],
- ],
- ],
- false,
- ['results' => [], 'exact' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exactIdMatch' => true],
- true,
- ],
- // contact with space
- [
- 'user name@localhost',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'CLOUD' => [
- ],
- ],
- [
- 'FN' => 'User Name @ Localhost',
- 'CLOUD' => [
- 'user name@localhost',
- ],
- ],
- ],
- false,
- ['results' => [], 'exact' => [['label' => 'User Name @ Localhost (user name@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'user name@localhost', 'server' => 'localhost']]], 'exactIdMatch' => true],
- true,
- ],
- // remote with space, no contact
- [
- 'user space@remote',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'CLOUD' => [
- ],
- ],
- [
- 'FN' => 'User @ Localhost',
- 'CLOUD' => [
- 'username@localhost',
- ],
- ],
- ],
- false,
- ['results' => [], 'exact' => [['label' => 'user space@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'user space@remote']]], 'exactIdMatch' => false],
- true,
- ],
- ];
- }
-
- /**
- * @dataProvider dataGetEmail
- *
- * @param string $searchTerm
- * @param array $contacts
- * @param bool $shareeEnumeration
- * @param array $expected
- * @param bool $reachedEnd
- */
- public function testGetEmail($searchTerm, $contacts, $shareeEnumeration, $expected, $reachedEnd) {
- $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]);
- $this->contactsManager->expects($this->any())
- ->method('search')
- ->with($searchTerm, ['EMAIL', 'FN'])
- ->willReturn($contacts);
-
- $result = $this->invokePrivate($this->sharees, 'getEmail', [$searchTerm]);
-
- $this->assertEquals($expected, $result);
- $this->assertCount((int) $reachedEnd, $this->invokePrivate($this->sharees, 'reachedEndFor'));
- }
-
- public function dataGetEmail() {
- return [
- ['test', [], true, ['results' => [], 'exact' => [], 'exactIdMatch' => false], true],
- ['test', [], false, ['results' => [], 'exact' => [], 'exactIdMatch' => false], true],
- [
- 'test@remote.com',
- [],
- true,
- ['results' => [], 'exact' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]], 'exactIdMatch' => false],
- true,
- ],
- [ // no valid email address
- 'test@remote',
- [],
- true,
- ['results' => [], 'exact' => [], 'exactIdMatch' => false],
- true,
- ],
- [
- 'test@remote.com',
- [],
- false,
- ['results' => [], 'exact' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]], 'exactIdMatch' => false],
- true,
- ],
- [
- 'test',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'EMAIL' => [
- ],
- ],
- [
- 'FN' => 'User @ Localhost',
- 'EMAIL' => [
- 'username@localhost',
- ],
- ],
- ],
- true,
- ['results' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exact' => [], 'exactIdMatch' => false],
- true,
- ],
- [
- 'test',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'EMAIL' => [
- ],
- ],
- [
- 'FN' => 'User @ Localhost',
- 'EMAIL' => [
- 'username@localhost',
- ],
- ],
- ],
- false,
- ['results' => [], 'exact' => [], 'exactIdMatch' => false],
- true,
- ],
- [
- 'test@remote.com',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'EMAIL' => [
- ],
- ],
- [
- 'FN' => 'User @ Localhost',
- 'EMAIL' => [
- 'username@localhost',
- ],
- ],
- ],
- true,
- ['results' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exact' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]], 'exactIdMatch' => false],
- true,
- ],
- [
- 'test@remote.com',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'EMAIL' => [
- ],
- ],
- [
- 'FN' => 'User @ Localhost',
- 'EMAIL' => [
- 'username@localhost',
- ],
- ],
- ],
- false,
- ['results' => [], 'exact' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]], 'exactIdMatch' => false],
- true,
- ],
- [
- 'username@localhost',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'EMAIL' => [
- ],
- ],
- [
- 'FN' => 'User @ Localhost',
- 'EMAIL' => [
- 'username@localhost',
- ],
- ],
- ],
- true,
- ['results' => [], 'exact' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exactIdMatch' => true],
- true,
- ],
- [
- 'username@localhost',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'EMAIL' => [
- ],
- ],
- [
- 'FN' => 'User @ Localhost',
- 'EMAIL' => [
- 'username@localhost',
- ],
- ],
- ],
- false,
- ['results' => [], 'exact' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exactIdMatch' => true],
- true,
- ],
- // contact with space
- [
- 'user name@localhost',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'EMAIL' => [
- ],
- ],
- [
- 'FN' => 'User Name @ Localhost',
- 'EMAIL' => [
- 'user name@localhost',
- ],
- ],
- ],
- false,
- ['results' => [], 'exact' => [['label' => 'User Name @ Localhost (user name@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'user name@localhost']]], 'exactIdMatch' => true],
- true,
- ],
- // remote with space, no contact
- [
- 'user space@remote.com',
- [
- [
- 'FN' => 'User3 @ Localhost',
- ],
- [
- 'FN' => 'User2 @ Localhost',
- 'EMAIL' => [
- ],
- ],
- [
- 'FN' => 'User @ Localhost',
- 'EMAIL' => [
- 'username@localhost',
- ],
- ],
- ],
- false,
- ['results' => [], 'exact' => [], 'exactIdMatch' => false],
- true,
- ],
- // Local user found by email
- [
- 'test@example.com',
- [
- [
- 'FN' => 'User',
- 'EMAIL' => ['test@example.com'],
- 'CLOUD' => ['test@localhost'],
- 'isLocalSystemBook' => true,
- ]
- ],
- false,
- ['results' => [], 'exact' => [], 'exactIdMatch' => true],
- false,
- ]
- ];
- }
-
public function dataSearch() {
$noRemote = [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_EMAIL];
$allTypes = [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE, Share::SHARE_TYPE_EMAIL];
@@ -1424,14 +214,13 @@ class ShareesAPIControllerTest extends TestCase {
*/
public function testSearch($getData, $apiSetting, $enumSetting, $remoteSharingEnabled, $emailSharingEnabled, $shareTypes, $shareWithGroupOnly, $shareeEnumeration, $allowGroupSharing) {
$search = isset($getData['search']) ? $getData['search'] : '';
- $itemType = isset($getData['itemType']) ? $getData['itemType'] : null;
+ $itemType = isset($getData['itemType']) ? $getData['itemType'] : 'irrelevant';
$page = isset($getData['page']) ? $getData['page'] : 1;
$perPage = isset($getData['perPage']) ? $getData['perPage'] : 200;
$shareType = isset($getData['shareType']) ? $getData['shareType'] : null;
- $config = $this->getMockBuilder('OCP\IConfig')
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject $config */
+ $config = $this->createMock(IConfig::class);
$config->expects($this->exactly(2))
->method('getAppValue')
->with('core', $this->anything(), $this->anything())
@@ -1444,41 +233,29 @@ class ShareesAPIControllerTest extends TestCase {
->method('allowGroupSharing')
->willReturn($allowGroupSharing);
+ /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject $request */
+ $request = $this->createMock(IRequest::class);
+ /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject $urlGenerator */
+ $urlGenerator = $this->createMock(IURLGenerator::class);
+
/** @var \PHPUnit_Framework_MockObject_MockObject|\OCA\Files_Sharing\Controller\ShareesAPIController $sharees */
$sharees = $this->getMockBuilder('\OCA\Files_Sharing\Controller\ShareesAPIController')
->setConstructorArgs([
'files_sharing',
- $this->getMockBuilder('OCP\IRequest')->disableOriginalConstructor()->getMock(),
- $this->groupManager,
- $this->userManager,
- $this->contactsManager,
+ $request,
$config,
- $this->session,
- $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(),
- $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(),
+ $urlGenerator,
$this->shareManager,
- $this->clientService,
- $this->cloudIdManager
+ $this->collaboratorSearch
])
- ->setMethods(array('searchSharees', 'isRemoteSharingAllowed', 'shareProviderExists'))
+ ->setMethods(['isRemoteSharingAllowed', 'shareProviderExists'])
->getMock();
- $sharees->expects($this->once())
- ->method('searchSharees')
- ->willReturnCallback(function
- ($isearch, $iitemType, $ishareTypes, $ipage, $iperPage)
- use ($search, $itemType, $shareTypes, $page, $perPage) {
- // We are doing strict comparisons here, so we can differ 0/'' and null on shareType/itemType
- $this->assertSame($search, $isearch);
- $this->assertSame($itemType, $iitemType);
- $this->assertSame(count($shareTypes), count($ishareTypes));
- foreach($shareTypes as $expected) {
- $this->assertTrue(in_array($expected, $ishareTypes));
- }
- $this->assertSame($page, $ipage);
- $this->assertSame($perPage, $iperPage);
- return new Http\DataResponse();
- });
+ $this->collaboratorSearch->expects($this->once())
+ ->method('search')
+ ->with($search, $shareTypes, $this->anything(), $perPage, $perPage * ($page -1))
+ ->willReturn([[], false]);
+
$sharees->expects($this->any())
->method('isRemoteSharingAllowed')
->with($itemType)
@@ -1531,35 +308,34 @@ class ShareesAPIControllerTest extends TestCase {
$page = isset($getData['page']) ? $getData['page'] : 1;
$perPage = isset($getData['perPage']) ? $getData['perPage'] : 200;
- $config = $this->getMockBuilder('OCP\IConfig')
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject $config */
+ $config = $this->createMock(IConfig::class);
$config->expects($this->never())
->method('getAppValue');
+ /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject $request */
+ $request = $this->createMock(IRequest::class);
+ /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject $urlGenerator */
+ $urlGenerator = $this->createMock(IURLGenerator::class);
+
/** @var \PHPUnit_Framework_MockObject_MockObject|\OCA\Files_Sharing\Controller\ShareesAPIController $sharees */
$sharees = $this->getMockBuilder('\OCA\Files_Sharing\Controller\ShareesAPIController')
->setConstructorArgs([
'files_sharing',
- $this->getMockBuilder('OCP\IRequest')->disableOriginalConstructor()->getMock(),
- $this->groupManager,
- $this->userManager,
- $this->contactsManager,
+ $request,
$config,
- $this->session,
- $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(),
- $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(),
+ $urlGenerator,
$this->shareManager,
- $this->clientService,
- $this->cloudIdManager
+ $this->collaboratorSearch
])
- ->setMethods(array('searchSharees', 'isRemoteSharingAllowed'))
+ ->setMethods(['isRemoteSharingAllowed'])
->getMock();
$sharees->expects($this->never())
- ->method('searchSharees');
- $sharees->expects($this->never())
->method('isRemoteSharingAllowed');
+ $this->collaboratorSearch->expects($this->never())
+ ->method('search');
+
try {
$sharees->search('', null, $page, $perPage, null);
$this->fail();
@@ -1587,188 +363,12 @@ class ShareesAPIControllerTest extends TestCase {
$this->assertSame($expected, $this->invokePrivate($this->sharees, 'isRemoteSharingAllowed', [$itemType]));
}
- public function dataSearchSharees() {
- return [
- ['test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE], 1, 2, false, [], [], ['results' => [], 'exact' => [], 'exactIdMatch' => false],
- [
- 'exact' => ['users' => [], 'groups' => [], 'remotes' => [], 'circles' => [], 'emails' => []],
- 'users' => [],
- 'groups' => [],
- 'remotes' => [],
- 'emails' => [],
- 'circles' => [],
- 'lookup' => [],
- ], false],
- ['test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE], 1, 2, false, [], [], ['results' => [], 'exact' => [], 'exactIdMatch' => false],
- [
- 'exact' => ['users' => [], 'groups' => [], 'remotes' => [], 'circles' => [], 'emails' => []],
- 'users' => [],
- 'groups' => [],
- 'remotes' => [],
- 'emails' => [],
- 'circles' => [],
- 'lookup' => [],
- ], false],
- [
- 'test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE], 1, 2, false, [
- ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
- ], [
- ['label' => 'testgroup1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'testgroup1']],
- ], [
- 'results' => [['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']]], 'exact' => [], 'exactIdMatch' => false,
- ],
- [
- 'exact' => ['users' => [], 'groups' => [], 'remotes' => [], 'circles' => [], 'emails' => []],
- 'users' => [
- ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
- ],
- 'groups' => [
- ['label' => 'testgroup1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'testgroup1']],
- ],
- 'remotes' => [
- ['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']],
- ],
- 'emails' => [],
- 'circles' => [],
- 'lookup' => [],
- ], true,
- ],
- // No groups requested
- [
- 'test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_REMOTE], 1, 2, false, [
- ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
- ], null, [
- 'results' => [['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']]], 'exact' => [], 'exactIdMatch' => false
- ],
- [
- 'exact' => ['users' => [], 'groups' => [], 'remotes' => [], 'circles' => [], 'emails' => []],
- 'users' => [
- ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
- ],
- 'groups' => [],
- 'remotes' => [
- ['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']],
- ],
- 'emails' => [],
- 'circles' => [],
- 'lookup' => [],
- ], false,
- ],
- // Share type restricted to user - Only one user
- [
- 'test', 'folder', [Share::SHARE_TYPE_USER], 1, 2, false, [
- ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
- ], null, null,
- [
- 'exact' => ['users' => [], 'groups' => [], 'remotes' => [], 'circles' => [], 'emails' => []],
- 'users' => [
- ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
- ],
- 'groups' => [],
- 'remotes' => [],
- 'emails' => [],
- 'circles' => [],
- 'lookup' => [],
- ], false,
- ],
- // Share type restricted to user - Multipage result
- [
- 'test', 'folder', [Share::SHARE_TYPE_USER], 1, 2, false, [
- ['label' => 'test 1', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
- ['label' => 'test 2', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
- ], null, null,
- [
- 'exact' => ['users' => [], 'groups' => [], 'remotes' => [], 'circles' => [], 'emails' => []],
- 'users' => [
- ['label' => 'test 1', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
- ['label' => 'test 2', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
- ],
- 'groups' => [],
- 'remotes' => [],
- 'emails' => [],
- 'circles' => [],
- 'lookup' => [],
- ], true,
- ],
- ];
- }
-
- /**
- * @dataProvider dataSearchSharees
- *
- * @param string $searchTerm
- * @param string $itemType
- * @param array $shareTypes
- * @param int $page
- * @param int $perPage
- * @param bool $shareWithGroupOnly
- * @param array $mockedUserResult
- * @param array $mockedGroupsResult
- * @param array $mockedRemotesResult
- * @param array $expected
- * @param bool $nextLink
- */
- public function testSearchSharees($searchTerm, $itemType, array $shareTypes, $page, $perPage, $shareWithGroupOnly,
- $mockedUserResult, $mockedGroupsResult, $mockedRemotesResult, $expected, $nextLink) {
- /** @var \PHPUnit_Framework_MockObject_MockObject|\OCA\Files_Sharing\Controller\ShareesAPIController $sharees */
- $sharees = $this->getMockBuilder('\OCA\Files_Sharing\Controller\ShareesAPIController')
- ->setConstructorArgs([
- 'files_sharing',
- $this->getMockBuilder('OCP\IRequest')->disableOriginalConstructor()->getMock(),
- $this->groupManager,
- $this->userManager,
- $this->contactsManager,
- $this->getMockBuilder('OCP\IConfig')->disableOriginalConstructor()->getMock(),
- $this->session,
- $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(),
- $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(),
- $this->shareManager,
- $this->clientService,
- $this->cloudIdManager
- ])
- ->setMethods(array('getShareesForShareIds', 'getUsers', 'getGroups', 'getRemote'))
- ->getMock();
- $sharees->expects(($mockedUserResult === null) ? $this->never() : $this->once())
- ->method('getUsers')
- ->with($searchTerm)
- ->willReturnCallback(function() use ($sharees, $mockedUserResult) {
- $result = $this->invokePrivate($sharees, 'result');
- $result['users'] = $mockedUserResult;
- $this->invokePrivate($sharees, 'result', [$result]);
- });
- $sharees->expects(($mockedGroupsResult === null) ? $this->never() : $this->once())
- ->method('getGroups')
- ->with($searchTerm)
- ->willReturnCallback(function() use ($sharees, $mockedGroupsResult) {
- $result = $this->invokePrivate($sharees, 'result');
- $result['groups'] = $mockedGroupsResult;
- $this->invokePrivate($sharees, 'result', [$result]);
- });
-
- $sharees->expects(($mockedRemotesResult === null) ? $this->never() : $this->once())
- ->method('getRemote')
- ->with($searchTerm)
- ->willReturn($mockedRemotesResult);
-
- $ocs = $this->invokePrivate($sharees, 'searchSharees', [$searchTerm, $itemType, $shareTypes, $page, $perPage, $shareWithGroupOnly]);
- $this->assertInstanceOf('\OCP\AppFramework\Http\DataResponse', $ocs);
- $this->assertEquals($expected, $ocs->getData());
-
- // Check if next link is set
- if ($nextLink) {
- $headers = $ocs->getHeaders();
- $this->assertArrayHasKey('Link', $headers);
- $this->assertStringStartsWith('<', $headers['Link']);
- $this->assertStringEndsWith('>; rel="next"', $headers['Link']);
- }
- }
-
/**
* @expectedException \OCP\AppFramework\OCS\OCSBadRequestException
* @expectedExceptionMessage Missing itemType
*/
- public function testSearchShareesNoItemType() {
- $this->invokePrivate($this->sharees, 'searchSharees', ['', null, [], [], 0, 0, false]);
+ public function testSearchNoItemType() {
+ $this->sharees->search('', null, 1, 10, [], false);
}
public function dataGetPaginationLink() {
@@ -1814,97 +414,4 @@ class ShareesAPIControllerTest extends TestCase {
$this->assertEquals($expected, $this->invokePrivate($this->sharees, 'isV2'));
}
-
- /**
- * @dataProvider dataTestSplitUserRemote
- *
- * @param string $remote
- * @param string $expectedUser
- * @param string $expectedUrl
- */
- public function testSplitUserRemote($remote, $expectedUser, $expectedUrl) {
- list($remoteUser, $remoteUrl) = $this->sharees->splitUserRemote($remote);
- $this->assertSame($expectedUser, $remoteUser);
- $this->assertSame($expectedUrl, $remoteUrl);
- }
-
- public function dataTestSplitUserRemote() {
- $userPrefix = ['user@name', 'username'];
- $protocols = ['', 'http://', 'https://'];
- $remotes = [
- 'localhost',
- 'local.host',
- 'dev.local.host',
- 'dev.local.host/path',
- 'dev.local.host/at@inpath',
- '127.0.0.1',
- '::1',
- '::192.0.2.128',
- '::192.0.2.128/at@inpath',
- ];
-
- $testCases = [];
- foreach ($userPrefix as $user) {
- foreach ($remotes as $remote) {
- foreach ($protocols as $protocol) {
- $baseUrl = $user . '@' . $protocol . $remote;
-
- $testCases[] = [$baseUrl, $user, $protocol . $remote];
- $testCases[] = [$baseUrl . '/', $user, $protocol . $remote];
- $testCases[] = [$baseUrl . '/index.php', $user, $protocol . $remote];
- $testCases[] = [$baseUrl . '/index.php/s/token', $user, $protocol . $remote];
- }
- }
- }
- return $testCases;
- }
-
- public function dataTestSplitUserRemoteError() {
- return array(
- // Invalid path
- array('user@'),
-
- // Invalid user
- array('@server'),
- array('us/er@server'),
- array('us:er@server'),
-
- // Invalid splitting
- array('user'),
- array(''),
- array('us/erserver'),
- array('us:erserver'),
- );
- }
-
- /**
- * @dataProvider dataTestSplitUserRemoteError
- *
- * @param string $id
- * @expectedException \Exception
- */
- public function testSplitUserRemoteError($id) {
- $this->sharees->splitUserRemote($id);
- }
-
- /**
- * @dataProvider dataTestFixRemoteUrl
- *
- * @param string $url
- * @param string $expected
- */
- public function testFixRemoteUrl($url, $expected) {
- $this->assertSame($expected,
- $this->invokePrivate($this->sharees, 'fixRemoteURL', [$url])
- );
- }
-
- public function dataTestFixRemoteUrl() {
- return [
- ['http://localhost', 'http://localhost'],
- ['http://localhost/', 'http://localhost'],
- ['http://localhost/index.php', 'http://localhost'],
- ['http://localhost/index.php/s/AShareToken', 'http://localhost'],
- ];
- }
}
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 50bd6d33274..9341bd1a762 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -68,6 +68,10 @@ return array(
'OCP\\BackgroundJob\\IJobList' => $baseDir . '/lib/public/BackgroundJob/IJobList.php',
'OCP\\Capabilities\\ICapability' => $baseDir . '/lib/public/Capabilities/ICapability.php',
'OCP\\Capabilities\\IPublicCapability' => $baseDir . '/lib/public/Capabilities/IPublicCapability.php',
+ 'OCP\\Collaboration\\Collaborators\\ISearch' => $baseDir . '/lib/public/Collaboration/Collaborators/ISearch.php',
+ 'OCP\\Collaboration\\Collaborators\\ISearchPlugin' => $baseDir . '/lib/public/Collaboration/Collaborators/ISearchPlugin.php',
+ 'OCP\\Collaboration\\Collaborators\\ISearchResult' => $baseDir . '/lib/public/Collaboration/Collaborators/ISearchResult.php',
+ 'OCP\\Collaboration\\Collaborators\\SearchResultType' => $baseDir . '/lib/public/Collaboration/Collaborators/SearchResultType.php',
'OCP\\Command\\IBus' => $baseDir . '/lib/public/Command/IBus.php',
'OCP\\Command\\ICommand' => $baseDir . '/lib/public/Command/ICommand.php',
'OCP\\Comments\\CommentsEntityEvent' => $baseDir . '/lib/public/Comments/CommentsEntityEvent.php',
@@ -384,6 +388,13 @@ return array(
'OC\\Cache\\CappedMemoryCache' => $baseDir . '/lib/private/Cache/CappedMemoryCache.php',
'OC\\Cache\\File' => $baseDir . '/lib/private/Cache/File.php',
'OC\\CapabilitiesManager' => $baseDir . '/lib/private/CapabilitiesManager.php',
+ 'OC\\Collaboration\\Collaborators\\GroupPlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/GroupPlugin.php',
+ 'OC\\Collaboration\\Collaborators\\LookupPlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/LookupPlugin.php',
+ 'OC\\Collaboration\\Collaborators\\MailPlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/MailPlugin.php',
+ 'OC\\Collaboration\\Collaborators\\RemotePlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/RemotePlugin.php',
+ 'OC\\Collaboration\\Collaborators\\Search' => $baseDir . '/lib/private/Collaboration/Collaborators/Search.php',
+ 'OC\\Collaboration\\Collaborators\\SearchResult' => $baseDir . '/lib/private/Collaboration/Collaborators/SearchResult.php',
+ 'OC\\Collaboration\\Collaborators\\UserPlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/UserPlugin.php',
'OC\\Command\\AsyncBus' => $baseDir . '/lib/private/Command/AsyncBus.php',
'OC\\Command\\CallableJob' => $baseDir . '/lib/private/Command/CallableJob.php',
'OC\\Command\\ClosureJob' => $baseDir . '/lib/private/Command/ClosureJob.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 1828957b32a..5715ff6ed05 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -98,6 +98,10 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\BackgroundJob\\IJobList' => __DIR__ . '/../../..' . '/lib/public/BackgroundJob/IJobList.php',
'OCP\\Capabilities\\ICapability' => __DIR__ . '/../../..' . '/lib/public/Capabilities/ICapability.php',
'OCP\\Capabilities\\IPublicCapability' => __DIR__ . '/../../..' . '/lib/public/Capabilities/IPublicCapability.php',
+ 'OCP\\Collaboration\\Collaborators\\ISearch' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/ISearch.php',
+ 'OCP\\Collaboration\\Collaborators\\ISearchPlugin' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/ISearchPlugin.php',
+ 'OCP\\Collaboration\\Collaborators\\ISearchResult' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/ISearchResult.php',
+ 'OCP\\Collaboration\\Collaborators\\SearchResultType' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/SearchResultType.php',
'OCP\\Command\\IBus' => __DIR__ . '/../../..' . '/lib/public/Command/IBus.php',
'OCP\\Command\\ICommand' => __DIR__ . '/../../..' . '/lib/public/Command/ICommand.php',
'OCP\\Comments\\CommentsEntityEvent' => __DIR__ . '/../../..' . '/lib/public/Comments/CommentsEntityEvent.php',
@@ -414,6 +418,13 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Cache\\CappedMemoryCache' => __DIR__ . '/../../..' . '/lib/private/Cache/CappedMemoryCache.php',
'OC\\Cache\\File' => __DIR__ . '/../../..' . '/lib/private/Cache/File.php',
'OC\\CapabilitiesManager' => __DIR__ . '/../../..' . '/lib/private/CapabilitiesManager.php',
+ 'OC\\Collaboration\\Collaborators\\GroupPlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/GroupPlugin.php',
+ 'OC\\Collaboration\\Collaborators\\LookupPlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/LookupPlugin.php',
+ 'OC\\Collaboration\\Collaborators\\MailPlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/MailPlugin.php',
+ 'OC\\Collaboration\\Collaborators\\RemotePlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/RemotePlugin.php',
+ 'OC\\Collaboration\\Collaborators\\Search' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/Search.php',
+ 'OC\\Collaboration\\Collaborators\\SearchResult' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/SearchResult.php',
+ 'OC\\Collaboration\\Collaborators\\UserPlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/UserPlugin.php',
'OC\\Command\\AsyncBus' => __DIR__ . '/../../..' . '/lib/private/Command/AsyncBus.php',
'OC\\Command\\CallableJob' => __DIR__ . '/../../..' . '/lib/private/Command/CallableJob.php',
'OC\\Command\\ClosureJob' => __DIR__ . '/../../..' . '/lib/private/Command/ClosureJob.php',
diff --git a/lib/private/App/InfoParser.php b/lib/private/App/InfoParser.php
index fef8ab7a1e8..0531682d67a 100644
--- a/lib/private/App/InfoParser.php
+++ b/lib/private/App/InfoParser.php
@@ -165,6 +165,12 @@ class InfoParser {
if (isset($array['activity']['providers']['provider']) && is_array($array['activity']['providers']['provider'])) {
$array['activity']['providers'] = $array['activity']['providers']['provider'];
}
+ if (isset($array['collaboration']['collaborators']['searchPlugins']['searchPlugin'])
+ && is_array($array['collaboration']['collaborators']['searchPlugins']['searchPlugin'])
+ && !isset($array['collaboration']['collaborators']['searchPlugins']['searchPlugin']['class'])
+ ) {
+ $array['collaboration']['collaborators']['searchPlugins'] = $array['collaboration']['collaborators']['searchPlugins']['searchPlugin'];
+ }
if(!is_null($this->cache)) {
$this->cache->set($fileCacheKey, json_encode($array));
diff --git a/lib/private/Collaboration/Collaborators/GroupPlugin.php b/lib/private/Collaboration/Collaborators/GroupPlugin.php
new file mode 100644
index 00000000000..0b2b3d71028
--- /dev/null
+++ b/lib/private/Collaboration/Collaborators/GroupPlugin.php
@@ -0,0 +1,124 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace OC\Collaboration\Collaborators;
+
+use OCP\Collaboration\Collaborators\ISearchPlugin;
+use OCP\Collaboration\Collaborators\ISearchResult;
+use OCP\Collaboration\Collaborators\SearchResultType;
+use OCP\IConfig;
+use OCP\IGroup;
+use OCP\IGroupManager;
+use OCP\IUserSession;
+use OCP\Share;
+
+class GroupPlugin implements ISearchPlugin {
+ protected $shareeEnumeration;
+ protected $shareWithGroupOnly;
+
+ /** @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;
+
+ $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';
+ }
+
+ public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ $hasMoreResults = false;
+ $result = ['wide' => [], 'exact' => []];
+
+ $groups = $this->groupManager->search($search, $limit, $offset);
+ $groupIds = array_map(function (IGroup $group) { return $group->getGID(); }, $groups);
+
+ if (!$this->shareeEnumeration || sizeof($groups) < $limit) {
+ $hasMoreResults = true;
+ }
+
+ $userGroups = [];
+ if (!empty($groups) && $this->shareWithGroupOnly) {
+ // Intersect all the groups that match with the groups this user is a member of
+ $userGroups = $this->groupManager->getUserGroups($this->userSession->getUser());
+ $userGroups = array_map(function (IGroup $group) { return $group->getGID(); }, $userGroups);
+ $groupIds = array_intersect($groupIds, $userGroups);
+ }
+
+ $lowerSearch = strtolower($search);
+ foreach ($groups as $group) {
+ // FIXME: use a more efficient approach
+ $gid = $group->getGID();
+ if (!in_array($gid, $groupIds)) {
+ continue;
+ }
+ if (strtolower($gid) === $lowerSearch || strtolower($group->getDisplayName()) === $lowerSearch) {
+ $result['exact'][] = [
+ 'label' => $group->getDisplayName(),
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_GROUP,
+ 'shareWith' => $gid,
+ ],
+ ];
+ } else {
+ $result['wide'][] = [
+ 'label' => $group->getDisplayName(),
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_GROUP,
+ 'shareWith' => $gid,
+ ],
+ ];
+ }
+ }
+
+ if ($offset === 0 && empty($result['exact'])) {
+ // On page one we try if the search result has a direct hit on the
+ // user id and if so, we add that to the exact match list
+ $group = $this->groupManager->get($search);
+ if ($group instanceof IGroup && (!$this->shareWithGroupOnly || in_array($group->getGID(), $userGroups))) {
+ array_push($result['exact'], [
+ 'label' => $group->getDisplayName(),
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_GROUP,
+ 'shareWith' => $group->getGID(),
+ ],
+ ]);
+ }
+ }
+
+ if (!$this->shareeEnumeration) {
+ $result['wide'] = [];
+ }
+
+ $type = new SearchResultType('groups');
+ $searchResult->addResultSet($type, $result['wide'], $result['exact']);
+
+ return $hasMoreResults;
+ }
+}
diff --git a/lib/private/Collaboration/Collaborators/LookupPlugin.php b/lib/private/Collaboration/Collaborators/LookupPlugin.php
new file mode 100644
index 00000000000..3a6a0943772
--- /dev/null
+++ b/lib/private/Collaboration/Collaborators/LookupPlugin.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace OC\Collaboration\Collaborators;
+
+
+use OCP\Collaboration\Collaborators\ISearchPlugin;
+use OCP\Collaboration\Collaborators\ISearchResult;
+use OCP\Collaboration\Collaborators\SearchResultType;
+use OCP\Http\Client\IClientService;
+use OCP\IConfig;
+use OCP\Share;
+
+class LookupPlugin implements ISearchPlugin {
+
+ /** @var IConfig */
+ private $config;
+ /** @var IClientService */
+ private $clientService;
+
+ public function __construct(IConfig $config, IClientService $clientService) {
+ $this->config = $config;
+ $this->clientService = $clientService;
+ }
+
+ public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ if ($this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no') !== 'yes') {
+ return false;
+ }
+
+ $lookupServerUrl = $this->config->getSystemValue('lookup_server', 'https://lookup.nextcloud.com');
+ $lookupServerUrl = rtrim($lookupServerUrl, '/');
+ $result = [];
+
+ try {
+ $client = $this->clientService->newClient();
+ $response = $client->get(
+ $lookupServerUrl . '/users?search=' . urlencode($search),
+ [
+ 'timeout' => 10,
+ 'connect_timeout' => 3,
+ ]
+ );
+
+ $body = json_decode($response->getBody(), true);
+
+ foreach ($body as $lookup) {
+ $result[] = [
+ 'label' => $lookup['federationId'],
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_REMOTE,
+ 'shareWith' => $lookup['federationId'],
+ ],
+ 'extra' => $lookup,
+ ];
+ }
+ } catch (\Exception $e) {
+ }
+
+ $type = new SearchResultType('lookup');
+ $searchResult->addResultSet($type, $result, []);
+
+ return false;
+ }
+}
diff --git a/lib/private/Collaboration/Collaborators/MailPlugin.php b/lib/private/Collaboration/Collaborators/MailPlugin.php
new file mode 100644
index 00000000000..d28bd3692a4
--- /dev/null
+++ b/lib/private/Collaboration/Collaborators/MailPlugin.php
@@ -0,0 +1,164 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace OC\Collaboration\Collaborators;
+
+
+use OCP\Collaboration\Collaborators\ISearchPlugin;
+use OCP\Collaboration\Collaborators\ISearchResult;
+use OCP\Collaboration\Collaborators\SearchResultType;
+use OCP\Contacts\IManager;
+use OCP\Federation\ICloudIdManager;
+use OCP\IConfig;
+use OCP\Share;
+
+class MailPlugin implements ISearchPlugin {
+ protected $shareeEnumeration;
+
+ /** @var IManager */
+ private $contactsManager;
+ /** @var ICloudIdManager */
+ private $cloudIdManager;
+ /** @var IConfig */
+ private $config;
+
+ public function __construct(IManager $contactsManager, ICloudIdManager $cloudIdManager, IConfig $config) {
+ $this->contactsManager = $contactsManager;
+ $this->cloudIdManager = $cloudIdManager;
+ $this->config = $config;
+
+ $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
+ }
+
+ /**
+ * @param $search
+ * @param $limit
+ * @param $offset
+ * @param ISearchResult $searchResult
+ * @return bool
+ * @since 13.0.0
+ */
+ public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ $result = ['wide' => [], 'exact' => []];
+ $userType = new SearchResultType('users');
+ $emailType = new SearchResultType('emails');
+
+ // Search in contacts
+ //@todo Pagination missing
+ $addressBookContacts = $this->contactsManager->search($search, ['EMAIL', 'FN']);
+ $lowerSearch = strtolower($search);
+ foreach ($addressBookContacts as $contact) {
+ if (isset($contact['EMAIL'])) {
+ $emailAddresses = $contact['EMAIL'];
+ if (!is_array($emailAddresses)) {
+ $emailAddresses = [$emailAddresses];
+ }
+ foreach ($emailAddresses as $emailAddress) {
+ $exactEmailMatch = strtolower($emailAddress) === $lowerSearch;
+
+ if (isset($contact['isLocalSystemBook'])) {
+ if ($exactEmailMatch) {
+ try {
+ $cloud = $this->cloudIdManager->resolveCloudId($contact['CLOUD'][0]);
+ } catch (\InvalidArgumentException $e) {
+ continue;
+ }
+
+ if (!$searchResult->hasResult($userType, $cloud->getUser())) {
+ $singleResult = [[
+ 'label' => $contact['FN'] . " ($emailAddress)",
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_USER,
+ 'shareWith' => $cloud->getUser(),
+ ],
+ ]];
+ $searchResult->addResultSet($userType, [], $singleResult);
+ $searchResult->markExactIdMatch($emailType);
+ }
+ return false;
+ }
+
+ if ($this->shareeEnumeration) {
+ try {
+ $cloud = $this->cloudIdManager->resolveCloudId($contact['CLOUD'][0]);
+ } catch (\InvalidArgumentException $e) {
+ continue;
+ }
+
+ if (!$searchResult->hasResult($userType, $cloud->getUser())) {
+ $singleResult = [[
+ 'label' => $contact['FN'] . " ($emailAddress)",
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_USER,
+ 'shareWith' => $cloud->getUser(),
+ ]],
+ ];
+ $searchResult->addResultSet($userType, $singleResult, []);
+ }
+ }
+ continue;
+ }
+
+ if ($exactEmailMatch || strtolower($contact['FN']) === $lowerSearch) {
+ if ($exactEmailMatch) {
+ $searchResult->markExactIdMatch($emailType);
+ }
+ $result['exact'][] = [
+ 'label' => $contact['FN'] . " ($emailAddress)",
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_EMAIL,
+ 'shareWith' => $emailAddress,
+ ],
+ ];
+ } else {
+ $result['wide'][] = [
+ 'label' => $contact['FN'] . " ($emailAddress)",
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_EMAIL,
+ 'shareWith' => $emailAddress,
+ ],
+ ];
+ }
+ }
+ }
+ }
+
+ if (!$this->shareeEnumeration) {
+ $result['wide'] = [];
+ }
+
+ if (!$searchResult->hasExactIdMatch($emailType) && filter_var($search, FILTER_VALIDATE_EMAIL)) {
+ $result['exact'][] = [
+ 'label' => $search,
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_EMAIL,
+ 'shareWith' => $search,
+ ],
+ ];
+ }
+
+ $searchResult->addResultSet($emailType, $result['wide'], $result['exact']);
+
+ return true;
+ }
+}
diff --git a/lib/private/Collaboration/Collaborators/RemotePlugin.php b/lib/private/Collaboration/Collaborators/RemotePlugin.php
new file mode 100644
index 00000000000..b17a64e4ff1
--- /dev/null
+++ b/lib/private/Collaboration/Collaborators/RemotePlugin.php
@@ -0,0 +1,137 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace OC\Collaboration\Collaborators;
+
+
+use OCP\Collaboration\Collaborators\ISearchPlugin;
+use OCP\Collaboration\Collaborators\ISearchResult;
+use OCP\Collaboration\Collaborators\SearchResultType;
+use OCP\Contacts\IManager;
+use OCP\Federation\ICloudIdManager;
+use OCP\IConfig;
+use OCP\Share;
+
+class RemotePlugin implements ISearchPlugin {
+ protected $shareeEnumeration;
+
+ /** @var IManager */
+ private $contactsManager;
+ /** @var ICloudIdManager */
+ private $cloudIdManager;
+ /** @var IConfig */
+ private $config;
+
+ public function __construct(IManager $contactsManager, ICloudIdManager $cloudIdManager, IConfig $config) {
+ $this->contactsManager = $contactsManager;
+ $this->cloudIdManager = $cloudIdManager;
+ $this->config = $config;
+
+ $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
+ }
+
+ public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ $result = ['wide' => [], 'exact' => []];
+ $resultType = new SearchResultType('remotes');
+
+ // Search in contacts
+ //@todo Pagination missing
+ $addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN']);
+ foreach ($addressBookContacts as $contact) {
+ if (isset($contact['isLocalSystemBook'])) {
+ continue;
+ }
+ if (isset($contact['CLOUD'])) {
+ $cloudIds = $contact['CLOUD'];
+ if (!is_array($cloudIds)) {
+ $cloudIds = [$cloudIds];
+ }
+ $lowerSearch = strtolower($search);
+ foreach ($cloudIds as $cloudId) {
+ try {
+ list(, $serverUrl) = $this->splitUserRemote($cloudId);
+ } catch (\InvalidArgumentException $e) {
+ continue;
+ }
+
+ if (strtolower($contact['FN']) === $lowerSearch || strtolower($cloudId) === $lowerSearch) {
+ if (strtolower($cloudId) === $lowerSearch) {
+ $searchResult->markExactIdMatch($resultType);
+ }
+ $result['exact'][] = [
+ 'label' => $contact['FN'] . " ($cloudId)",
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_REMOTE,
+ 'shareWith' => $cloudId,
+ 'server' => $serverUrl,
+ ],
+ ];
+ } else {
+ $result['wide'][] = [
+ 'label' => $contact['FN'] . " ($cloudId)",
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_REMOTE,
+ 'shareWith' => $cloudId,
+ 'server' => $serverUrl,
+ ],
+ ];
+ }
+ }
+ }
+ }
+
+ if (!$this->shareeEnumeration) {
+ $result['wide'] = [];
+ }
+
+ if (!$searchResult->hasExactIdMatch($resultType) && $this->cloudIdManager->isValidCloudId($search) && $offset === 0) {
+ $result['exact'][] = [
+ 'label' => $search,
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_REMOTE,
+ 'shareWith' => $search,
+ ],
+ ];
+ }
+
+ $searchResult->addResultSet($resultType, $result['wide'], $result['exact']);
+
+ return true;
+ }
+
+ /**
+ * split user and remote from federated cloud id
+ *
+ * @param string $address federated share address
+ * @return array [user, remoteURL]
+ * @throws \InvalidArgumentException
+ */
+ public function splitUserRemote($address) {
+ try {
+ $cloudId = $this->cloudIdManager->resolveCloudId($address);
+ return [$cloudId->getUser(), $cloudId->getRemote()];
+ } 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
new file mode 100644
index 00000000000..e9b15dd1201
--- /dev/null
+++ b/lib/private/Collaboration/Collaborators/Search.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace OC\Collaboration\Collaborators;
+
+use OCP\Collaboration\Collaborators\ISearch;
+use OCP\Collaboration\Collaborators\ISearchPlugin;
+use OCP\Collaboration\Collaborators\ISearchResult;
+use OCP\Collaboration\Collaborators\SearchResultType;
+use OCP\IContainer;
+use OCP\Share;
+
+class Search implements ISearch {
+ /** @var IContainer */
+ private $c;
+
+ protected $pluginList = [];
+
+ public function __construct(IContainer $c) {
+ $this->c = $c;
+ }
+
+ public function search($search, array $shareTypes, $lookup, $limit, $offset) {
+ $hasMoreResults = false;
+
+ /** @var ISearchResult $searchResult */
+ $searchResult = $this->c->resolve(SearchResult::class);
+
+ foreach ($shareTypes as $type) {
+ if(!isset($this->pluginList[$type])) {
+ continue;
+ }
+ foreach ($this->pluginList[$type] as $plugin) {
+ /** @var ISearchPlugin $searchPlugin */
+ $searchPlugin = $this->c->resolve($plugin);
+ $hasMoreResults |= $searchPlugin->search($search, $limit, $offset, $searchResult);
+ }
+ }
+
+ // Get from lookup server, not a separate share type
+ if ($lookup) {
+ $searchPlugin = $this->c->resolve(LookupPlugin::class);
+ $hasMoreResults |= $searchPlugin->search($search, $limit, $offset, $searchResult);
+ }
+
+ // sanitizing, could go into the plugins as well
+
+ // if we have a exact match, either for the federated cloud id or for the
+ // email address we only return the exact match. It is highly unlikely
+ // that the exact same email address and federated cloud id exists
+ $emailType = new SearchResultType('emails');
+ $remoteType = new SearchResultType('remotes');
+ if($searchResult->hasExactIdMatch($emailType) && !$searchResult->hasExactIdMatch($remoteType)) {
+ $searchResult->unsetResult($remoteType);
+ } elseif (!$searchResult->hasExactIdMatch($emailType) && $searchResult->hasExactIdMatch($remoteType)) {
+ $searchResult->unsetResult($emailType);
+ }
+
+ return [$searchResult->asArray(), (bool)$hasMoreResults];
+ }
+
+ public function registerPlugin(array $pluginInfo) {
+ $shareType = constant(Share::class . '::' . $pluginInfo['shareType']);
+ if($shareType === null) {
+ throw new \InvalidArgumentException('Provided ShareType is invalid');
+ }
+ $this->pluginList[$shareType][] = $pluginInfo['class'];
+ }
+}
diff --git a/lib/private/Collaboration/Collaborators/SearchResult.php b/lib/private/Collaboration/Collaborators/SearchResult.php
new file mode 100644
index 00000000000..7b32b388203
--- /dev/null
+++ b/lib/private/Collaboration/Collaborators/SearchResult.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace OC\Collaboration\Collaborators;
+
+
+use OCP\Collaboration\Collaborators\ISearchResult;
+use OCP\Collaboration\Collaborators\SearchResultType;
+
+class SearchResult implements ISearchResult {
+
+ protected $result = [
+ 'exact' => [],
+ ];
+
+ protected $exactIdMatches = [];
+
+ public function addResultSet(SearchResultType $type, array $matches, array $exactMatches = null) {
+ $type = $type->getLabel();
+ if(!isset($this->result[$type])) {
+ $this->result[$type] = [];
+ $this->result['exact'][$type] = [];
+ }
+
+ $this->result[$type] = array_merge($this->result[$type], $matches);
+ if(is_array($exactMatches)) {
+ $this->result['exact'][$type] = array_merge($this->result['exact'][$type], $exactMatches);
+ }
+ }
+
+ public function markExactIdMatch(SearchResultType $type) {
+ $this->exactIdMatches[$type->getLabel()] = 1;
+ }
+
+ public function hasExactIdMatch(SearchResultType$type) {
+ return isset($this->exactIdMatches[$type->getLabel()]);
+ }
+
+ public function hasResult(SearchResultType $type, $collaboratorId) {
+ $type = $type->getLabel();
+ if(!isset($this->result[$type])) {
+ return false;
+ }
+
+ $resultArrays = [$this->result['exact'][$type], $this->result[$type]];
+ foreach($resultArrays as $resultArray) {
+ if ($resultArray['value']['shareWith'] === $collaboratorId) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public function asArray() {
+ return $this->result;
+ }
+
+ public function unsetResult(SearchResultType $type) {
+ $type = $type->getLabel();
+ $this->result[$type] = [];
+ if(isset($this->result['exact'][$type])) {
+ $this->result['exact'][$type] = [];
+ }
+ }
+}
diff --git a/lib/private/Collaboration/Collaborators/UserPlugin.php b/lib/private/Collaboration/Collaborators/UserPlugin.php
new file mode 100644
index 00000000000..86a55aa428f
--- /dev/null
+++ b/lib/private/Collaboration/Collaborators/UserPlugin.php
@@ -0,0 +1,149 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace OC\Collaboration\Collaborators;
+
+
+use OCP\Collaboration\Collaborators\ISearchPlugin;
+use OCP\Collaboration\Collaborators\ISearchResult;
+use OCP\Collaboration\Collaborators\SearchResultType;
+use OCP\IConfig;
+use OCP\IGroupManager;
+use OCP\IUser;
+use OCP\IUserManager;
+use OCP\IUserSession;
+use OCP\Share;
+
+class UserPlugin implements ISearchPlugin {
+ /* @var bool */
+ protected $shareWithGroupOnly;
+ protected $shareeEnumeration;
+
+ /** @var IConfig */
+ private $config;
+ /** @var IGroupManager */
+ private $groupManager;
+ /** @var IUserSession */
+ private $userSession;
+ /** @var IUserManager */
+ private $userManager;
+
+ public function __construct(IConfig $config, IUserManager $userManager, IGroupManager $groupManager, IUserSession $userSession) {
+ $this->config = $config;
+
+ $this->groupManager = $groupManager;
+ $this->userSession = $userSession;
+ $this->userManager = $userManager;
+
+ $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';
+ }
+
+ public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ $result = ['wide' => [], 'exact' => []];
+ $users = [];
+ $hasMoreResults = false;
+
+ $userGroups = [];
+ if ($this->shareWithGroupOnly) {
+ // Search in all the groups this user is part of
+ $userGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser());
+ foreach ($userGroups as $userGroup) {
+ $usersTmp = $this->groupManager->displayNamesInGroup($userGroup, $search, $limit, $offset);
+ foreach ($usersTmp as $uid => $userDisplayName) {
+ $users[$uid] = $userDisplayName;
+ }
+ }
+ } else {
+ // Search in all users
+ $usersTmp = $this->userManager->searchDisplayName($search, $limit, $offset);
+
+ foreach ($usersTmp as $user) {
+ $users[$user->getUID()] = $user->getDisplayName();
+ }
+ }
+
+ if (!$this->shareeEnumeration || sizeof($users) < $limit) {
+ $hasMoreResults = true;
+ }
+
+ $foundUserById = false;
+ $lowerSearch = strtolower($search);
+ foreach ($users as $uid => $userDisplayName) {
+ if (strtolower($uid) === $lowerSearch || strtolower($userDisplayName) === $lowerSearch) {
+ if (strtolower($uid) === $lowerSearch) {
+ $foundUserById = true;
+ }
+ $result['exact'][] = [
+ 'label' => $userDisplayName,
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_USER,
+ 'shareWith' => $uid,
+ ],
+ ];
+ } else {
+ $result['wide'][] = [
+ 'label' => $userDisplayName,
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_USER,
+ 'shareWith' => $uid,
+ ],
+ ];
+ }
+ }
+
+ if ($offset === 0 && !$foundUserById) {
+ // On page one we try if the search result has a direct hit on the
+ // user id and if so, we add that to the exact match list
+ $user = $this->userManager->get($search);
+ if ($user instanceof IUser) {
+ $addUser = true;
+
+ if ($this->shareWithGroupOnly) {
+ // Only add, if we have a common group
+ $commonGroups = array_intersect($userGroups, $this->groupManager->getUserGroupIds($user));
+ $addUser = !empty($commonGroups);
+ }
+
+ if ($addUser) {
+ array_push($result['exact'], [
+ 'label' => $user->getDisplayName(),
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_USER,
+ 'shareWith' => $user->getUID(),
+ ],
+ ]);
+ }
+ }
+ }
+
+ if (!$this->shareeEnumeration) {
+ $result['wide'] = [];
+ }
+
+ $type = new SearchResultType('users');
+ $searchResult->addResultSet($type, $result['wide'], $result['exact']);
+
+ return $hasMoreResults;
+ }
+}
diff --git a/lib/private/Server.php b/lib/private/Server.php
index a20d9ccfc01..29aee06d896 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -52,6 +52,10 @@ use OC\AppFramework\Http\Request;
use OC\AppFramework\Utility\SimpleContainer;
use OC\AppFramework\Utility\TimeFactory;
use OC\Authentication\LoginCredentials\Store;
+use OC\Collaboration\Collaborators\GroupPlugin;
+use OC\Collaboration\Collaborators\MailPlugin;
+use OC\Collaboration\Collaborators\RemotePlugin;
+use OC\Collaboration\Collaborators\UserPlugin;
use OC\Command\CronBus;
use OC\Contacts\ContactsMenu\ActionFactory;
use OC\Diagnostics\EventLogger;
@@ -115,6 +119,7 @@ use OCP\Contacts\ContactsMenu\IActionFactory;
use OCP\Lock\ILockingProvider;
use OCP\RichObjectStrings\IValidator;
use OCP\Security\IContentSecurityPolicyManager;
+use OCP\Share;
use OCP\Share\IShareHelper;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -993,6 +998,19 @@ class Server extends ServerContainer implements IServerContainer {
});
$this->registerAlias('ShareManager', \OCP\Share\IManager::class);
+ $this->registerService(\OCP\Collaboration\Collaborators\ISearch::class, function(Server $c) {
+ $instance = new Collaboration\Collaborators\Search($c);
+
+ // register default plugins
+ $instance->registerPlugin(['shareType' => 'SHARE_TYPE_USER', 'class' => UserPlugin::class]);
+ $instance->registerPlugin(['shareType' => 'SHARE_TYPE_GROUP', 'class' => GroupPlugin::class]);
+ $instance->registerPlugin(['shareType' => 'SHARE_TYPE_EMAIL', 'class' => MailPlugin::class]);
+ $instance->registerPlugin(['shareType' => 'SHARE_TYPE_REMOTE', 'class' => RemotePlugin::class]);
+
+ return $instance;
+ });
+ $this->registerAlias('CollaboratorSearch', \OCP\Collaboration\Collaborators\ISearch::class);
+
$this->registerService('SettingsManager', function (Server $c) {
$manager = new \OC\Settings\Manager(
$c->getLogger(),
@@ -1777,6 +1795,13 @@ class Server extends ServerContainer implements IServerContainer {
}
/**
+ * @return \OCP\Collaboration\Collaborators\ISearch
+ */
+ public function getCollaboratorSearch() {
+ return $this->query('CollaboratorSearch');
+ }
+
+ /**
* Returns the LDAP Provider
*
* @return \OCP\LDAP\ILDAPProvider
diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php
index 24c7a344e00..a33c9be20fc 100644
--- a/lib/private/legacy/app.php
+++ b/lib/private/legacy/app.php
@@ -174,6 +174,20 @@ class OC_App {
\OC::$server->getActivityManager()->registerProvider($provider);
}
}
+ if (!empty($info['collaboration']['plugins'])) {
+ // deal with one or many plugin entries
+ $plugins = isset($info['collaboration']['plugins']['plugin']['@value']) ?
+ [$info['collaboration']['plugins']['plugin']] : $info['collaboration']['plugins']['plugin'];
+ foreach ($plugins as $plugin) {
+ if($plugin['@attributes']['type'] === 'collaborator-search') {
+ $pluginInfo = [
+ 'shareType' => $plugin['@attributes']['share-type'],
+ 'class' => $plugin['@value'],
+ ];
+ \OC::$server->getCollaboratorSearch()->registerPlugin($pluginInfo);
+ }
+ }
+ }
}
/**
diff --git a/lib/public/Collaboration/Collaborators/ISearch.php b/lib/public/Collaboration/Collaborators/ISearch.php
new file mode 100644
index 00000000000..281893908ee
--- /dev/null
+++ b/lib/public/Collaboration/Collaborators/ISearch.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace OCP\Collaboration\Collaborators;
+
+/**
+ * Interface ISearch
+ *
+ * @package OCP\Collaboration\Collaborators
+ * @since 13.0.0
+ */
+interface ISearch {
+ /**
+ * @param string $search
+ * @param array $shareTypes
+ * @param bool $lookup
+ * @param int $limit
+ * @param int $offset
+ * @return array with two elements, 1st ISearchResult as array, 2nd a bool indicating whether more result are available
+ * @since 13.0.0
+ */
+ public function search($search, array $shareTypes, $lookup, $limit, $offset);
+
+ /**
+ * @param array $pluginInfo with keys 'shareType' containing the name of a corresponding constant in \OCP\Share and
+ * 'class' with the class name of the plugin
+ * @since 13.0.0
+ */
+ public function registerPlugin(array $pluginInfo);
+}
diff --git a/lib/public/Collaboration/Collaborators/ISearchPlugin.php b/lib/public/Collaboration/Collaborators/ISearchPlugin.php
new file mode 100644
index 00000000000..bc6fa53799b
--- /dev/null
+++ b/lib/public/Collaboration/Collaborators/ISearchPlugin.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace OCP\Collaboration\Collaborators;
+
+/**
+ * Interface ISearchPlugin
+ *
+ * @package OCP\Collaboration\Collaborators
+ * @since 13.0.0
+ */
+interface ISearchPlugin {
+ /**
+ * @param string $search
+ * @param int $limit
+ * @param int $offset
+ * @param ISearchResult $searchResult
+ * @return bool whether the plugin has more results
+ * @since 13.0.0
+ */
+ public function search($search, $limit, $offset, ISearchResult $searchResult);
+}
diff --git a/lib/public/Collaboration/Collaborators/ISearchResult.php b/lib/public/Collaboration/Collaborators/ISearchResult.php
new file mode 100644
index 00000000000..abea5df8598
--- /dev/null
+++ b/lib/public/Collaboration/Collaborators/ISearchResult.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace OCP\Collaboration\Collaborators;
+
+/**
+ * Interface ISearchResult
+ *
+ * @package OCP\Collaboration\Collaborators
+ * @since 13.0.0
+ */
+interface ISearchResult {
+ /**
+ * @param SearchResultType $type
+ * @param array $matches
+ * @param array|null $exactMatches
+ * @since 13.0.0
+ */
+ public function addResultSet(SearchResultType $type, array $matches, array $exactMatches = null);
+
+ /**
+ * @param SearchResultType $type
+ * @param string $collaboratorId
+ * @return bool
+ * @since 13.0.0
+ */
+ public function hasResult(SearchResultType $type, $collaboratorId);
+
+ /**
+ * @param SearchResultType $type
+ * @since 13.0.0
+ */
+ public function unsetResult(SearchResultType $type);
+
+ /**
+ * @param SearchResultType $type
+ * @since 13.0.0
+ */
+ public function markExactIdMatch(SearchResultType $type);
+
+ /**
+ * @param SearchResultType $type
+ * @return bool
+ * @since 13.0.0
+ */
+ public function hasExactIdMatch(SearchResultType $type);
+
+ /**
+ * @return array
+ * @since 13.0.0
+ */
+ public function asArray();
+}
diff --git a/lib/public/Collaboration/Collaborators/SearchResultType.php b/lib/public/Collaboration/Collaborators/SearchResultType.php
new file mode 100644
index 00000000000..e4ad888d6e4
--- /dev/null
+++ b/lib/public/Collaboration/Collaborators/SearchResultType.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace OCP\Collaboration\Collaborators;
+
+/**
+ * Class SearchResultType
+ *
+ * @package OCP\Collaboration\Collaborators
+ * @since 13.0.0
+ */
+class SearchResultType {
+ /** @var string */
+ protected $label;
+
+ /**
+ * SearchResultType constructor.
+ *
+ * @param string $label
+ * @since 13.0.0
+ */
+ public function __construct($label) {
+ $this->label = $this->getValidatedType($label);
+ }
+
+ /**
+ * @return string
+ * @since 13.0.0
+ */
+ public function getLabel() {
+ return $this->label;
+ }
+
+ /**
+ * @param $type
+ * @return string
+ * @throws \InvalidArgumentException
+ * @since 13.0.0
+ */
+ protected function getValidatedType($type) {
+ $type = trim(strval($type));
+
+ if($type === '') {
+ throw new \InvalidArgumentException('Type must not be empty');
+ }
+
+ if($type === 'exact') {
+ throw new \InvalidArgumentException('Provided type is a reserved word');
+ }
+
+ return $type;
+ }
+}
diff --git a/tests/lib/Collaboration/Collaborators/GroupPluginTest.php b/tests/lib/Collaboration/Collaborators/GroupPluginTest.php
new file mode 100644
index 00000000000..9849bdb874a
--- /dev/null
+++ b/tests/lib/Collaboration/Collaborators/GroupPluginTest.php
@@ -0,0 +1,491 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace Test\Collaboration\Collaborators;
+
+
+use OC\Collaboration\Collaborators\GroupPlugin;
+use OC\Collaboration\Collaborators\SearchResult;
+use OCP\Collaboration\Collaborators\ISearchResult;
+use OCP\IConfig;
+use OCP\IGroup;
+use OCP\IGroupManager;
+use OCP\IUser;
+use OCP\IUserSession;
+use OCP\Share;
+use Test\TestCase;
+
+class GroupPluginTest extends TestCase {
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
+ protected $config;
+
+ /** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */
+ protected $groupManager;
+
+ /** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */
+ protected $session;
+
+ /** @var ISearchResult */
+ protected $searchResult;
+
+ /** @var GroupPlugin */
+ protected $plugin;
+
+ /** @var int */
+ protected $limit = 2;
+
+ /** @var int */
+ protected $offset = 0;
+
+ /** @var IUser|\PHPUnit_Framework_MockObject_MockObject */
+ protected $user;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->config = $this->createMock(IConfig::class);
+
+ $this->groupManager = $this->createMock(IGroupManager::class);
+
+ $this->session = $this->createMock(IUserSession::class);
+
+ $this->searchResult = new SearchResult();
+
+ $this->user = $this->getUserMock('admin', 'Administrator');
+ }
+
+ public function instantiatePlugin() {
+ // cannot be done within setUp, because dependent mocks needs to be set
+ // up with configuration etc. first
+ $this->plugin = new GroupPlugin(
+ $this->config,
+ $this->groupManager,
+ $this->session
+ );
+ }
+
+ public function getUserMock($uid, $displayName) {
+ $user = $this->createMock(IUser::class);
+
+ $user->expects($this->any())
+ ->method('getUID')
+ ->willReturn($uid);
+
+ $user->expects($this->any())
+ ->method('getDisplayName')
+ ->willReturn($displayName);
+
+ return $user;
+ }
+
+ /**
+ * @param string $gid
+ * @param null $displayName
+ * @return IGroup|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected function getGroupMock($gid, $displayName = null) {
+ $group = $this->createMock(IGroup::class);
+
+ $group->expects($this->any())
+ ->method('getGID')
+ ->willReturn($gid);
+
+ if (is_null($displayName)) {
+ // note: this is how the Group class behaves
+ $displayName = $gid;
+ }
+
+ $group->expects($this->any())
+ ->method('getDisplayName')
+ ->willReturn($displayName);
+
+ return $group;
+ }
+
+ public function dataGetGroups() {
+ return [
+ ['test', false, true, [], [], [], [], true, false],
+ ['test', false, false, [], [], [], [], true, false],
+ // group without display name
+ [
+ 'test', false, true,
+ [$this->getGroupMock('test1')],
+ [],
+ [],
+ [['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
+ true,
+ false,
+ ],
+ // group with display name, search by id
+ [
+ 'test', false, true,
+ [$this->getGroupMock('test1', 'Test One')],
+ [],
+ [],
+ [['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
+ true,
+ false,
+ ],
+ // group with display name, search by display name
+ [
+ 'one', false, true,
+ [$this->getGroupMock('test1', 'Test One')],
+ [],
+ [],
+ [['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
+ true,
+ false,
+ ],
+ // group with display name, search by display name, exact expected
+ [
+ 'Test One', false, true,
+ [$this->getGroupMock('test1', 'Test One')],
+ [],
+ [['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test', false, false,
+ [$this->getGroupMock('test1')],
+ [],
+ [],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test', false, true,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [],
+ [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
+ [['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
+ false,
+ false,
+ ],
+ [
+ 'test', false, false,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [],
+ [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test', false, true,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [],
+ [],
+ [
+ ['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
+ ['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
+ ],
+ false,
+ null,
+ ],
+ [
+ 'test', false, false,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [],
+ [],
+ [],
+ true,
+ null,
+ ],
+ [
+ 'test', false, true,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [],
+ [
+ ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
+ ],
+ [
+ ['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
+ ['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
+ ],
+ false,
+ $this->getGroupMock('test'),
+ ],
+ [
+ 'test', false, false,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [],
+ [
+ ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
+ ],
+ [],
+ true,
+ $this->getGroupMock('test'),
+ ],
+ ['test', true, true, [], [], [], [], true, false],
+ ['test', true, false, [], [], [], [], true, false],
+ [
+ 'test', true, true,
+ [
+ $this->getGroupMock('test1'),
+ $this->getGroupMock('test2'),
+ ],
+ [$this->getGroupMock('test1')],
+ [],
+ [['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
+ false,
+ false,
+ ],
+ [
+ 'test', true, false,
+ [
+ $this->getGroupMock('test1'),
+ $this->getGroupMock('test2'),
+ ],
+ [$this->getGroupMock('test1')],
+ [],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test', true, true,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test')],
+ [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
+ [],
+ false,
+ false,
+ ],
+ [
+ 'test', true, false,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test')],
+ [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test', true, true,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test1')],
+ [],
+ [['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
+ false,
+ false,
+ ],
+ [
+ 'test', true, false,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test1')],
+ [],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test', true, true,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
+ [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
+ [['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
+ false,
+ false,
+ ],
+ [
+ 'test', true, false,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
+ [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test', true, true,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
+ [],
+ [
+ ['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
+ ['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
+ ],
+ false,
+ null,
+ ],
+ [
+ 'test', true, false,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
+ [],
+ [],
+ true,
+ null,
+ ],
+ [
+ 'test', true, true,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
+ [
+ ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
+ ],
+ [
+ ['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
+ ['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
+ ],
+ false,
+ $this->getGroupMock('test'),
+ ],
+ [
+ 'test', true, false,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
+ [
+ ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
+ ],
+ [],
+ true,
+ $this->getGroupMock('test'),
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataGetGroups
+ *
+ * @param string $searchTerm
+ * @param bool $shareWithGroupOnly
+ * @param bool $shareeEnumeration
+ * @param array $groupResponse
+ * @param array $userGroupsResponse
+ * @param array $exactExpected
+ * @param array $expected
+ * @param bool $reachedEnd
+ * @param bool|IGroup $singleGroup
+ */
+ public function testSearch(
+ $searchTerm,
+ $shareWithGroupOnly,
+ $shareeEnumeration,
+ array $groupResponse,
+ array $userGroupsResponse,
+ array $exactExpected,
+ array $expected,
+ $reachedEnd,
+ $singleGroup
+ ) {
+ $this->config->expects($this->any())
+ ->method('getAppValue')
+ ->willReturnCallback(
+ function($appName, $key, $default)
+ use ($shareWithGroupOnly, $shareeEnumeration)
+ {
+ if ($appName === 'core' && $key === 'shareapi_only_share_with_group_members') {
+ return $shareWithGroupOnly ? 'yes' : 'no';
+ } else if ($appName === 'core' && $key === 'shareapi_allow_share_dialog_user_enumeration') {
+ return $shareeEnumeration ? 'yes' : 'no';
+ }
+ return $default;
+ }
+ );
+
+ $this->instantiatePlugin();
+
+ $this->groupManager->expects($this->once())
+ ->method('search')
+ ->with($searchTerm, $this->limit, $this->offset)
+ ->willReturn($groupResponse);
+
+ if ($singleGroup !== false) {
+ $this->groupManager->expects($this->once())
+ ->method('get')
+ ->with($searchTerm)
+ ->willReturn($singleGroup);
+ }
+
+ if ($shareWithGroupOnly) {
+ $this->session->expects($this->any())
+ ->method('getUser')
+ ->willReturn($this->user);
+
+ $numGetUserGroupsCalls = empty($groupResponse) ? 0 : 1;
+ $this->groupManager->expects($this->exactly($numGetUserGroupsCalls))
+ ->method('getUserGroups')
+ ->with($this->user)
+ ->willReturn($userGroupsResponse);
+ }
+
+ $moreResults = $this->plugin->search($searchTerm, $this->limit, $this->offset, $this->searchResult);
+ $result = $this->searchResult->asArray();
+
+ $this->assertEquals($exactExpected, $result['exact']['groups']);
+ $this->assertEquals($expected, $result['groups']);
+ $this->assertSame($reachedEnd, $moreResults);
+ }
+}
diff --git a/tests/lib/Collaboration/Collaborators/LookupPluginTest.php b/tests/lib/Collaboration/Collaborators/LookupPluginTest.php
new file mode 100644
index 00000000000..83d366cf467
--- /dev/null
+++ b/tests/lib/Collaboration/Collaborators/LookupPluginTest.php
@@ -0,0 +1,180 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace Test\Collaboration\Collaborators;
+
+
+use OC\Collaboration\Collaborators\LookupPlugin;
+use OCP\Collaboration\Collaborators\ISearchResult;
+use OCP\Collaboration\Collaborators\SearchResultType;
+use OCP\Http\Client\IClient;
+use OCP\Http\Client\IClientService;
+use OCP\Http\Client\IResponse;
+use OCP\IConfig;
+use OCP\Share;
+use Test\TestCase;
+
+class LookupPluginTest extends TestCase {
+
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
+ protected $config;
+ /** @var IClientService|\PHPUnit_Framework_MockObject_MockObject */
+ protected $clientService;
+ /** @var LookupPlugin */
+ protected $plugin;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->config = $this->createMock(IConfig::class);
+ $this->clientService = $this->createMock(IClientService::class);
+
+ $this->plugin = new LookupPlugin($this->config, $this->clientService);
+ }
+
+ /**
+ * @dataProvider searchDataProvider
+ * @param array $searchParams
+ */
+ public function testSearch(array $searchParams) {
+ $type = new SearchResultType('lookup');
+
+ /** @var ISearchResult|\PHPUnit_Framework_MockObject_MockObject $searchResult */
+ $searchResult = $this->createMock(ISearchResult::class);
+ $searchResult->expects($this->once())
+ ->method('addResultSet')
+ ->with($type, $searchParams['expectedResult'], []);
+
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('files_sharing', 'lookupServerEnabled', 'no')
+ ->willReturn('yes');
+ $this->config->expects($this->once())
+ ->method('getSystemValue')
+ ->with('lookup_server', 'https://lookup.nextcloud.com')
+ ->willReturn($searchParams['server']);
+
+ $response = $this->createMock(IResponse::class);
+ $response->expects($this->once())
+ ->method('getBody')
+ ->willReturn(json_encode($searchParams['resultBody']));
+
+ $client = $this->createMock(IClient::class);
+ $client->expects($this->once())
+ ->method('get')
+ ->willReturnCallback(function($url) use ($searchParams, $response) {
+ $this->assertSame(strpos($url, $searchParams['server'] . '/users?search='), 0);
+ $this->assertNotFalse(strpos($url, urlencode($searchParams['search'])));
+ return $response;
+ });
+
+ $this->clientService->expects($this->once())
+ ->method('newClient')
+ ->willReturn($client);
+
+ $moreResults = $this->plugin->search(
+ $searchParams['search'],
+ $searchParams['limit'],
+ $searchParams['offset'],
+ $searchResult
+ );
+
+
+
+ $this->assertFalse($moreResults);
+ }
+
+ public function testSearchLookupServerDisabled() {
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('files_sharing', 'lookupServerEnabled', 'no')
+ ->willReturn('no');
+
+ /** @var ISearchResult|\PHPUnit_Framework_MockObject_MockObject $searchResult */
+ $searchResult = $this->createMock(ISearchResult::class);
+ $searchResult->expects($this->never())
+ ->method('addResultSet');
+ $searchResult->expects($this->never())
+ ->method('markExactIdMatch');
+
+ $this->assertFalse($this->plugin->search('irr', 10, 0, $searchResult));
+ }
+
+ public function searchDataProvider() {
+ $fedIDs = [
+ 'foo@enceladus.moon',
+ 'foobar@enceladus.moon',
+ 'foongus@enceladus.moon',
+ ];
+
+ return [
+ // #0, standard search with results
+ [[
+ 'search' => 'foo',
+ 'limit' => 10,
+ 'offset' => 0,
+ 'server' => 'https://lookup.example.io',
+ 'resultBody' => [
+ [ 'federationId' => $fedIDs[0] ],
+ [ 'federationId' => $fedIDs[1] ],
+ [ 'federationId' => $fedIDs[2] ],
+ ],
+ 'expectedResult' => [
+ [
+ 'label' => $fedIDs[0],
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_REMOTE,
+ 'shareWith' => $fedIDs[0]
+ ],
+ 'extra' => ['federationId' => $fedIDs[0]],
+ ],
+ [
+ 'label' => $fedIDs[1],
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_REMOTE,
+ 'shareWith' => $fedIDs[1]
+ ],
+ 'extra' => ['federationId' => $fedIDs[1]],
+ ],
+ [
+ 'label' => $fedIDs[2],
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_REMOTE,
+ 'shareWith' => $fedIDs[2]
+ ],
+ 'extra' => ['federationId' => $fedIDs[2]],
+ ],
+ ]
+ ]],
+ // #1, search without results
+ [[
+ 'search' => 'foo',
+ 'limit' => 10,
+ 'offset' => 0,
+ 'server' => 'https://lookup.example.io',
+ 'resultBody' => [],
+ 'expectedResult' => [],
+ ]],
+ ];
+ }
+}
diff --git a/tests/lib/Collaboration/Collaborators/MailPluginTest.php b/tests/lib/Collaboration/Collaborators/MailPluginTest.php
new file mode 100644
index 00000000000..9c9d9cff909
--- /dev/null
+++ b/tests/lib/Collaboration/Collaborators/MailPluginTest.php
@@ -0,0 +1,336 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace Test\Collaboration\Collaborators;
+
+
+use OC\Collaboration\Collaborators\MailPlugin;
+use OC\Collaboration\Collaborators\SearchResult;
+use OC\Federation\CloudIdManager;
+use OCP\Collaboration\Collaborators\SearchResultType;
+use OCP\Contacts\IManager;
+use OCP\Federation\ICloudIdManager;
+use OCP\IConfig;
+use OCP\Share;
+use Test\TestCase;
+
+class MailPluginTest extends TestCase {
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
+ protected $config;
+
+ /** @var IManager|\PHPUnit_Framework_MockObject_MockObject */
+ protected $contactsManager;
+
+ /** @var ICloudIdManager|\PHPUnit_Framework_MockObject_MockObject */
+ protected $cloudIdManager;
+
+ /** @var MailPlugin */
+ protected $plugin;
+
+ /** @var SearchResult */
+ protected $searchResult;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->config = $this->createMock(IConfig::class);
+ $this->contactsManager = $this->createMock(IManager::class);
+ $this->cloudIdManager = new CloudIdManager();
+ $this->searchResult = new SearchResult();
+ }
+
+ public function instantiatePlugin() {
+ $this->plugin = new MailPlugin($this->contactsManager, $this->cloudIdManager, $this->config);
+ }
+
+ /**
+ * @dataProvider dataGetEmail
+ *
+ * @param string $searchTerm
+ * @param array $contacts
+ * @param bool $shareeEnumeration
+ * @param array $expected
+ * @param bool $reachedEnd
+ */
+ public function testSearch($searchTerm, $contacts, $shareeEnumeration, $expected, $exactIdMatch, $reachedEnd) {
+ $this->config->expects($this->any())
+ ->method('getAppValue')
+ ->willReturnCallback(
+ function($appName, $key, $default)
+ use ($shareeEnumeration)
+ {
+ if ($appName === 'core' && $key === 'shareapi_allow_share_dialog_user_enumeration') {
+ return $shareeEnumeration ? 'yes' : 'no';
+ }
+ return $default;
+ }
+ );
+
+ $this->instantiatePlugin();
+
+ $this->contactsManager->expects($this->any())
+ ->method('search')
+ ->with($searchTerm, ['EMAIL', 'FN'])
+ ->willReturn($contacts);
+
+ $moreResults = $this->plugin->search($searchTerm, 0, 0, $this->searchResult);
+ $result = $this->searchResult->asArray();
+
+ $this->assertSame($exactIdMatch, $this->searchResult->hasExactIdMatch(new SearchResultType('emails')));
+ $this->assertEquals($expected, $result);
+ $this->assertSame($reachedEnd, $moreResults);
+ }
+
+ public function dataGetEmail() {
+ return [
+ ['test', [], true, ['emails' => [], 'exact' => ['emails' => []]], false, true],
+ ['test', [], false, ['emails' => [], 'exact' => ['emails' => []]], false, true],
+ [
+ 'test@remote.com',
+ [],
+ true,
+ ['emails' => [], 'exact' => ['emails' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]],
+ false,
+ true,
+ ],
+ [ // no valid email address
+ 'test@remote',
+ [],
+ true,
+ ['emails' => [], 'exact' => ['emails' => []]],
+ false,
+ true,
+ ],
+ [
+ 'test@remote.com',
+ [],
+ false,
+ ['emails' => [], 'exact' => ['emails' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]],
+ false,
+ true,
+ ],
+ [
+ 'test',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'EMAIL' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'EMAIL' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ true,
+ ['emails' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exact' => ['emails' => []]],
+ false,
+ true,
+ ],
+ [
+ 'test',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'EMAIL' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'EMAIL' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ false,
+ ['emails' => [], 'exact' => ['emails' => []]],
+ false,
+ true,
+ ],
+ [
+ 'test@remote.com',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'EMAIL' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'EMAIL' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ true,
+ ['emails' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exact' => ['emails' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]],
+ false,
+ true,
+ ],
+ [
+ 'test@remote.com',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'EMAIL' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'EMAIL' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ false,
+ ['emails' => [], 'exact' => ['emails' => [['label' => 'test@remote.com', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]],
+ false,
+ true,
+ ],
+ [
+ 'username@localhost',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'EMAIL' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'EMAIL' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ true,
+ ['emails' => [], 'exact' => ['emails' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]]]],
+ true,
+ true,
+ ],
+ [
+ 'username@localhost',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'EMAIL' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'EMAIL' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ false,
+ ['emails' => [], 'exact' => ['emails' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'username@localhost']]]]],
+ true,
+ true,
+ ],
+ // contact with space
+ [
+ 'user name@localhost',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'EMAIL' => [
+ ],
+ ],
+ [
+ 'FN' => 'User Name @ Localhost',
+ 'EMAIL' => [
+ 'user name@localhost',
+ ],
+ ],
+ ],
+ false,
+ ['emails' => [], 'exact' => ['emails' => [['label' => 'User Name @ Localhost (user name@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_EMAIL, 'shareWith' => 'user name@localhost']]]]],
+ true,
+ true,
+ ],
+ // remote with space, no contact
+ [
+ 'user space@remote.com',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'EMAIL' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'EMAIL' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ false,
+ ['emails' => [], 'exact' => ['emails' => []]],
+ false,
+ true,
+ ],
+ // Local user found by email
+ [
+ 'test@example.com',
+ [
+ [
+ 'FN' => 'User',
+ 'EMAIL' => ['test@example.com'],
+ 'CLOUD' => ['test@localhost'],
+ 'isLocalSystemBook' => true,
+ ]
+ ],
+ false,
+ ['users' => [], 'exact' => ['users' => [['label' => 'User (test@example.com)','value' => ['shareType' => 0, 'shareWith' => 'test'],]]]],
+ true,
+ false,
+ ]
+ ];
+ }
+}
diff --git a/tests/lib/Collaboration/Collaborators/RemotePluginTest.php b/tests/lib/Collaboration/Collaborators/RemotePluginTest.php
new file mode 100644
index 00000000000..5c4b3af5e70
--- /dev/null
+++ b/tests/lib/Collaboration/Collaborators/RemotePluginTest.php
@@ -0,0 +1,388 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace Test\Collaboration\Collaborators;
+
+
+use OC\Collaboration\Collaborators\RemotePlugin;
+use OC\Collaboration\Collaborators\SearchResult;
+use OC\Federation\CloudIdManager;
+use OCP\Collaboration\Collaborators\SearchResultType;
+use OCP\Contacts\IManager;
+use OCP\Federation\ICloudIdManager;
+use OCP\IConfig;
+use OCP\Share;
+use Test\TestCase;
+
+class RemotePluginTest extends TestCase {
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
+ protected $config;
+
+ /** @var IManager|\PHPUnit_Framework_MockObject_MockObject */
+ protected $contactsManager;
+
+ /** @var ICloudIdManager|\PHPUnit_Framework_MockObject_MockObject */
+ protected $cloudIdManager;
+
+ /** @var RemotePlugin */
+ protected $plugin;
+
+ /** @var SearchResult */
+ protected $searchResult;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->config = $this->createMock(IConfig::class);
+ $this->contactsManager = $this->createMock(IManager::class);
+ $this->cloudIdManager = new CloudIdManager();
+ $this->searchResult = new SearchResult();
+ }
+
+ public function instantiatePlugin() {
+ $this->plugin = new RemotePlugin($this->contactsManager, $this->cloudIdManager, $this->config);
+ }
+
+ /**
+ * @dataProvider dataGetRemote
+ *
+ * @param string $searchTerm
+ * @param array $contacts
+ * @param bool $shareeEnumeration
+ * @param array $expected
+ * @param bool $exactIdMatch
+ * @param bool $reachedEnd
+ */
+ public function testSearch($searchTerm, array $contacts, $shareeEnumeration, array $expected, $exactIdMatch, $reachedEnd) {
+ $this->config->expects($this->any())
+ ->method('getAppValue')
+ ->willReturnCallback(
+ function($appName, $key, $default)
+ use ($shareeEnumeration)
+ {
+ if ($appName === 'core' && $key === 'shareapi_allow_share_dialog_user_enumeration') {
+ return $shareeEnumeration ? 'yes' : 'no';
+ }
+ return $default;
+ }
+ );
+
+ $this->instantiatePlugin();
+
+ $this->contactsManager->expects($this->any())
+ ->method('search')
+ ->with($searchTerm, ['CLOUD', 'FN'])
+ ->willReturn($contacts);
+
+ $moreResults = $this->plugin->search($searchTerm, 0, 0, $this->searchResult);
+ $result = $this->searchResult->asArray();
+
+ $this->assertSame($exactIdMatch, $this->searchResult->hasExactIdMatch(new SearchResultType('remotes')));
+ $this->assertEquals($expected, $result);
+ $this->assertSame($reachedEnd, $moreResults);
+ }
+
+ /**
+ * @dataProvider dataTestSplitUserRemote
+ *
+ * @param string $remote
+ * @param string $expectedUser
+ * @param string $expectedUrl
+ */
+ public function testSplitUserRemote($remote, $expectedUser, $expectedUrl) {
+ $this->instantiatePlugin();
+
+ list($remoteUser, $remoteUrl) = $this->plugin->splitUserRemote($remote);
+ $this->assertSame($expectedUser, $remoteUser);
+ $this->assertSame($expectedUrl, $remoteUrl);
+ }
+
+ /**
+ * @dataProvider dataTestSplitUserRemoteError
+ *
+ * @param string $id
+ * @expectedException \Exception
+ */
+ public function testSplitUserRemoteError($id) {
+ $this->instantiatePlugin();
+ $this->plugin->splitUserRemote($id);
+ }
+
+ public function dataGetRemote() {
+ return [
+ ['test', [], true, ['remotes' => [], 'exact' => ['remotes' => []]], false, true],
+ ['test', [], false, ['remotes' => [], 'exact' => ['remotes' => []]], false, true],
+ [
+ 'test@remote',
+ [],
+ true,
+ ['remotes' => [], 'exact' => ['remotes' => [['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']]]]],
+ false,
+ true,
+ ],
+ [
+ 'test@remote',
+ [],
+ false,
+ ['remotes' => [], 'exact' => ['remotes' => [['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']]]]],
+ false,
+ true,
+ ],
+ [
+ 'test',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'CLOUD' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'CLOUD' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ true,
+ ['remotes' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exact' => ['remotes' => []]],
+ false,
+ true,
+ ],
+ [
+ 'test',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'CLOUD' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'CLOUD' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ false,
+ ['remotes' => [], 'exact' => ['remotes' => []]],
+ false,
+ true,
+ ],
+ [
+ 'test@remote',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'CLOUD' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'CLOUD' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ true,
+ ['remotes' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]], 'exact' => ['remotes' => [['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']]]]],
+ false,
+ true,
+ ],
+ [
+ 'test@remote',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'CLOUD' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'CLOUD' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ false,
+ ['remotes' => [], 'exact' => ['remotes' => [['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']]]]],
+ false,
+ true,
+ ],
+ [
+ 'username@localhost',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'CLOUD' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'CLOUD' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ true,
+ ['remotes' => [], 'exact' => ['remotes' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]]]],
+ true,
+ true,
+ ],
+ [
+ 'username@localhost',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'CLOUD' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'CLOUD' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ false,
+ ['remotes' => [], 'exact' => ['remotes' => [['label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']]]]],
+ true,
+ true,
+ ],
+ // contact with space
+ [
+ 'user name@localhost',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'CLOUD' => [
+ ],
+ ],
+ [
+ 'FN' => 'User Name @ Localhost',
+ 'CLOUD' => [
+ 'user name@localhost',
+ ],
+ ],
+ ],
+ false,
+ ['remotes' => [], 'exact' => ['remotes' => [['label' => 'User Name @ Localhost (user name@localhost)', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'user name@localhost', 'server' => 'localhost']]]]],
+ true,
+ true,
+ ],
+ // remote with space, no contact
+ [
+ 'user space@remote',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'CLOUD' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'CLOUD' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ false,
+ ['remotes' => [], 'exact' => ['remotes' => [['label' => 'user space@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'user space@remote']]]]],
+ false,
+ true,
+ ],
+ ];
+ }
+
+ public function dataTestSplitUserRemote() {
+ $userPrefix = ['user@name', 'username'];
+ $protocols = ['', 'http://', 'https://'];
+ $remotes = [
+ 'localhost',
+ 'local.host',
+ 'dev.local.host',
+ 'dev.local.host/path',
+ 'dev.local.host/at@inpath',
+ '127.0.0.1',
+ '::1',
+ '::192.0.2.128',
+ '::192.0.2.128/at@inpath',
+ ];
+
+ $testCases = [];
+ foreach ($userPrefix as $user) {
+ foreach ($remotes as $remote) {
+ foreach ($protocols as $protocol) {
+ $baseUrl = $user . '@' . $protocol . $remote;
+
+ $testCases[] = [$baseUrl, $user, $protocol . $remote];
+ $testCases[] = [$baseUrl . '/', $user, $protocol . $remote];
+ $testCases[] = [$baseUrl . '/index.php', $user, $protocol . $remote];
+ $testCases[] = [$baseUrl . '/index.php/s/token', $user, $protocol . $remote];
+ }
+ }
+ }
+ return $testCases;
+ }
+
+ public function dataTestSplitUserRemoteError() {
+ return array(
+ // Invalid path
+ array('user@'),
+
+ // Invalid user
+ array('@server'),
+ array('us/er@server'),
+ array('us:er@server'),
+
+ // Invalid splitting
+ array('user'),
+ array(''),
+ array('us/erserver'),
+ array('us:erserver'),
+ );
+ }
+}
diff --git a/tests/lib/Collaboration/Collaborators/SearchTest.php b/tests/lib/Collaboration/Collaborators/SearchTest.php
new file mode 100644
index 00000000000..80e6c7f0beb
--- /dev/null
+++ b/tests/lib/Collaboration/Collaborators/SearchTest.php
@@ -0,0 +1,219 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace Test\Collaboration\Collaborators;
+
+
+use OC\Collaboration\Collaborators\Search;
+use OC\Collaboration\Collaborators\SearchResult;
+use OCP\Collaboration\Collaborators\ISearch;
+use OCP\Collaboration\Collaborators\ISearchPlugin;
+use OCP\Collaboration\Collaborators\SearchResultType;
+use OCP\IContainer;
+use OCP\Share;
+use Test\TestCase;
+
+class SearchTest extends TestCase {
+ /** @var IContainer|\PHPUnit_Framework_MockObject_MockObject */
+ protected $container;
+ /** @var ISearch */
+ protected $search;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->container = $this->createMock(IContainer::class);
+
+ $this->search = new Search($this->container);
+ }
+
+ /**
+ * @dataProvider dataSearchSharees
+ *
+ * @param string $searchTerm
+ * @param array $shareTypes
+ * @param int $page
+ * @param int $perPage
+ * @param array $mockedUserResult
+ * @param array $mockedGroupsResult
+ * @param array $mockedRemotesResult
+ * @param array $expected
+ * @param bool $expectedMoreResults
+ */
+ public function testSearch(
+ $searchTerm,
+ array $shareTypes,
+ $page,
+ $perPage,
+ array $mockedUserResult,
+ array $mockedGroupsResult,
+ array $mockedRemotesResult,
+ array $expected,
+ $expectedMoreResults
+ ) {
+ $searchResult = new SearchResult();
+
+ $userPlugin = $this->createMock(ISearchPlugin::class);
+ $userPlugin->expects($this->any())
+ ->method('search')
+ ->willReturnCallback(function() use ($searchResult, $mockedUserResult, $expectedMoreResults) {
+ $type = new SearchResultType('users');
+ $searchResult->addResultSet($type, $mockedUserResult);
+ return $expectedMoreResults;
+ });
+
+ $groupPlugin = $this->createMock(ISearchPlugin::class);
+ $groupPlugin->expects($this->any())
+ ->method('search')
+ ->willReturnCallback(function() use ($searchResult, $mockedGroupsResult, $expectedMoreResults) {
+ $type = new SearchResultType('groups');
+ $searchResult->addResultSet($type, $mockedGroupsResult);
+ return $expectedMoreResults;
+ });
+
+ $remotePlugin = $this->createMock(ISearchPlugin::class);
+ $remotePlugin->expects($this->any())
+ ->method('search')
+ ->willReturnCallback(function() use ($searchResult, $mockedRemotesResult, $expectedMoreResults) {
+ if($mockedRemotesResult !== null) {
+ $type = new SearchResultType('remotes');
+ $searchResult->addResultSet($type, $mockedRemotesResult['results'], $mockedRemotesResult['exact']);
+ if($mockedRemotesResult['exactIdMatch'] === true) {
+ $searchResult->markExactIdMatch($type);
+ }
+ }
+ return $expectedMoreResults;
+ });
+
+ $this->container->expects($this->any())
+ ->method('resolve')
+ ->willReturnCallback(function($class) use ($searchResult, $userPlugin, $groupPlugin, $remotePlugin) {
+ if($class === SearchResult::class) {
+ return $searchResult;
+ } elseif ($class === $userPlugin) {
+ return $userPlugin;
+ } elseif ($class === $groupPlugin) {
+ return $groupPlugin;
+ } elseif ($class === $remotePlugin) {
+ return $remotePlugin;
+ }
+ return null;
+ });
+
+ $this->search->registerPlugin(['shareType' => 'SHARE_TYPE_USER', 'class' => $userPlugin]);
+ $this->search->registerPlugin(['shareType' => 'SHARE_TYPE_GROUP', 'class' => $groupPlugin]);
+ $this->search->registerPlugin(['shareType' => 'SHARE_TYPE_REMOTE', 'class' => $remotePlugin]);
+
+ list($results, $moreResults) = $this->search->search($searchTerm, $shareTypes, false, $perPage, $perPage * ($page - 1));
+
+ $this->assertEquals($expected, $results);
+ $this->assertSame($expectedMoreResults, $moreResults);
+ }
+
+ public function dataSearchSharees() {
+ return [
+ [
+ 'test', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE], 1, 2, [], [], ['results' => [], 'exact' => [], 'exactIdMatch' => false],
+ [
+ 'exact' => ['users' => [], 'groups' => [], 'remotes' => []],
+ 'users' => [],
+ 'groups' => [],
+ 'remotes' => [],
+ ], false
+ ],
+ [
+ 'test', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE], 1, 2, [], [], ['results' => [], 'exact' => [], 'exactIdMatch' => false],
+ [
+ 'exact' => ['users' => [], 'groups' => [], 'remotes' => []],
+ 'users' => [],
+ 'groups' => [],
+ 'remotes' => [],
+ ], false
+ ],
+ [
+ 'test', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE], 1, 2, [
+ ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ], [
+ ['label' => 'testgroup1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'testgroup1']],
+ ], [
+ 'results' => [['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']]], 'exact' => [], 'exactIdMatch' => false,
+ ],
+ [
+ 'exact' => ['users' => [], 'groups' => [], 'remotes' => []],
+ 'users' => [
+ ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ],
+ 'groups' => [
+ ['label' => 'testgroup1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'testgroup1']],
+ ],
+ 'remotes' => [
+ ['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']],
+ ],
+ ], true,
+ ],
+ // No groups requested
+ [
+ 'test', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_REMOTE], 1, 2, [
+ ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ], [], [
+ 'results' => [['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']]], 'exact' => [], 'exactIdMatch' => false
+ ],
+ [
+ 'exact' => ['users' => [], 'remotes' => []],
+ 'users' => [
+ ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ],
+ 'remotes' => [
+ ['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']],
+ ],
+ ], false,
+ ],
+ // Share type restricted to user - Only one user
+ [
+ 'test', [Share::SHARE_TYPE_USER], 1, 2, [
+ ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ], [], [],
+ [
+ 'exact' => ['users' => []],
+ 'users' => [
+ ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ],
+ ], false,
+ ],
+ // Share type restricted to user - Multipage result
+ [
+ 'test', [Share::SHARE_TYPE_USER], 1, 2, [
+ ['label' => 'test 1', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ['label' => 'test 2', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
+ ], [], [],
+ [
+ 'exact' => ['users' => []],
+ 'users' => [
+ ['label' => 'test 1', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ['label' => 'test 2', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
+ ],
+ ], true,
+ ],
+ ];
+ }
+}
diff --git a/tests/lib/Collaboration/Collaborators/UserPluginTest.php b/tests/lib/Collaboration/Collaborators/UserPluginTest.php
new file mode 100644
index 00000000000..7d6d9c645a0
--- /dev/null
+++ b/tests/lib/Collaboration/Collaborators/UserPluginTest.php
@@ -0,0 +1,445 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @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/>.
+ *
+ */
+
+namespace Test\Collaboration\Collaborators;
+
+use OC\Collaboration\Collaborators\SearchResult;
+use OC\Collaboration\Collaborators\UserPlugin;
+use OCP\Collaboration\Collaborators\ISearchResult;
+use OCP\IConfig;
+use OCP\IGroupManager;
+use OCP\IUser;
+use OCP\IUserManager;
+use OCP\IUserSession;
+use OCP\Share;
+use Test\TestCase;
+
+class UserPluginTest extends TestCase {
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
+ protected $config;
+
+ /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */
+ protected $userManager;
+
+ /** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */
+ protected $groupManager;
+
+ /** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */
+ protected $session;
+
+ /** @var UserPlugin */
+ protected $plugin;
+
+ /** @var ISearchResult */
+ protected $searchResult;
+
+ /** @var int */
+ protected $limit = 2;
+
+ /** @var int */
+ protected $offset = 0;
+
+ /** @var IUser|\PHPUnit_Framework_MockObject_MockObject */
+ protected $user;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->config = $this->createMock(IConfig::class);
+
+ $this->userManager = $this->createMock(IUserManager::class);
+
+ $this->groupManager = $this->createMock(IGroupManager::class);
+
+ $this->session = $this->createMock(IUserSession::class);
+
+ $this->searchResult = new SearchResult();
+
+ $this->user = $this->getUserMock('admin', 'Administrator');
+ }
+
+ public function instantiatePlugin() {
+ // cannot be done within setUp, because dependent mocks needs to be set
+ // up with configuration etc. first
+ $this->plugin = new UserPlugin(
+ $this->config,
+ $this->userManager,
+ $this->groupManager,
+ $this->session
+ );
+ }
+
+ public function getUserMock($uid, $displayName) {
+ $user = $this->createMock(IUser::class);
+
+ $user->expects($this->any())
+ ->method('getUID')
+ ->willReturn($uid);
+
+ $user->expects($this->any())
+ ->method('getDisplayName')
+ ->willReturn($displayName);
+
+ return $user;
+ }
+
+ public function dataGetUsers() {
+ return [
+ ['test', false, true, [], [], [], [], true, false],
+ ['test', false, false, [], [], [], [], true, false],
+ ['test', true, true, [], [], [], [], true, false],
+ ['test', true, false, [], [], [], [], true, false],
+ [
+ 'test', false, true, [], [],
+ [
+ ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
+ ], [], true, $this->getUserMock('test', 'Test')
+ ],
+ [
+ 'test', false, false, [], [],
+ [
+ ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
+ ], [], true, $this->getUserMock('test', 'Test')
+ ],
+ [
+ 'test', true, true, [], [],
+ [], [], true, $this->getUserMock('test', 'Test')
+ ],
+ [
+ 'test', true, false, [], [],
+ [], [], true, $this->getUserMock('test', 'Test')
+ ],
+ [
+ 'test', true, true, ['test-group'], [['test-group', 'test', 2, 0, []]],
+ [
+ ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
+ ], [], true, $this->getUserMock('test', 'Test')
+ ],
+ [
+ 'test', true, false, ['test-group'], [['test-group', 'test', 2, 0, []]],
+ [
+ ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
+ ], [], true, $this->getUserMock('test', 'Test')
+ ],
+ [
+ 'test',
+ false,
+ true,
+ [],
+ [
+ $this->getUserMock('test1', 'Test One'),
+ ],
+ [],
+ [
+ ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ],
+ true,
+ false,
+ ],
+ [
+ 'test',
+ false,
+ false,
+ [],
+ [
+ $this->getUserMock('test1', 'Test One'),
+ ],
+ [],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test',
+ false,
+ true,
+ [],
+ [
+ $this->getUserMock('test1', 'Test One'),
+ $this->getUserMock('test2', 'Test Two'),
+ ],
+ [],
+ [
+ ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ['label' => 'Test Two', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
+ ],
+ false,
+ false,
+ ],
+ [
+ 'test',
+ false,
+ false,
+ [],
+ [
+ $this->getUserMock('test1', 'Test One'),
+ $this->getUserMock('test2', 'Test Two'),
+ ],
+ [],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test',
+ false,
+ true,
+ [],
+ [
+ $this->getUserMock('test0', 'Test'),
+ $this->getUserMock('test1', 'Test One'),
+ $this->getUserMock('test2', 'Test Two'),
+ ],
+ [
+ ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test0']],
+ ],
+ [
+ ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ['label' => 'Test Two', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
+ ],
+ false,
+ false,
+ ],
+ [
+ 'test',
+ false,
+ false,
+ [],
+ [
+ $this->getUserMock('test0', 'Test'),
+ $this->getUserMock('test1', 'Test One'),
+ $this->getUserMock('test2', 'Test Two'),
+ ],
+ [
+ ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test0']],
+ ],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test',
+ true,
+ true,
+ ['abc', 'xyz'],
+ [
+ ['abc', 'test', 2, 0, ['test1' => 'Test One']],
+ ['xyz', 'test', 2, 0, []],
+ ],
+ [],
+ [
+ ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ],
+ true,
+ false,
+ ],
+ [
+ 'test',
+ true,
+ false,
+ ['abc', 'xyz'],
+ [
+ ['abc', 'test', 2, 0, ['test1' => 'Test One']],
+ ['xyz', 'test', 2, 0, []],
+ ],
+ [],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test',
+ true,
+ true,
+ ['abc', 'xyz'],
+ [
+ ['abc', 'test', 2, 0, [
+ 'test1' => 'Test One',
+ 'test2' => 'Test Two',
+ ]],
+ ['xyz', 'test', 2, 0, [
+ 'test1' => 'Test One',
+ 'test2' => 'Test Two',
+ ]],
+ ],
+ [],
+ [
+ ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ['label' => 'Test Two', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
+ ],
+ false,
+ false,
+ ],
+ [
+ 'test',
+ true,
+ false,
+ ['abc', 'xyz'],
+ [
+ ['abc', 'test', 2, 0, [
+ 'test1' => 'Test One',
+ 'test2' => 'Test Two',
+ ]],
+ ['xyz', 'test', 2, 0, [
+ 'test1' => 'Test One',
+ 'test2' => 'Test Two',
+ ]],
+ ],
+ [],
+ [],
+ true,
+ false,
+ ],
+ [
+ 'test',
+ true,
+ true,
+ ['abc', 'xyz'],
+ [
+ ['abc', 'test', 2, 0, [
+ 'test' => 'Test One',
+ ]],
+ ['xyz', 'test', 2, 0, [
+ 'test2' => 'Test Two',
+ ]],
+ ],
+ [
+ ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
+ ],
+ [
+ ['label' => 'Test Two', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
+ ],
+ false,
+ false,
+ ],
+ [
+ 'test',
+ true,
+ false,
+ ['abc', 'xyz'],
+ [
+ ['abc', 'test', 2, 0, [
+ 'test' => 'Test One',
+ ]],
+ ['xyz', 'test', 2, 0, [
+ 'test2' => 'Test Two',
+ ]],
+ ],
+ [
+ ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
+ ],
+ [],
+ true,
+ false,
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataGetUsers
+ *
+ * @param string $searchTerm
+ * @param bool $shareWithGroupOnly
+ * @param bool $shareeEnumeration
+ * @param array $groupResponse
+ * @param array $userResponse
+ * @param array $exactExpected
+ * @param array $expected
+ * @param bool $reachedEnd
+ * @param bool|IUser $singleUser
+ */
+ public function testSearch(
+ $searchTerm,
+ $shareWithGroupOnly,
+ $shareeEnumeration,
+ array $groupResponse,
+ array $userResponse,
+ array $exactExpected,
+ array $expected,
+ $reachedEnd,
+ $singleUser
+ ) {
+ $this->config->expects($this->any())
+ ->method('getAppValue')
+ ->willReturnCallback(
+ function($appName, $key, $default)
+ use ($shareWithGroupOnly, $shareeEnumeration)
+ {
+ if ($appName === 'core' && $key === 'shareapi_only_share_with_group_members') {
+ return $shareWithGroupOnly ? 'yes' : 'no';
+ } else if ($appName === 'core' && $key === 'shareapi_allow_share_dialog_user_enumeration') {
+ return $shareeEnumeration ? 'yes' : 'no';
+ }
+ return $default;
+ }
+ );
+
+ $this->instantiatePlugin();
+
+ $this->session->expects($this->any())
+ ->method('getUser')
+ ->willReturn($this->user);
+
+ if(!$shareWithGroupOnly) {
+ $this->userManager->expects($this->once())
+ ->method('searchDisplayName')
+ ->with($searchTerm, $this->limit, $this->offset)
+ ->willReturn($userResponse);
+ } else {
+ if ($singleUser !== false) {
+ $this->groupManager->expects($this->exactly(2))
+ ->method('getUserGroupIds')
+ ->withConsecutive(
+ $this->user,
+ $singleUser
+ )
+ ->willReturn($groupResponse);
+ } else {
+ $this->groupManager->expects($this->once())
+ ->method('getUserGroupIds')
+ ->with($this->user)
+ ->willReturn($groupResponse);
+ }
+
+ $this->groupManager->expects($this->exactly(sizeof($groupResponse)))
+ ->method('displayNamesInGroup')
+ ->with($this->anything(), $searchTerm, $this->limit, $this->offset)
+ ->willReturnMap($userResponse);
+ }
+
+ if ($singleUser !== false) {
+ $this->userManager->expects($this->once())
+ ->method('get')
+ ->with($searchTerm)
+ ->willReturn($singleUser);
+ }
+
+
+ $moreResults = $this->plugin->search($searchTerm, $this->limit, $this->offset, $this->searchResult);
+ $result = $this->searchResult->asArray();
+
+ $this->assertEquals($exactExpected, $result['exact']['users']);
+ $this->assertEquals($expected, $result['users']);
+ $this->assertSame($reachedEnd, $moreResults);
+ }
+}