From 5001036fd49cecdf1dcda1b4aed0be1b24d18c24 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 17 May 2016 10:31:50 +0200 Subject: Move classes from outside lib/ to PSR-4 --- apps/files_sharing/api/ocssharewrapper.php | 63 -- apps/files_sharing/api/remote.php | 229 -------- apps/files_sharing/api/share20ocs.php | 768 ------------------------- apps/files_sharing/api/sharees.php | 536 ----------------- apps/files_sharing/appinfo/app.php | 4 +- apps/files_sharing/appinfo/application.php | 145 ----- apps/files_sharing/appinfo/info.xml | 2 + apps/files_sharing/appinfo/routes.php | 3 +- apps/files_sharing/lib/API/OCSShareWrapper.php | 63 ++ apps/files_sharing/lib/API/Remote.php | 229 ++++++++ apps/files_sharing/lib/API/Share20OCS.php | 768 +++++++++++++++++++++++++ apps/files_sharing/lib/API/Sharees.php | 536 +++++++++++++++++ apps/files_sharing/lib/AppInfo/Application.php | 145 +++++ apps/files_sharing/tests/testcase.php | 2 +- 14 files changed, 1746 insertions(+), 1747 deletions(-) delete mode 100644 apps/files_sharing/api/ocssharewrapper.php delete mode 100644 apps/files_sharing/api/remote.php delete mode 100644 apps/files_sharing/api/share20ocs.php delete mode 100644 apps/files_sharing/api/sharees.php delete mode 100644 apps/files_sharing/appinfo/application.php create mode 100644 apps/files_sharing/lib/API/OCSShareWrapper.php create mode 100644 apps/files_sharing/lib/API/Remote.php create mode 100644 apps/files_sharing/lib/API/Share20OCS.php create mode 100644 apps/files_sharing/lib/API/Sharees.php create mode 100644 apps/files_sharing/lib/AppInfo/Application.php diff --git a/apps/files_sharing/api/ocssharewrapper.php b/apps/files_sharing/api/ocssharewrapper.php deleted file mode 100644 index 8ce9271a709..00000000000 --- a/apps/files_sharing/api/ocssharewrapper.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -namespace OCA\Files_Sharing\API; - -class OCSShareWrapper { - - /** - * @return Share20OCS - */ - private function getShare20OCS() { - return new Share20OCS( - \OC::$server->getShareManager(), - \OC::$server->getGroupManager(), - \OC::$server->getUserManager(), - \OC::$server->getRequest(), - \OC::$server->getRootFolder(), - \OC::$server->getURLGenerator(), - \OC::$server->getUserSession()->getUser(), - \OC::$server->getL10N('files_sharing') - ); - } - - public function getAllShares() { - return $this->getShare20OCS()->getShares(); - } - - public function createShare() { - return $this->getShare20OCS()->createShare(); - } - - public function getShare($params) { - $id = $params['id']; - return $this->getShare20OCS()->getShare($id); - } - - public function updateShare($params) { - $id = $params['id']; - return $this->getShare20OCS()->updateShare($id); - } - - public function deleteShare($params) { - $id = $params['id']; - return $this->getShare20OCS()->deleteShare($id); - } -} diff --git a/apps/files_sharing/api/remote.php b/apps/files_sharing/api/remote.php deleted file mode 100644 index 1b5eb28aa86..00000000000 --- a/apps/files_sharing/api/remote.php +++ /dev/null @@ -1,229 +0,0 @@ - - * @author Lukas Reschke - * @author Roeland Jago Douma - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\API; - -use OC\Files\Filesystem; -use OCA\FederatedFileSharing\DiscoveryManager; -use OCA\Files_Sharing\External\Manager; - -class Remote { - - /** - * Get list of pending remote shares - * - * @param array $params empty - * @return \OC_OCS_Result - */ - public static function getOpenShares($params) { - $discoveryManager = new DiscoveryManager( - \OC::$server->getMemCacheFactory(), - \OC::$server->getHTTPClientService() - ); - $externalManager = new Manager( - \OC::$server->getDatabaseConnection(), - Filesystem::getMountManager(), - Filesystem::getLoader(), - \OC::$server->getHTTPHelper(), - \OC::$server->getNotificationManager(), - $discoveryManager, - \OC_User::getUser() - ); - - return new \OC_OCS_Result($externalManager->getOpenShares()); - } - - /** - * Accept a remote share - * - * @param array $params contains the shareID 'id' which should be accepted - * @return \OC_OCS_Result - */ - public static function acceptShare($params) { - $discoveryManager = new DiscoveryManager( - \OC::$server->getMemCacheFactory(), - \OC::$server->getHTTPClientService() - ); - $externalManager = new Manager( - \OC::$server->getDatabaseConnection(), - Filesystem::getMountManager(), - Filesystem::getLoader(), - \OC::$server->getHTTPHelper(), - \OC::$server->getNotificationManager(), - $discoveryManager, - \OC_User::getUser() - ); - - if ($externalManager->acceptShare((int) $params['id'])) { - return new \OC_OCS_Result(); - } - - // Make sure the user has no notification for something that does not exist anymore. - $externalManager->processNotification((int) $params['id']); - - return new \OC_OCS_Result(null, 404, "wrong share ID, share doesn't exist."); - } - - /** - * Decline a remote share - * - * @param array $params contains the shareID 'id' which should be declined - * @return \OC_OCS_Result - */ - public static function declineShare($params) { - $discoveryManager = new DiscoveryManager( - \OC::$server->getMemCacheFactory(), - \OC::$server->getHTTPClientService() - ); - $externalManager = new Manager( - \OC::$server->getDatabaseConnection(), - Filesystem::getMountManager(), - Filesystem::getLoader(), - \OC::$server->getHTTPHelper(), - \OC::$server->getNotificationManager(), - $discoveryManager, - \OC_User::getUser() - ); - - if ($externalManager->declineShare((int) $params['id'])) { - return new \OC_OCS_Result(); - } - - // Make sure the user has no notification for something that does not exist anymore. - $externalManager->processNotification((int) $params['id']); - - return new \OC_OCS_Result(null, 404, "wrong share ID, share doesn't exist."); - } - - /** - * @param array $share Share with info from the share_external table - * @return array enriched share info with data from the filecache - */ - private static function extendShareInfo($share) { - $view = new \OC\Files\View('/' . \OC_User::getUser() . '/files/'); - $info = $view->getFileInfo($share['mountpoint']); - - $share['mimetype'] = $info->getMimetype(); - $share['mtime'] = $info->getMtime(); - $share['permissions'] = $info->getPermissions(); - $share['type'] = $info->getType(); - $share['file_id'] = $info->getId(); - - return $share; - } - - /** - * List accepted remote shares - * - * @param array $params - * @return \OC_OCS_Result - */ - public static function getShares($params) { - $discoveryManager = new DiscoveryManager( - \OC::$server->getMemCacheFactory(), - \OC::$server->getHTTPClientService() - ); - $externalManager = new Manager( - \OC::$server->getDatabaseConnection(), - Filesystem::getMountManager(), - Filesystem::getLoader(), - \OC::$server->getHTTPHelper(), - \OC::$server->getNotificationManager(), - $discoveryManager, - \OC_User::getUser() - ); - - $shares = $externalManager->getAcceptedShares(); - - $shares = array_map('self::extendShareInfo', $shares); - - return new \OC_OCS_Result($shares); - } - - /** - * Get info of a remote share - * - * @param array $params contains the shareID 'id' - * @return \OC_OCS_Result - */ - public static function getShare($params) { - $discoveryManager = new DiscoveryManager( - \OC::$server->getMemCacheFactory(), - \OC::$server->getHTTPClientService() - ); - $externalManager = new Manager( - \OC::$server->getDatabaseConnection(), - Filesystem::getMountManager(), - Filesystem::getLoader(), - \OC::$server->getHTTPHelper(), - \OC::$server->getNotificationManager(), - $discoveryManager, - \OC_User::getUser() - ); - - $shareInfo = $externalManager->getShare($params['id']); - - if ($shareInfo === false) { - return new \OC_OCS_Result(null, 404, 'share does not exist'); - } else { - $shareInfo = self::extendShareInfo($shareInfo); - return new \OC_OCS_Result($shareInfo); - } - } - - /** - * Unshare a remote share - * - * @param array $params contains the shareID 'id' which should be unshared - * @return \OC_OCS_Result - */ - public static function unshare($params) { - $discoveryManager = new DiscoveryManager( - \OC::$server->getMemCacheFactory(), - \OC::$server->getHTTPClientService() - ); - $externalManager = new Manager( - \OC::$server->getDatabaseConnection(), - Filesystem::getMountManager(), - Filesystem::getLoader(), - \OC::$server->getHTTPHelper(), - \OC::$server->getNotificationManager(), - $discoveryManager, - \OC_User::getUser() - ); - - $shareInfo = $externalManager->getShare($params['id']); - - if ($shareInfo === false) { - return new \OC_OCS_Result(null, 404, 'Share does not exist'); - } - - $mountPoint = '/' . \OC_User::getUser() . '/files' . $shareInfo['mountpoint']; - - if ($externalManager->removeShare($mountPoint) === true) { - return new \OC_OCS_Result(null); - } else { - return new \OC_OCS_Result(null, 403, 'Could not unshare'); - } - } -} diff --git a/apps/files_sharing/api/share20ocs.php b/apps/files_sharing/api/share20ocs.php deleted file mode 100644 index 28166b943b8..00000000000 --- a/apps/files_sharing/api/share20ocs.php +++ /dev/null @@ -1,768 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -namespace OCA\Files_Sharing\API; - -use OCP\Files\NotFoundException; -use OCP\IGroupManager; -use OCP\IL10N; -use OCP\IUserManager; -use OCP\IRequest; -use OCP\IURLGenerator; -use OCP\IUser; -use OCP\Files\IRootFolder; -use OCP\Lock\LockedException; -use OCP\Share; -use OCP\Share\IManager; -use OCP\Share\Exceptions\ShareNotFound; -use OCP\Share\Exceptions\GenericShareException; -use OCP\Lock\ILockingProvider; - -/** - * Class Share20OCS - * - * @package OCA\Files_Sharing\API - */ -class Share20OCS { - - /** @var IManager */ - private $shareManager; - /** @var IGroupManager */ - private $groupManager; - /** @var IUserManager */ - private $userManager; - /** @var IRequest */ - private $request; - /** @var IRootFolder */ - private $rootFolder; - /** @var IURLGenerator */ - private $urlGenerator; - /** @var IUser */ - private $currentUser; - /** @var IL10N */ - private $l; - - /** - * Share20OCS constructor. - * - * @param IManager $shareManager - * @param IGroupManager $groupManager - * @param IUserManager $userManager - * @param IRequest $request - * @param IRootFolder $rootFolder - * @param IURLGenerator $urlGenerator - * @param IUser $currentUser - */ - public function __construct( - IManager $shareManager, - IGroupManager $groupManager, - IUserManager $userManager, - IRequest $request, - IRootFolder $rootFolder, - IURLGenerator $urlGenerator, - IUser $currentUser, - IL10N $l10n - ) { - $this->shareManager = $shareManager; - $this->userManager = $userManager; - $this->groupManager = $groupManager; - $this->request = $request; - $this->rootFolder = $rootFolder; - $this->urlGenerator = $urlGenerator; - $this->currentUser = $currentUser; - $this->l = $l10n; - } - - /** - * Convert an IShare to an array for OCS output - * - * @param \OCP\Share\IShare $share - * @return array - * @throws NotFoundException In case the node can't be resolved. - */ - protected function formatShare(\OCP\Share\IShare $share) { - $sharedBy = $this->userManager->get($share->getSharedBy()); - // for federated shares the owner can be a remote user, in this - // case we use the initiator - if ($this->userManager->userExists($share->getShareOwner())) { - $shareOwner = $this->userManager->get($share->getShareOwner()); - $localUser = $share->getShareOwner(); - } else { - $shareOwner = $this->userManager->get($share->getSharedBy()); - $localUser = $share->getSharedBy(); - } - $result = [ - 'id' => $share->getId(), - 'share_type' => $share->getShareType(), - 'uid_owner' => $share->getSharedBy(), - 'displayname_owner' => $sharedBy !== null ? $sharedBy->getDisplayName() : $share->getSharedBy(), - 'permissions' => $share->getPermissions(), - 'stime' => $share->getShareTime()->getTimestamp(), - 'parent' => null, - 'expiration' => null, - 'token' => null, - 'uid_file_owner' => $share->getShareOwner(), - 'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(), - ]; - - $node = $share->getNode(); - $result['path'] = $this->rootFolder->getUserFolder($localUser)->getRelativePath($node->getPath()); - if ($node instanceOf \OCP\Files\Folder) { - $result['item_type'] = 'folder'; - } else { - $result['item_type'] = 'file'; - } - $result['mimetype'] = $node->getMimeType(); - $result['storage_id'] = $node->getStorage()->getId(); - $result['storage'] = $node->getStorage()->getCache()->getNumericStorageId(); - $result['item_source'] = $node->getId(); - $result['file_source'] = $node->getId(); - $result['file_parent'] = $node->getParent()->getId(); - $result['file_target'] = $share->getTarget(); - - if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { - $sharedWith = $this->userManager->get($share->getSharedWith()); - $result['share_with'] = $share->getSharedWith(); - $result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith(); - } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { - $result['share_with'] = $share->getSharedWith(); - $result['share_with_displayname'] = $share->getSharedWith(); - } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { - - $result['share_with'] = $share->getPassword(); - $result['share_with_displayname'] = $share->getPassword(); - - $result['token'] = $share->getToken(); - $result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]); - - $expiration = $share->getExpirationDate(); - if ($expiration !== null) { - $result['expiration'] = $expiration->format('Y-m-d 00:00:00'); - } - - } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) { - $result['share_with'] = $share->getSharedWith(); - $result['share_with_displayname'] = $share->getSharedWith(); - $result['token'] = $share->getToken(); - } - - $result['mail_send'] = $share->getMailSend() ? 1 : 0; - - return $result; - } - - /** - * Get a specific share by id - * - * @param string $id - * @return \OC_OCS_Result - */ - public function getShare($id) { - if (!$this->shareManager->shareApiEnabled()) { - return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled')); - } - - try { - $share = $this->getShareById($id); - } catch (ShareNotFound $e) { - return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); - } - - if ($this->canAccessShare($share)) { - try { - $share = $this->formatShare($share); - return new \OC_OCS_Result([$share]); - } catch (NotFoundException $e) { - //Fall trough - } - } - - return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); - } - - /** - * Delete a share - * - * @param string $id - * @return \OC_OCS_Result - */ - public function deleteShare($id) { - if (!$this->shareManager->shareApiEnabled()) { - return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled')); - } - - try { - $share = $this->getShareById($id); - } catch (ShareNotFound $e) { - return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); - } - - try { - $share->getNode()->lock(ILockingProvider::LOCK_SHARED); - } catch (LockedException $e) { - return new \OC_OCS_Result(null, 404, 'could not delete share'); - } - - if (!$this->canAccessShare($share)) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 404, $this->l->t('Could not delete share')); - } - - $this->shareManager->deleteShare($share); - - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - - return new \OC_OCS_Result(); - } - - /** - * @return \OC_OCS_Result - */ - public function createShare() { - $share = $this->shareManager->newShare(); - - if (!$this->shareManager->shareApiEnabled()) { - return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled')); - } - - // Verify path - $path = $this->request->getParam('path', null); - if ($path === null) { - return new \OC_OCS_Result(null, 404, $this->l->t('Please specify a file or folder path')); - } - - $userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); - try { - $path = $userFolder->get($path); - } catch (NotFoundException $e) { - return new \OC_OCS_Result(null, 404, $this->l->t('Wrong path, file/folder doesn\'t exist')); - } - - $share->setNode($path); - - try { - $share->getNode()->lock(ILockingProvider::LOCK_SHARED); - } catch (LockedException $e) { - return new \OC_OCS_Result(null, 404, 'Could not create share'); - } - - // Parse permissions (if available) - $permissions = $this->request->getParam('permissions', null); - if ($permissions === null) { - $permissions = \OCP\Constants::PERMISSION_ALL; - } else { - $permissions = (int)$permissions; - } - - if ($permissions < 0 || $permissions > \OCP\Constants::PERMISSION_ALL) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 404, 'invalid permissions'); - } - - // Shares always require read permissions - $permissions |= \OCP\Constants::PERMISSION_READ; - - if ($path instanceof \OCP\Files\File) { - // Single file shares should never have delete or create permissions - $permissions &= ~\OCP\Constants::PERMISSION_DELETE; - $permissions &= ~\OCP\Constants::PERMISSION_CREATE; - } - - /* - * Hack for https://github.com/owncloud/core/issues/22587 - * We check the permissions via webdav. But the permissions of the mount point - * do not equal the share permissions. Here we fix that for federated mounts. - */ - if ($path->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) { - $permissions &= ~($permissions & ~$path->getPermissions()); - } - - $shareWith = $this->request->getParam('shareWith', null); - $shareType = (int)$this->request->getParam('shareType', '-1'); - - if ($shareType === \OCP\Share::SHARE_TYPE_USER) { - // Valid user is required to share - if ($shareWith === null || !$this->userManager->userExists($shareWith)) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 404, $this->l->t('Please specify a valid user')); - } - $share->setSharedWith($shareWith); - $share->setPermissions($permissions); - } else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) { - if (!$this->shareManager->allowGroupSharing()) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 404, $this->l->t('Group sharing is disabled by the administrator')); - } - - // Valid group is required to share - if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 404, $this->l->t('Please specify a valid group')); - } - $share->setSharedWith($shareWith); - $share->setPermissions($permissions); - } else if ($shareType === \OCP\Share::SHARE_TYPE_LINK) { - //Can we even share links? - if (!$this->shareManager->shareApiAllowLinks()) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 404, $this->l->t('Public link sharing is disabled by the administrator')); - } - - /* - * For now we only allow 1 link share. - * Return the existing link share if this is a duplicate - */ - $existingShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $path, false, 1, 0); - if (!empty($existingShares)) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result($this->formatShare($existingShares[0])); - } - - $publicUpload = $this->request->getParam('publicUpload', null); - if ($publicUpload === 'true') { - // Check if public upload is allowed - if (!$this->shareManager->shareApiLinkAllowPublicUpload()) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 403, $this->l->t('Public upload disabled by the administrator')); - } - - // Public upload can only be set for folders - if ($path instanceof \OCP\Files\File) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 404, $this->l->t('Public upload is only possible for publicly shared folders')); - } - - $share->setPermissions( - \OCP\Constants::PERMISSION_READ | - \OCP\Constants::PERMISSION_CREATE | - \OCP\Constants::PERMISSION_UPDATE - ); - } else { - $share->setPermissions(\OCP\Constants::PERMISSION_READ); - } - - // Set password - $password = $this->request->getParam('password', ''); - - if ($password !== '') { - $share->setPassword($password); - } - - //Expire date - $expireDate = $this->request->getParam('expireDate', ''); - - if ($expireDate !== '') { - try { - $expireDate = $this->parseDate($expireDate); - $share->setExpirationDate($expireDate); - } catch (\Exception $e) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 404, $this->l->t('Invalid date, date format must be YYYY-MM-DD')); - } - } - - } else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) { - if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 403, $this->l->t('Sharing %s failed because the back end does not allow shares from type %s', [$path->getPath(), $shareType])); - } - - $share->setSharedWith($shareWith); - $share->setPermissions($permissions); - } else { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 400, $this->l->t('Unknown share type')); - } - - $share->setShareType($shareType); - $share->setSharedBy($this->currentUser->getUID()); - - try { - $share = $this->shareManager->createShare($share); - } catch (GenericShareException $e) { - $code = $e->getCode() === 0 ? 403 : $e->getCode(); - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, $code, $e->getHint()); - }catch (\Exception $e) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 403, $e->getMessage()); - } - - $output = $this->formatShare($share); - - $share->getNode()->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - return new \OC_OCS_Result($output); - } - - /** - * @param \OCP\Files\File|\OCP\Files\Folder $node - * @return \OC_OCS_Result - */ - private function getSharedWithMe($node = null) { - $userShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $node, -1, 0); - $groupShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $node, -1, 0); - - $shares = array_merge($userShares, $groupShares); - - $formatted = []; - foreach ($shares as $share) { - if ($this->canAccessShare($share)) { - try { - $formatted[] = $this->formatShare($share); - } catch (NotFoundException $e) { - // Ignore this share - } - } - } - - return new \OC_OCS_Result($formatted); - } - - /** - * @param \OCP\Files\Folder $folder - * @return \OC_OCS_Result - */ - private function getSharesInDir($folder) { - if (!($folder instanceof \OCP\Files\Folder)) { - return new \OC_OCS_Result(null, 400, $this->l->t('Not a directory')); - } - - $nodes = $folder->getDirectoryListing(); - /** @var \OCP\Share\IShare[] $shares */ - $shares = []; - foreach ($nodes as $node) { - $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $node, false, -1, 0)); - $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $node, false, -1, 0)); - $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $node, false, -1, 0)); - if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { - $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_REMOTE, $node, false, -1, 0)); - } - } - - $formatted = []; - foreach ($shares as $share) { - try { - $formatted[] = $this->formatShare($share); - } catch (NotFoundException $e) { - //Ignore this share - } - } - - return new \OC_OCS_Result($formatted); - } - - /** - * The getShares function. - * - * - Get shares by the current user - * - Get shares by the current user and reshares (?reshares=true) - * - Get shares with the current user (?shared_with_me=true) - * - Get shares for a specific path (?path=...) - * - Get all shares in a folder (?subfiles=true&path=..) - * - * @return \OC_OCS_Result - */ - public function getShares() { - if (!$this->shareManager->shareApiEnabled()) { - return new \OC_OCS_Result(); - } - - $sharedWithMe = $this->request->getParam('shared_with_me', null); - $reshares = $this->request->getParam('reshares', null); - $subfiles = $this->request->getParam('subfiles'); - $path = $this->request->getParam('path', null); - - if ($path !== null) { - $userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); - try { - $path = $userFolder->get($path); - $path->lock(ILockingProvider::LOCK_SHARED); - } catch (\OCP\Files\NotFoundException $e) { - return new \OC_OCS_Result(null, 404, $this->l->t('Wrong path, file/folder doesn\'t exist')); - } catch (LockedException $e) { - return new \OC_OCS_Result(null, 404, $this->l->t('Could not lock path')); - } - } - - if ($sharedWithMe === 'true') { - $result = $this->getSharedWithMe($path); - if ($path !== null) { - $path->unlock(ILockingProvider::LOCK_SHARED); - } - return $result; - } - - if ($subfiles === 'true') { - $result = $this->getSharesInDir($path); - if ($path !== null) { - $path->unlock(ILockingProvider::LOCK_SHARED); - } - return $result; - } - - if ($reshares === 'true') { - $reshares = true; - } else { - $reshares = false; - } - - // Get all shares - $userShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $path, $reshares, -1, 0); - $groupShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0); - $linkShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0); - $shares = array_merge($userShares, $groupShares, $linkShares); - - if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { - $federatedShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0); - $shares = array_merge($shares, $federatedShares); - } - - - $formatted = []; - foreach ($shares as $share) { - try { - $formatted[] = $this->formatShare($share); - } catch (NotFoundException $e) { - //Ignore share - } - } - - if ($path !== null) { - $path->unlock(ILockingProvider::LOCK_SHARED); - } - - return new \OC_OCS_Result($formatted); - } - - /** - * @param int $id - * @return \OC_OCS_Result - */ - public function updateShare($id) { - if (!$this->shareManager->shareApiEnabled()) { - return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled')); - } - - try { - $share = $this->getShareById($id); - } catch (ShareNotFound $e) { - return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); - } - - $share->getNode()->lock(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - if (!$this->canAccessShare($share)) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); - } - - $permissions = $this->request->getParam('permissions', null); - $password = $this->request->getParam('password', null); - $publicUpload = $this->request->getParam('publicUpload', null); - $expireDate = $this->request->getParam('expireDate', null); - - /* - * expirationdate, password and publicUpload only make sense for link shares - */ - if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { - if ($permissions === null && $password === null && $publicUpload === null && $expireDate === null) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 400, 'Wrong or no update parameter given'); - } - - $newPermissions = null; - if ($publicUpload === 'true') { - $newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE; - } else if ($publicUpload === 'false') { - $newPermissions = \OCP\Constants::PERMISSION_READ; - } - - if ($permissions !== null) { - $newPermissions = (int)$permissions; - } - - if ($newPermissions !== null && - $newPermissions !== \OCP\Constants::PERMISSION_READ && - $newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE)) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 400, $this->l->t('Can\'t change permissions for public share links')); - } - - if ($newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE)) { - if (!$this->shareManager->shareApiLinkAllowPublicUpload()) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 403, $this->l->t('Public upload disabled by the administrator')); - } - - if (!($share->getNode() instanceof \OCP\Files\Folder)) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 400, $this->l->t('Public upload is only possible for publicly shared folders')); - } - } - - if ($newPermissions !== null) { - $share->setPermissions($newPermissions); - } - - if ($expireDate === '') { - $share->setExpirationDate(null); - } else if ($expireDate !== null) { - try { - $expireDate = $this->parseDate($expireDate); - } catch (\Exception $e) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 400, $e->getMessage()); - } - $share->setExpirationDate($expireDate); - } - - if ($password === '') { - $share->setPassword(null); - } else if ($password !== null) { - $share->setPassword($password); - } - - } else { - // For other shares only permissions is valid. - if ($permissions === null) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 400, $this->l->t('Wrong or no update parameter given')); - } else { - $permissions = (int)$permissions; - $share->setPermissions($permissions); - } - } - - if ($permissions !== null) { - /* Check if this is an incomming share */ - $incomingShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $share->getNode(), -1, 0); - $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0)); - - if (!empty($incomingShares)) { - $maxPermissions = 0; - foreach ($incomingShares as $incomingShare) { - $maxPermissions |= $incomingShare->getPermissions(); - } - - if ($share->getPermissions() & ~$maxPermissions) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 404, $this->l->t('Cannot increase permissions')); - } - } - } - - - try { - $share = $this->shareManager->updateShare($share); - } catch (\Exception $e) { - $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC_OCS_Result(null, 400, $e->getMessage()); - } - - $share->getNode()->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - return new \OC_OCS_Result($this->formatShare($share)); - } - - /** - * @param \OCP\Share\IShare $share - * @return bool - */ - protected function canAccessShare(\OCP\Share\IShare $share) { - // A file with permissions 0 can't be accessed by us. So Don't show it - if ($share->getPermissions() === 0) { - return false; - } - - // Owner of the file and the sharer of the file can always get share - if ($share->getShareOwner() === $this->currentUser->getUID() || - $share->getSharedBy() === $this->currentUser->getUID() - ) { - return true; - } - - // If the share is shared with you (or a group you are a member of) - if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && - $share->getSharedWith() === $this->currentUser->getUID()) { - return true; - } - - if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { - $sharedWith = $this->groupManager->get($share->getSharedWith()); - if ($sharedWith->inGroup($this->currentUser)) { - return true; - } - } - - return false; - } - - /** - * Make sure that the passed date is valid ISO 8601 - * So YYYY-MM-DD - * If not throw an exception - * - * @param string $expireDate - * - * @throws \Exception - * @return \DateTime - */ - private function parseDate($expireDate) { - try { - $date = new \DateTime($expireDate); - } catch (\Exception $e) { - throw new \Exception('Invalid date. Format must be YYYY-MM-DD'); - } - - if ($date === false) { - throw new \Exception('Invalid date. Format must be YYYY-MM-DD'); - } - - $date->setTime(0,0,0); - - return $date; - } - - /** - * Since we have multiple providers but the OCS Share API v1 does - * not support this we need to check all backends. - * - * @param string $id - * @return \OCP\Share\IShare - * @throws ShareNotFound - */ - private function getShareById($id) { - $share = null; - - // First check if it is an internal share. - try { - $share = $this->shareManager->getShareById('ocinternal:'.$id); - } catch (ShareNotFound $e) { - if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { - throw new ShareNotFound(); - } - - $share = $this->shareManager->getShareById('ocFederatedSharing:' . $id); - } - - return $share; - } -} diff --git a/apps/files_sharing/api/sharees.php b/apps/files_sharing/api/sharees.php deleted file mode 100644 index 4e005c5e26c..00000000000 --- a/apps/files_sharing/api/sharees.php +++ /dev/null @@ -1,536 +0,0 @@ - - * @author Joas Schilling - * @author Roeland Jago Douma - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -namespace OCA\Files_Sharing\API; - -use OCP\AppFramework\Http; -use OCP\Contacts\IManager; -use OCP\IGroup; -use OCP\IGroupManager; -use OCP\ILogger; -use OCP\IRequest; -use OCP\IUser; -use OCP\IUserManager; -use OCP\IConfig; -use OCP\IUserSession; -use OCP\IURLGenerator; -use OCP\Share; - -class Sharees { - - /** @var IGroupManager */ - protected $groupManager; - - /** @var IUserManager */ - protected $userManager; - - /** @var IManager */ - protected $contactsManager; - - /** @var IConfig */ - protected $config; - - /** @var IUserSession */ - protected $userSession; - - /** @var IRequest */ - protected $request; - - /** @var IURLGenerator */ - protected $urlGenerator; - - /** @var ILogger */ - protected $logger; - - /** @var \OCP\Share\IManager */ - protected $shareManager; - - /** @var bool */ - protected $shareWithGroupOnly = false; - - /** @var bool */ - protected $shareeEnumeration = true; - - /** @var int */ - protected $offset = 0; - - /** @var int */ - protected $limit = 10; - - /** @var array */ - protected $result = [ - 'exact' => [ - 'users' => [], - 'groups' => [], - 'remotes' => [], - ], - 'users' => [], - 'groups' => [], - 'remotes' => [], - ]; - - protected $reachedEndFor = []; - - /** - * @param IGroupManager $groupManager - * @param IUserManager $userManager - * @param IManager $contactsManager - * @param IConfig $config - * @param IUserSession $userSession - * @param IURLGenerator $urlGenerator - * @param IRequest $request - * @param ILogger $logger - * @param \OCP\Share\IManager $shareManager - */ - public function __construct(IGroupManager $groupManager, - IUserManager $userManager, - IManager $contactsManager, - IConfig $config, - IUserSession $userSession, - IURLGenerator $urlGenerator, - IRequest $request, - ILogger $logger, - \OCP\Share\IManager $shareManager) { - $this->groupManager = $groupManager; - $this->userManager = $userManager; - $this->contactsManager = $contactsManager; - $this->config = $config; - $this->userSession = $userSession; - $this->urlGenerator = $urlGenerator; - $this->request = $request; - $this->logger = $logger; - $this->shareManager = $shareManager; - } - - /** - * @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; - foreach ($users as $uid => $userDisplayName) { - if (strtolower($uid) === strtolower($search) || strtolower($userDisplayName) === strtolower($search)) { - if (strtolower($uid) === strtolower($search)) { - $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); - $groups = 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); - $groups = array_intersect($groups, $userGroups); - } - - foreach ($groups as $gid) { - if (strtolower($gid) === strtolower($search)) { - $this->result['exact']['groups'][] = [ - 'label' => $gid, - 'value' => [ - 'shareType' => Share::SHARE_TYPE_GROUP, - 'shareWith' => $gid, - ], - ]; - } else { - $this->result['groups'][] = [ - 'label' => $gid, - '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->getGID(), - 'value' => [ - 'shareType' => Share::SHARE_TYPE_GROUP, - 'shareWith' => $group->getGID(), - ], - ]); - } - } - - if (!$this->shareeEnumeration) { - $this->result['groups'] = []; - } - } - - /** - * @param string $search - * @return array possible sharees - */ - protected function getRemote($search) { - $this->result['remotes'] = []; - - // Search in contacts - //@todo Pagination missing - $addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN']); - $foundRemoteById = false; - foreach ($addressBookContacts as $contact) { - if (isset($contact['isLocalSystemBook'])) { - continue; - } - if (isset($contact['CLOUD'])) { - $cloudIds = $contact['CLOUD']; - if (!is_array($cloudIds)) { - $cloudIds = [$cloudIds]; - } - foreach ($cloudIds as $cloudId) { - list(, $serverUrl) = $this->splitUserRemote($cloudId); - if (strtolower($contact['FN']) === strtolower($search) || strtolower($cloudId) === strtolower($search)) { - if (strtolower($cloudId) === strtolower($search)) { - $foundRemoteById = true; - } - $this->result['exact']['remotes'][] = [ - 'label' => $contact['FN'], - 'value' => [ - 'shareType' => Share::SHARE_TYPE_REMOTE, - 'shareWith' => $cloudId, - 'server' => $serverUrl, - ], - ]; - } else { - $this->result['remotes'][] = [ - 'label' => $contact['FN'], - 'value' => [ - 'shareType' => Share::SHARE_TYPE_REMOTE, - 'shareWith' => $cloudId, - 'server' => $serverUrl, - ], - ]; - } - } - } - } - - if (!$this->shareeEnumeration) { - $this->result['remotes'] = []; - } - - if (!$foundRemoteById && substr_count($search, '@') >= 1 && substr_count($search, ' ') === 0 && $this->offset === 0) { - $this->result['exact']['remotes'][] = [ - 'label' => $search, - 'value' => [ - 'shareType' => Share::SHARE_TYPE_REMOTE, - 'shareWith' => $search, - ], - ]; - } - - $this->reachedEndFor[] = 'remotes'; - } - - /** - * split user and remote from federated cloud id - * - * @param string $address federated share address - * @return array [user, remoteURL] - * @throws \Exception - */ - public function splitUserRemote($address) { - if (strpos($address, '@') === false) { - throw new \Exception('Invalid Federated Cloud ID'); - } - - // Find the first character that is not allowed in user names - $id = str_replace('\\', '/', $address); - $posSlash = strpos($id, '/'); - $posColon = strpos($id, ':'); - - if ($posSlash === false && $posColon === false) { - $invalidPos = strlen($id); - } else if ($posSlash === false) { - $invalidPos = $posColon; - } else if ($posColon === false) { - $invalidPos = $posSlash; - } else { - $invalidPos = min($posSlash, $posColon); - } - - // Find the last @ before $invalidPos - $pos = $lastAtPos = 0; - while ($lastAtPos !== false && $lastAtPos <= $invalidPos) { - $pos = $lastAtPos; - $lastAtPos = strpos($id, '@', $pos + 1); - } - - if ($pos !== false) { - $user = substr($id, 0, $pos); - $remote = substr($id, $pos + 1); - $remote = $this->fixRemoteURL($remote); - if (!empty($user) && !empty($remote)) { - return array($user, $remote); - } - } - - throw new \Exception('Invalid Federated Cloud ID'); - } - - /** - * 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; - } - - /** - * @return \OC_OCS_Result - */ - public function search() { - $search = isset($_GET['search']) ? (string) $_GET['search'] : ''; - $itemType = isset($_GET['itemType']) ? (string) $_GET['itemType'] : null; - $page = isset($_GET['page']) ? (int) $_GET['page'] : 1; - $perPage = isset($_GET['perPage']) ? (int) $_GET['perPage'] : 200; - - if ($perPage <= 0) { - return new \OC_OCS_Result(null, Http::STATUS_BAD_REQUEST, 'Invalid perPage argument'); - } - if ($page <= 0) { - return new \OC_OCS_Result(null, Http::STATUS_BAD_REQUEST, 'Invalid page'); - } - - $shareTypes = [ - Share::SHARE_TYPE_USER, - ]; - - if ($this->shareManager->allowGroupSharing()) { - $shareTypes[] = Share::SHARE_TYPE_GROUP; - } - - $shareTypes[] = Share::SHARE_TYPE_REMOTE; - - if (isset($_GET['shareType']) && is_array($_GET['shareType'])) { - $shareTypes = array_intersect($shareTypes, $_GET['shareType']); - sort($shareTypes); - - } else if (isset($_GET['shareType']) && is_numeric($_GET['shareType'])) { - $shareTypes = array_intersect($shareTypes, [(int) $_GET['shareType']]); - sort($shareTypes); - } - - if (in_array(Share::SHARE_TYPE_REMOTE, $shareTypes) && !$this->isRemoteSharingAllowed($itemType)) { - // Remove remote shares from type array, because it is not allowed. - $shareTypes = array_diff($shareTypes, [Share::SHARE_TYPE_REMOTE]); - } - - $this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes'; - $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes'; - $this->limit = (int) $perPage; - $this->offset = $perPage * ($page - 1); - - return $this->searchSharees($search, $itemType, $shareTypes, $page, $perPage); - } - - /** - * Method to get out the static call for better testing - * - * @param string $itemType - * @return bool - */ - protected function isRemoteSharingAllowed($itemType) { - try { - $backend = 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 - * @return \OC_OCS_Result - */ - protected function searchSharees($search, $itemType, array $shareTypes, $page, $perPage) { - // Verify arguments - if ($itemType === null) { - return new \OC_OCS_Result(null, Http::STATUS_BAD_REQUEST, '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 remote - if (in_array(Share::SHARE_TYPE_REMOTE, $shareTypes)) { - $this->getRemote($search); - } - - $response = new \OC_OCS_Result($this->result); - $response->setItemsPerPage($perPage); - - if (sizeof($this->reachedEndFor) < 3) { - $response->addHeader('Link', $this->getPaginationLink($page, [ - 'search' => $search, - 'itemType' => $itemType, - 'shareType' => $shareTypes, - 'perPage' => $perPage, - ])); - } - - return $response; - } - - /** - * Generates a bunch of pagination links for the current page - * - * @param int $page Current page - * @param array $params Parameters for the URL - * @return string - */ - protected function getPaginationLink($page, array $params) { - if ($this->isV2()) { - $url = $this->urlGenerator->getAbsoluteURL('/ocs/v2.php/apps/files_sharing/api/v1/sharees') . '?'; - } else { - $url = $this->urlGenerator->getAbsoluteURL('/ocs/v1.php/apps/files_sharing/api/v1/sharees') . '?'; - } - $params['page'] = $page + 1; - $link = '<' . $url . http_build_query($params) . '>; rel="next"'; - - return $link; - } - - /** - * @return bool - */ - protected function isV2() { - return $this->request->getScriptName() === '/ocs/v2.php'; - } -} diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php index 32eee9b6c9c..e96269d1148 100644 --- a/apps/files_sharing/appinfo/app.php +++ b/apps/files_sharing/appinfo/app.php @@ -26,15 +26,13 @@ * */ -namespace OCA\Files_Sharing\Appinfo; - $l = \OC::$server->getL10N('files_sharing'); \OC::$CLASSPATH['OC_Share_Backend_File'] = 'files_sharing/lib/share/file.php'; \OC::$CLASSPATH['OC_Share_Backend_Folder'] = 'files_sharing/lib/share/folder.php'; \OC::$CLASSPATH['OC\Files\Storage\Shared'] = 'files_sharing/lib/sharedstorage.php'; -$application = new Application(); +$application = new \OCA\Files_Sharing\AppInfo\Application(); $application->registerMountProviders(); \OCA\Files_Sharing\Helper::registerHooks(); diff --git a/apps/files_sharing/appinfo/application.php b/apps/files_sharing/appinfo/application.php deleted file mode 100644 index b17e213e2e2..00000000000 --- a/apps/files_sharing/appinfo/application.php +++ /dev/null @@ -1,145 +0,0 @@ - - * @author Lukas Reschke - * @author Robin Appelman - * @author Roeland Jago Douma - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\AppInfo; - -use OCA\FederatedFileSharing\DiscoveryManager; -use OCA\Files_Sharing\MountProvider; -use OCP\AppFramework\App; -use OC\AppFramework\Utility\SimpleContainer; -use OCA\Files_Sharing\Controllers\ExternalSharesController; -use OCA\Files_Sharing\Controllers\ShareController; -use OCA\Files_Sharing\Middleware\SharingCheckMiddleware; -use \OCP\IContainer; -use OCA\Files_Sharing\Capabilities; - -class Application extends App { - public function __construct(array $urlParams = array()) { - parent::__construct('files_sharing', $urlParams); - - $container = $this->getContainer(); - $server = $container->getServer(); - - /** - * Controllers - */ - $container->registerService('ShareController', function (SimpleContainer $c) use ($server) { - $federatedSharingApp = new \OCA\FederatedFileSharing\AppInfo\Application('federatedfilesharing'); - return new ShareController( - $c->query('AppName'), - $c->query('Request'), - $server->getConfig(), - $server->getURLGenerator(), - $server->getUserManager(), - $server->getLogger(), - $server->getActivityManager(), - $server->getShareManager(), - $server->getSession(), - $server->getPreviewManager(), - $server->getRootFolder(), - $federatedSharingApp->getFederatedShareProvider() - ); - }); - $container->registerService('ExternalSharesController', function (SimpleContainer $c) { - return new ExternalSharesController( - $c->query('AppName'), - $c->query('Request'), - $c->query('ExternalManager'), - $c->query('HttpClientService') - ); - }); - - /** - * Core class wrappers - */ - $container->registerService('HttpClientService', function (SimpleContainer $c) use ($server) { - return $server->getHTTPClientService(); - }); - $container->registerService('ExternalManager', function (SimpleContainer $c) use ($server) { - $user = $server->getUserSession()->getUser(); - $uid = $user ? $user->getUID() : null; - $discoveryManager = new DiscoveryManager( - \OC::$server->getMemCacheFactory(), - \OC::$server->getHTTPClientService() - ); - return new \OCA\Files_Sharing\External\Manager( - $server->getDatabaseConnection(), - \OC\Files\Filesystem::getMountManager(), - \OC\Files\Filesystem::getLoader(), - $server->getHTTPHelper(), - $server->getNotificationManager(), - $discoveryManager, - $uid - ); - }); - - /** - * Middleware - */ - $container->registerService('SharingCheckMiddleware', function (SimpleContainer $c) use ($server) { - return new SharingCheckMiddleware( - $c->query('AppName'), - $server->getConfig(), - $server->getAppManager(), - $c['ControllerMethodReflector'] - ); - }); - - // Execute middlewares - $container->registerMiddleware('SharingCheckMiddleware'); - - $container->registerService('MountProvider', function (IContainer $c) { - /** @var \OCP\IServerContainer $server */ - $server = $c->query('ServerContainer'); - return new MountProvider( - $server->getConfig(), - $server->getShareManager() - ); - }); - - $container->registerService('ExternalMountProvider', function (IContainer $c) { - /** @var \OCP\IServerContainer $server */ - $server = $c->query('ServerContainer'); - return new \OCA\Files_Sharing\External\MountProvider( - $server->getDatabaseConnection(), - function() use ($c) { - return $c->query('ExternalManager'); - } - ); - }); - - /* - * Register capabilities - */ - $container->registerCapability('OCA\Files_Sharing\Capabilities'); - } - - public function registerMountProviders() { - /** @var \OCP\IServerContainer $server */ - $server = $this->getContainer()->query('ServerContainer'); - $mountProviderCollection = $server->getMountProviderCollection(); - $mountProviderCollection->registerProvider($this->getContainer()->query('MountProvider')); - $mountProviderCollection->registerProvider($this->getContainer()->query('ExternalMountProvider')); - } -} diff --git a/apps/files_sharing/appinfo/info.xml b/apps/files_sharing/appinfo/info.xml index 7e49e267275..f6e3053961f 100644 --- a/apps/files_sharing/appinfo/info.xml +++ b/apps/files_sharing/appinfo/info.xml @@ -21,6 +21,8 @@ Turning the feature off removes shared files and folders on the server for all s public.php + Files_Sharing + OCA\Files_sharing\Lib\DeleteOrphanedSharesJob OCA\Files_sharing\ExpireSharesJob diff --git a/apps/files_sharing/appinfo/routes.php b/apps/files_sharing/appinfo/routes.php index 80632f0fedf..2e11e0e62bc 100644 --- a/apps/files_sharing/appinfo/routes.php +++ b/apps/files_sharing/appinfo/routes.php @@ -24,11 +24,10 @@ * along with this program. If not, see * */ -namespace OCA\Files_Sharing\AppInfo; use OCP\API; -$application = new Application(); +$application = new \OCA\Files_Sharing\AppInfo\Application(); $application->registerRoutes($this, [ 'resources' => [ 'ExternalShares' => ['url' => '/api/externalShares'], diff --git a/apps/files_sharing/lib/API/OCSShareWrapper.php b/apps/files_sharing/lib/API/OCSShareWrapper.php new file mode 100644 index 00000000000..8ce9271a709 --- /dev/null +++ b/apps/files_sharing/lib/API/OCSShareWrapper.php @@ -0,0 +1,63 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ +namespace OCA\Files_Sharing\API; + +class OCSShareWrapper { + + /** + * @return Share20OCS + */ + private function getShare20OCS() { + return new Share20OCS( + \OC::$server->getShareManager(), + \OC::$server->getGroupManager(), + \OC::$server->getUserManager(), + \OC::$server->getRequest(), + \OC::$server->getRootFolder(), + \OC::$server->getURLGenerator(), + \OC::$server->getUserSession()->getUser(), + \OC::$server->getL10N('files_sharing') + ); + } + + public function getAllShares() { + return $this->getShare20OCS()->getShares(); + } + + public function createShare() { + return $this->getShare20OCS()->createShare(); + } + + public function getShare($params) { + $id = $params['id']; + return $this->getShare20OCS()->getShare($id); + } + + public function updateShare($params) { + $id = $params['id']; + return $this->getShare20OCS()->updateShare($id); + } + + public function deleteShare($params) { + $id = $params['id']; + return $this->getShare20OCS()->deleteShare($id); + } +} diff --git a/apps/files_sharing/lib/API/Remote.php b/apps/files_sharing/lib/API/Remote.php new file mode 100644 index 00000000000..1b5eb28aa86 --- /dev/null +++ b/apps/files_sharing/lib/API/Remote.php @@ -0,0 +1,229 @@ + + * @author Lukas Reschke + * @author Roeland Jago Douma + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\API; + +use OC\Files\Filesystem; +use OCA\FederatedFileSharing\DiscoveryManager; +use OCA\Files_Sharing\External\Manager; + +class Remote { + + /** + * Get list of pending remote shares + * + * @param array $params empty + * @return \OC_OCS_Result + */ + public static function getOpenShares($params) { + $discoveryManager = new DiscoveryManager( + \OC::$server->getMemCacheFactory(), + \OC::$server->getHTTPClientService() + ); + $externalManager = new Manager( + \OC::$server->getDatabaseConnection(), + Filesystem::getMountManager(), + Filesystem::getLoader(), + \OC::$server->getHTTPHelper(), + \OC::$server->getNotificationManager(), + $discoveryManager, + \OC_User::getUser() + ); + + return new \OC_OCS_Result($externalManager->getOpenShares()); + } + + /** + * Accept a remote share + * + * @param array $params contains the shareID 'id' which should be accepted + * @return \OC_OCS_Result + */ + public static function acceptShare($params) { + $discoveryManager = new DiscoveryManager( + \OC::$server->getMemCacheFactory(), + \OC::$server->getHTTPClientService() + ); + $externalManager = new Manager( + \OC::$server->getDatabaseConnection(), + Filesystem::getMountManager(), + Filesystem::getLoader(), + \OC::$server->getHTTPHelper(), + \OC::$server->getNotificationManager(), + $discoveryManager, + \OC_User::getUser() + ); + + if ($externalManager->acceptShare((int) $params['id'])) { + return new \OC_OCS_Result(); + } + + // Make sure the user has no notification for something that does not exist anymore. + $externalManager->processNotification((int) $params['id']); + + return new \OC_OCS_Result(null, 404, "wrong share ID, share doesn't exist."); + } + + /** + * Decline a remote share + * + * @param array $params contains the shareID 'id' which should be declined + * @return \OC_OCS_Result + */ + public static function declineShare($params) { + $discoveryManager = new DiscoveryManager( + \OC::$server->getMemCacheFactory(), + \OC::$server->getHTTPClientService() + ); + $externalManager = new Manager( + \OC::$server->getDatabaseConnection(), + Filesystem::getMountManager(), + Filesystem::getLoader(), + \OC::$server->getHTTPHelper(), + \OC::$server->getNotificationManager(), + $discoveryManager, + \OC_User::getUser() + ); + + if ($externalManager->declineShare((int) $params['id'])) { + return new \OC_OCS_Result(); + } + + // Make sure the user has no notification for something that does not exist anymore. + $externalManager->processNotification((int) $params['id']); + + return new \OC_OCS_Result(null, 404, "wrong share ID, share doesn't exist."); + } + + /** + * @param array $share Share with info from the share_external table + * @return array enriched share info with data from the filecache + */ + private static function extendShareInfo($share) { + $view = new \OC\Files\View('/' . \OC_User::getUser() . '/files/'); + $info = $view->getFileInfo($share['mountpoint']); + + $share['mimetype'] = $info->getMimetype(); + $share['mtime'] = $info->getMtime(); + $share['permissions'] = $info->getPermissions(); + $share['type'] = $info->getType(); + $share['file_id'] = $info->getId(); + + return $share; + } + + /** + * List accepted remote shares + * + * @param array $params + * @return \OC_OCS_Result + */ + public static function getShares($params) { + $discoveryManager = new DiscoveryManager( + \OC::$server->getMemCacheFactory(), + \OC::$server->getHTTPClientService() + ); + $externalManager = new Manager( + \OC::$server->getDatabaseConnection(), + Filesystem::getMountManager(), + Filesystem::getLoader(), + \OC::$server->getHTTPHelper(), + \OC::$server->getNotificationManager(), + $discoveryManager, + \OC_User::getUser() + ); + + $shares = $externalManager->getAcceptedShares(); + + $shares = array_map('self::extendShareInfo', $shares); + + return new \OC_OCS_Result($shares); + } + + /** + * Get info of a remote share + * + * @param array $params contains the shareID 'id' + * @return \OC_OCS_Result + */ + public static function getShare($params) { + $discoveryManager = new DiscoveryManager( + \OC::$server->getMemCacheFactory(), + \OC::$server->getHTTPClientService() + ); + $externalManager = new Manager( + \OC::$server->getDatabaseConnection(), + Filesystem::getMountManager(), + Filesystem::getLoader(), + \OC::$server->getHTTPHelper(), + \OC::$server->getNotificationManager(), + $discoveryManager, + \OC_User::getUser() + ); + + $shareInfo = $externalManager->getShare($params['id']); + + if ($shareInfo === false) { + return new \OC_OCS_Result(null, 404, 'share does not exist'); + } else { + $shareInfo = self::extendShareInfo($shareInfo); + return new \OC_OCS_Result($shareInfo); + } + } + + /** + * Unshare a remote share + * + * @param array $params contains the shareID 'id' which should be unshared + * @return \OC_OCS_Result + */ + public static function unshare($params) { + $discoveryManager = new DiscoveryManager( + \OC::$server->getMemCacheFactory(), + \OC::$server->getHTTPClientService() + ); + $externalManager = new Manager( + \OC::$server->getDatabaseConnection(), + Filesystem::getMountManager(), + Filesystem::getLoader(), + \OC::$server->getHTTPHelper(), + \OC::$server->getNotificationManager(), + $discoveryManager, + \OC_User::getUser() + ); + + $shareInfo = $externalManager->getShare($params['id']); + + if ($shareInfo === false) { + return new \OC_OCS_Result(null, 404, 'Share does not exist'); + } + + $mountPoint = '/' . \OC_User::getUser() . '/files' . $shareInfo['mountpoint']; + + if ($externalManager->removeShare($mountPoint) === true) { + return new \OC_OCS_Result(null); + } else { + return new \OC_OCS_Result(null, 403, 'Could not unshare'); + } + } +} diff --git a/apps/files_sharing/lib/API/Share20OCS.php b/apps/files_sharing/lib/API/Share20OCS.php new file mode 100644 index 00000000000..28166b943b8 --- /dev/null +++ b/apps/files_sharing/lib/API/Share20OCS.php @@ -0,0 +1,768 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ +namespace OCA\Files_Sharing\API; + +use OCP\Files\NotFoundException; +use OCP\IGroupManager; +use OCP\IL10N; +use OCP\IUserManager; +use OCP\IRequest; +use OCP\IURLGenerator; +use OCP\IUser; +use OCP\Files\IRootFolder; +use OCP\Lock\LockedException; +use OCP\Share; +use OCP\Share\IManager; +use OCP\Share\Exceptions\ShareNotFound; +use OCP\Share\Exceptions\GenericShareException; +use OCP\Lock\ILockingProvider; + +/** + * Class Share20OCS + * + * @package OCA\Files_Sharing\API + */ +class Share20OCS { + + /** @var IManager */ + private $shareManager; + /** @var IGroupManager */ + private $groupManager; + /** @var IUserManager */ + private $userManager; + /** @var IRequest */ + private $request; + /** @var IRootFolder */ + private $rootFolder; + /** @var IURLGenerator */ + private $urlGenerator; + /** @var IUser */ + private $currentUser; + /** @var IL10N */ + private $l; + + /** + * Share20OCS constructor. + * + * @param IManager $shareManager + * @param IGroupManager $groupManager + * @param IUserManager $userManager + * @param IRequest $request + * @param IRootFolder $rootFolder + * @param IURLGenerator $urlGenerator + * @param IUser $currentUser + */ + public function __construct( + IManager $shareManager, + IGroupManager $groupManager, + IUserManager $userManager, + IRequest $request, + IRootFolder $rootFolder, + IURLGenerator $urlGenerator, + IUser $currentUser, + IL10N $l10n + ) { + $this->shareManager = $shareManager; + $this->userManager = $userManager; + $this->groupManager = $groupManager; + $this->request = $request; + $this->rootFolder = $rootFolder; + $this->urlGenerator = $urlGenerator; + $this->currentUser = $currentUser; + $this->l = $l10n; + } + + /** + * Convert an IShare to an array for OCS output + * + * @param \OCP\Share\IShare $share + * @return array + * @throws NotFoundException In case the node can't be resolved. + */ + protected function formatShare(\OCP\Share\IShare $share) { + $sharedBy = $this->userManager->get($share->getSharedBy()); + // for federated shares the owner can be a remote user, in this + // case we use the initiator + if ($this->userManager->userExists($share->getShareOwner())) { + $shareOwner = $this->userManager->get($share->getShareOwner()); + $localUser = $share->getShareOwner(); + } else { + $shareOwner = $this->userManager->get($share->getSharedBy()); + $localUser = $share->getSharedBy(); + } + $result = [ + 'id' => $share->getId(), + 'share_type' => $share->getShareType(), + 'uid_owner' => $share->getSharedBy(), + 'displayname_owner' => $sharedBy !== null ? $sharedBy->getDisplayName() : $share->getSharedBy(), + 'permissions' => $share->getPermissions(), + 'stime' => $share->getShareTime()->getTimestamp(), + 'parent' => null, + 'expiration' => null, + 'token' => null, + 'uid_file_owner' => $share->getShareOwner(), + 'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(), + ]; + + $node = $share->getNode(); + $result['path'] = $this->rootFolder->getUserFolder($localUser)->getRelativePath($node->getPath()); + if ($node instanceOf \OCP\Files\Folder) { + $result['item_type'] = 'folder'; + } else { + $result['item_type'] = 'file'; + } + $result['mimetype'] = $node->getMimeType(); + $result['storage_id'] = $node->getStorage()->getId(); + $result['storage'] = $node->getStorage()->getCache()->getNumericStorageId(); + $result['item_source'] = $node->getId(); + $result['file_source'] = $node->getId(); + $result['file_parent'] = $node->getParent()->getId(); + $result['file_target'] = $share->getTarget(); + + if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { + $sharedWith = $this->userManager->get($share->getSharedWith()); + $result['share_with'] = $share->getSharedWith(); + $result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith(); + } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { + $result['share_with'] = $share->getSharedWith(); + $result['share_with_displayname'] = $share->getSharedWith(); + } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { + + $result['share_with'] = $share->getPassword(); + $result['share_with_displayname'] = $share->getPassword(); + + $result['token'] = $share->getToken(); + $result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]); + + $expiration = $share->getExpirationDate(); + if ($expiration !== null) { + $result['expiration'] = $expiration->format('Y-m-d 00:00:00'); + } + + } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) { + $result['share_with'] = $share->getSharedWith(); + $result['share_with_displayname'] = $share->getSharedWith(); + $result['token'] = $share->getToken(); + } + + $result['mail_send'] = $share->getMailSend() ? 1 : 0; + + return $result; + } + + /** + * Get a specific share by id + * + * @param string $id + * @return \OC_OCS_Result + */ + public function getShare($id) { + if (!$this->shareManager->shareApiEnabled()) { + return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled')); + } + + try { + $share = $this->getShareById($id); + } catch (ShareNotFound $e) { + return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); + } + + if ($this->canAccessShare($share)) { + try { + $share = $this->formatShare($share); + return new \OC_OCS_Result([$share]); + } catch (NotFoundException $e) { + //Fall trough + } + } + + return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); + } + + /** + * Delete a share + * + * @param string $id + * @return \OC_OCS_Result + */ + public function deleteShare($id) { + if (!$this->shareManager->shareApiEnabled()) { + return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled')); + } + + try { + $share = $this->getShareById($id); + } catch (ShareNotFound $e) { + return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); + } + + try { + $share->getNode()->lock(ILockingProvider::LOCK_SHARED); + } catch (LockedException $e) { + return new \OC_OCS_Result(null, 404, 'could not delete share'); + } + + if (!$this->canAccessShare($share)) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 404, $this->l->t('Could not delete share')); + } + + $this->shareManager->deleteShare($share); + + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + + return new \OC_OCS_Result(); + } + + /** + * @return \OC_OCS_Result + */ + public function createShare() { + $share = $this->shareManager->newShare(); + + if (!$this->shareManager->shareApiEnabled()) { + return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled')); + } + + // Verify path + $path = $this->request->getParam('path', null); + if ($path === null) { + return new \OC_OCS_Result(null, 404, $this->l->t('Please specify a file or folder path')); + } + + $userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); + try { + $path = $userFolder->get($path); + } catch (NotFoundException $e) { + return new \OC_OCS_Result(null, 404, $this->l->t('Wrong path, file/folder doesn\'t exist')); + } + + $share->setNode($path); + + try { + $share->getNode()->lock(ILockingProvider::LOCK_SHARED); + } catch (LockedException $e) { + return new \OC_OCS_Result(null, 404, 'Could not create share'); + } + + // Parse permissions (if available) + $permissions = $this->request->getParam('permissions', null); + if ($permissions === null) { + $permissions = \OCP\Constants::PERMISSION_ALL; + } else { + $permissions = (int)$permissions; + } + + if ($permissions < 0 || $permissions > \OCP\Constants::PERMISSION_ALL) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 404, 'invalid permissions'); + } + + // Shares always require read permissions + $permissions |= \OCP\Constants::PERMISSION_READ; + + if ($path instanceof \OCP\Files\File) { + // Single file shares should never have delete or create permissions + $permissions &= ~\OCP\Constants::PERMISSION_DELETE; + $permissions &= ~\OCP\Constants::PERMISSION_CREATE; + } + + /* + * Hack for https://github.com/owncloud/core/issues/22587 + * We check the permissions via webdav. But the permissions of the mount point + * do not equal the share permissions. Here we fix that for federated mounts. + */ + if ($path->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) { + $permissions &= ~($permissions & ~$path->getPermissions()); + } + + $shareWith = $this->request->getParam('shareWith', null); + $shareType = (int)$this->request->getParam('shareType', '-1'); + + if ($shareType === \OCP\Share::SHARE_TYPE_USER) { + // Valid user is required to share + if ($shareWith === null || !$this->userManager->userExists($shareWith)) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 404, $this->l->t('Please specify a valid user')); + } + $share->setSharedWith($shareWith); + $share->setPermissions($permissions); + } else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) { + if (!$this->shareManager->allowGroupSharing()) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 404, $this->l->t('Group sharing is disabled by the administrator')); + } + + // Valid group is required to share + if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 404, $this->l->t('Please specify a valid group')); + } + $share->setSharedWith($shareWith); + $share->setPermissions($permissions); + } else if ($shareType === \OCP\Share::SHARE_TYPE_LINK) { + //Can we even share links? + if (!$this->shareManager->shareApiAllowLinks()) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 404, $this->l->t('Public link sharing is disabled by the administrator')); + } + + /* + * For now we only allow 1 link share. + * Return the existing link share if this is a duplicate + */ + $existingShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $path, false, 1, 0); + if (!empty($existingShares)) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result($this->formatShare($existingShares[0])); + } + + $publicUpload = $this->request->getParam('publicUpload', null); + if ($publicUpload === 'true') { + // Check if public upload is allowed + if (!$this->shareManager->shareApiLinkAllowPublicUpload()) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 403, $this->l->t('Public upload disabled by the administrator')); + } + + // Public upload can only be set for folders + if ($path instanceof \OCP\Files\File) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 404, $this->l->t('Public upload is only possible for publicly shared folders')); + } + + $share->setPermissions( + \OCP\Constants::PERMISSION_READ | + \OCP\Constants::PERMISSION_CREATE | + \OCP\Constants::PERMISSION_UPDATE + ); + } else { + $share->setPermissions(\OCP\Constants::PERMISSION_READ); + } + + // Set password + $password = $this->request->getParam('password', ''); + + if ($password !== '') { + $share->setPassword($password); + } + + //Expire date + $expireDate = $this->request->getParam('expireDate', ''); + + if ($expireDate !== '') { + try { + $expireDate = $this->parseDate($expireDate); + $share->setExpirationDate($expireDate); + } catch (\Exception $e) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 404, $this->l->t('Invalid date, date format must be YYYY-MM-DD')); + } + } + + } else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) { + if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 403, $this->l->t('Sharing %s failed because the back end does not allow shares from type %s', [$path->getPath(), $shareType])); + } + + $share->setSharedWith($shareWith); + $share->setPermissions($permissions); + } else { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 400, $this->l->t('Unknown share type')); + } + + $share->setShareType($shareType); + $share->setSharedBy($this->currentUser->getUID()); + + try { + $share = $this->shareManager->createShare($share); + } catch (GenericShareException $e) { + $code = $e->getCode() === 0 ? 403 : $e->getCode(); + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, $code, $e->getHint()); + }catch (\Exception $e) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 403, $e->getMessage()); + } + + $output = $this->formatShare($share); + + $share->getNode()->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + return new \OC_OCS_Result($output); + } + + /** + * @param \OCP\Files\File|\OCP\Files\Folder $node + * @return \OC_OCS_Result + */ + private function getSharedWithMe($node = null) { + $userShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $node, -1, 0); + $groupShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $node, -1, 0); + + $shares = array_merge($userShares, $groupShares); + + $formatted = []; + foreach ($shares as $share) { + if ($this->canAccessShare($share)) { + try { + $formatted[] = $this->formatShare($share); + } catch (NotFoundException $e) { + // Ignore this share + } + } + } + + return new \OC_OCS_Result($formatted); + } + + /** + * @param \OCP\Files\Folder $folder + * @return \OC_OCS_Result + */ + private function getSharesInDir($folder) { + if (!($folder instanceof \OCP\Files\Folder)) { + return new \OC_OCS_Result(null, 400, $this->l->t('Not a directory')); + } + + $nodes = $folder->getDirectoryListing(); + /** @var \OCP\Share\IShare[] $shares */ + $shares = []; + foreach ($nodes as $node) { + $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $node, false, -1, 0)); + $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $node, false, -1, 0)); + $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $node, false, -1, 0)); + if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { + $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_REMOTE, $node, false, -1, 0)); + } + } + + $formatted = []; + foreach ($shares as $share) { + try { + $formatted[] = $this->formatShare($share); + } catch (NotFoundException $e) { + //Ignore this share + } + } + + return new \OC_OCS_Result($formatted); + } + + /** + * The getShares function. + * + * - Get shares by the current user + * - Get shares by the current user and reshares (?reshares=true) + * - Get shares with the current user (?shared_with_me=true) + * - Get shares for a specific path (?path=...) + * - Get all shares in a folder (?subfiles=true&path=..) + * + * @return \OC_OCS_Result + */ + public function getShares() { + if (!$this->shareManager->shareApiEnabled()) { + return new \OC_OCS_Result(); + } + + $sharedWithMe = $this->request->getParam('shared_with_me', null); + $reshares = $this->request->getParam('reshares', null); + $subfiles = $this->request->getParam('subfiles'); + $path = $this->request->getParam('path', null); + + if ($path !== null) { + $userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); + try { + $path = $userFolder->get($path); + $path->lock(ILockingProvider::LOCK_SHARED); + } catch (\OCP\Files\NotFoundException $e) { + return new \OC_OCS_Result(null, 404, $this->l->t('Wrong path, file/folder doesn\'t exist')); + } catch (LockedException $e) { + return new \OC_OCS_Result(null, 404, $this->l->t('Could not lock path')); + } + } + + if ($sharedWithMe === 'true') { + $result = $this->getSharedWithMe($path); + if ($path !== null) { + $path->unlock(ILockingProvider::LOCK_SHARED); + } + return $result; + } + + if ($subfiles === 'true') { + $result = $this->getSharesInDir($path); + if ($path !== null) { + $path->unlock(ILockingProvider::LOCK_SHARED); + } + return $result; + } + + if ($reshares === 'true') { + $reshares = true; + } else { + $reshares = false; + } + + // Get all shares + $userShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $path, $reshares, -1, 0); + $groupShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0); + $linkShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0); + $shares = array_merge($userShares, $groupShares, $linkShares); + + if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { + $federatedShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0); + $shares = array_merge($shares, $federatedShares); + } + + + $formatted = []; + foreach ($shares as $share) { + try { + $formatted[] = $this->formatShare($share); + } catch (NotFoundException $e) { + //Ignore share + } + } + + if ($path !== null) { + $path->unlock(ILockingProvider::LOCK_SHARED); + } + + return new \OC_OCS_Result($formatted); + } + + /** + * @param int $id + * @return \OC_OCS_Result + */ + public function updateShare($id) { + if (!$this->shareManager->shareApiEnabled()) { + return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled')); + } + + try { + $share = $this->getShareById($id); + } catch (ShareNotFound $e) { + return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); + } + + $share->getNode()->lock(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + if (!$this->canAccessShare($share)) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); + } + + $permissions = $this->request->getParam('permissions', null); + $password = $this->request->getParam('password', null); + $publicUpload = $this->request->getParam('publicUpload', null); + $expireDate = $this->request->getParam('expireDate', null); + + /* + * expirationdate, password and publicUpload only make sense for link shares + */ + if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { + if ($permissions === null && $password === null && $publicUpload === null && $expireDate === null) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 400, 'Wrong or no update parameter given'); + } + + $newPermissions = null; + if ($publicUpload === 'true') { + $newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE; + } else if ($publicUpload === 'false') { + $newPermissions = \OCP\Constants::PERMISSION_READ; + } + + if ($permissions !== null) { + $newPermissions = (int)$permissions; + } + + if ($newPermissions !== null && + $newPermissions !== \OCP\Constants::PERMISSION_READ && + $newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE)) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 400, $this->l->t('Can\'t change permissions for public share links')); + } + + if ($newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE)) { + if (!$this->shareManager->shareApiLinkAllowPublicUpload()) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 403, $this->l->t('Public upload disabled by the administrator')); + } + + if (!($share->getNode() instanceof \OCP\Files\Folder)) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 400, $this->l->t('Public upload is only possible for publicly shared folders')); + } + } + + if ($newPermissions !== null) { + $share->setPermissions($newPermissions); + } + + if ($expireDate === '') { + $share->setExpirationDate(null); + } else if ($expireDate !== null) { + try { + $expireDate = $this->parseDate($expireDate); + } catch (\Exception $e) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 400, $e->getMessage()); + } + $share->setExpirationDate($expireDate); + } + + if ($password === '') { + $share->setPassword(null); + } else if ($password !== null) { + $share->setPassword($password); + } + + } else { + // For other shares only permissions is valid. + if ($permissions === null) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 400, $this->l->t('Wrong or no update parameter given')); + } else { + $permissions = (int)$permissions; + $share->setPermissions($permissions); + } + } + + if ($permissions !== null) { + /* Check if this is an incomming share */ + $incomingShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $share->getNode(), -1, 0); + $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0)); + + if (!empty($incomingShares)) { + $maxPermissions = 0; + foreach ($incomingShares as $incomingShare) { + $maxPermissions |= $incomingShare->getPermissions(); + } + + if ($share->getPermissions() & ~$maxPermissions) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 404, $this->l->t('Cannot increase permissions')); + } + } + } + + + try { + $share = $this->shareManager->updateShare($share); + } catch (\Exception $e) { + $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); + return new \OC_OCS_Result(null, 400, $e->getMessage()); + } + + $share->getNode()->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + return new \OC_OCS_Result($this->formatShare($share)); + } + + /** + * @param \OCP\Share\IShare $share + * @return bool + */ + protected function canAccessShare(\OCP\Share\IShare $share) { + // A file with permissions 0 can't be accessed by us. So Don't show it + if ($share->getPermissions() === 0) { + return false; + } + + // Owner of the file and the sharer of the file can always get share + if ($share->getShareOwner() === $this->currentUser->getUID() || + $share->getSharedBy() === $this->currentUser->getUID() + ) { + return true; + } + + // If the share is shared with you (or a group you are a member of) + if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && + $share->getSharedWith() === $this->currentUser->getUID()) { + return true; + } + + if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { + $sharedWith = $this->groupManager->get($share->getSharedWith()); + if ($sharedWith->inGroup($this->currentUser)) { + return true; + } + } + + return false; + } + + /** + * Make sure that the passed date is valid ISO 8601 + * So YYYY-MM-DD + * If not throw an exception + * + * @param string $expireDate + * + * @throws \Exception + * @return \DateTime + */ + private function parseDate($expireDate) { + try { + $date = new \DateTime($expireDate); + } catch (\Exception $e) { + throw new \Exception('Invalid date. Format must be YYYY-MM-DD'); + } + + if ($date === false) { + throw new \Exception('Invalid date. Format must be YYYY-MM-DD'); + } + + $date->setTime(0,0,0); + + return $date; + } + + /** + * Since we have multiple providers but the OCS Share API v1 does + * not support this we need to check all backends. + * + * @param string $id + * @return \OCP\Share\IShare + * @throws ShareNotFound + */ + private function getShareById($id) { + $share = null; + + // First check if it is an internal share. + try { + $share = $this->shareManager->getShareById('ocinternal:'.$id); + } catch (ShareNotFound $e) { + if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { + throw new ShareNotFound(); + } + + $share = $this->shareManager->getShareById('ocFederatedSharing:' . $id); + } + + return $share; + } +} diff --git a/apps/files_sharing/lib/API/Sharees.php b/apps/files_sharing/lib/API/Sharees.php new file mode 100644 index 00000000000..4e005c5e26c --- /dev/null +++ b/apps/files_sharing/lib/API/Sharees.php @@ -0,0 +1,536 @@ + + * @author Joas Schilling + * @author Roeland Jago Douma + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ +namespace OCA\Files_Sharing\API; + +use OCP\AppFramework\Http; +use OCP\Contacts\IManager; +use OCP\IGroup; +use OCP\IGroupManager; +use OCP\ILogger; +use OCP\IRequest; +use OCP\IUser; +use OCP\IUserManager; +use OCP\IConfig; +use OCP\IUserSession; +use OCP\IURLGenerator; +use OCP\Share; + +class Sharees { + + /** @var IGroupManager */ + protected $groupManager; + + /** @var IUserManager */ + protected $userManager; + + /** @var IManager */ + protected $contactsManager; + + /** @var IConfig */ + protected $config; + + /** @var IUserSession */ + protected $userSession; + + /** @var IRequest */ + protected $request; + + /** @var IURLGenerator */ + protected $urlGenerator; + + /** @var ILogger */ + protected $logger; + + /** @var \OCP\Share\IManager */ + protected $shareManager; + + /** @var bool */ + protected $shareWithGroupOnly = false; + + /** @var bool */ + protected $shareeEnumeration = true; + + /** @var int */ + protected $offset = 0; + + /** @var int */ + protected $limit = 10; + + /** @var array */ + protected $result = [ + 'exact' => [ + 'users' => [], + 'groups' => [], + 'remotes' => [], + ], + 'users' => [], + 'groups' => [], + 'remotes' => [], + ]; + + protected $reachedEndFor = []; + + /** + * @param IGroupManager $groupManager + * @param IUserManager $userManager + * @param IManager $contactsManager + * @param IConfig $config + * @param IUserSession $userSession + * @param IURLGenerator $urlGenerator + * @param IRequest $request + * @param ILogger $logger + * @param \OCP\Share\IManager $shareManager + */ + public function __construct(IGroupManager $groupManager, + IUserManager $userManager, + IManager $contactsManager, + IConfig $config, + IUserSession $userSession, + IURLGenerator $urlGenerator, + IRequest $request, + ILogger $logger, + \OCP\Share\IManager $shareManager) { + $this->groupManager = $groupManager; + $this->userManager = $userManager; + $this->contactsManager = $contactsManager; + $this->config = $config; + $this->userSession = $userSession; + $this->urlGenerator = $urlGenerator; + $this->request = $request; + $this->logger = $logger; + $this->shareManager = $shareManager; + } + + /** + * @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; + foreach ($users as $uid => $userDisplayName) { + if (strtolower($uid) === strtolower($search) || strtolower($userDisplayName) === strtolower($search)) { + if (strtolower($uid) === strtolower($search)) { + $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); + $groups = 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); + $groups = array_intersect($groups, $userGroups); + } + + foreach ($groups as $gid) { + if (strtolower($gid) === strtolower($search)) { + $this->result['exact']['groups'][] = [ + 'label' => $gid, + 'value' => [ + 'shareType' => Share::SHARE_TYPE_GROUP, + 'shareWith' => $gid, + ], + ]; + } else { + $this->result['groups'][] = [ + 'label' => $gid, + '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->getGID(), + 'value' => [ + 'shareType' => Share::SHARE_TYPE_GROUP, + 'shareWith' => $group->getGID(), + ], + ]); + } + } + + if (!$this->shareeEnumeration) { + $this->result['groups'] = []; + } + } + + /** + * @param string $search + * @return array possible sharees + */ + protected function getRemote($search) { + $this->result['remotes'] = []; + + // Search in contacts + //@todo Pagination missing + $addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN']); + $foundRemoteById = false; + foreach ($addressBookContacts as $contact) { + if (isset($contact['isLocalSystemBook'])) { + continue; + } + if (isset($contact['CLOUD'])) { + $cloudIds = $contact['CLOUD']; + if (!is_array($cloudIds)) { + $cloudIds = [$cloudIds]; + } + foreach ($cloudIds as $cloudId) { + list(, $serverUrl) = $this->splitUserRemote($cloudId); + if (strtolower($contact['FN']) === strtolower($search) || strtolower($cloudId) === strtolower($search)) { + if (strtolower($cloudId) === strtolower($search)) { + $foundRemoteById = true; + } + $this->result['exact']['remotes'][] = [ + 'label' => $contact['FN'], + 'value' => [ + 'shareType' => Share::SHARE_TYPE_REMOTE, + 'shareWith' => $cloudId, + 'server' => $serverUrl, + ], + ]; + } else { + $this->result['remotes'][] = [ + 'label' => $contact['FN'], + 'value' => [ + 'shareType' => Share::SHARE_TYPE_REMOTE, + 'shareWith' => $cloudId, + 'server' => $serverUrl, + ], + ]; + } + } + } + } + + if (!$this->shareeEnumeration) { + $this->result['remotes'] = []; + } + + if (!$foundRemoteById && substr_count($search, '@') >= 1 && substr_count($search, ' ') === 0 && $this->offset === 0) { + $this->result['exact']['remotes'][] = [ + 'label' => $search, + 'value' => [ + 'shareType' => Share::SHARE_TYPE_REMOTE, + 'shareWith' => $search, + ], + ]; + } + + $this->reachedEndFor[] = 'remotes'; + } + + /** + * split user and remote from federated cloud id + * + * @param string $address federated share address + * @return array [user, remoteURL] + * @throws \Exception + */ + public function splitUserRemote($address) { + if (strpos($address, '@') === false) { + throw new \Exception('Invalid Federated Cloud ID'); + } + + // Find the first character that is not allowed in user names + $id = str_replace('\\', '/', $address); + $posSlash = strpos($id, '/'); + $posColon = strpos($id, ':'); + + if ($posSlash === false && $posColon === false) { + $invalidPos = strlen($id); + } else if ($posSlash === false) { + $invalidPos = $posColon; + } else if ($posColon === false) { + $invalidPos = $posSlash; + } else { + $invalidPos = min($posSlash, $posColon); + } + + // Find the last @ before $invalidPos + $pos = $lastAtPos = 0; + while ($lastAtPos !== false && $lastAtPos <= $invalidPos) { + $pos = $lastAtPos; + $lastAtPos = strpos($id, '@', $pos + 1); + } + + if ($pos !== false) { + $user = substr($id, 0, $pos); + $remote = substr($id, $pos + 1); + $remote = $this->fixRemoteURL($remote); + if (!empty($user) && !empty($remote)) { + return array($user, $remote); + } + } + + throw new \Exception('Invalid Federated Cloud ID'); + } + + /** + * 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; + } + + /** + * @return \OC_OCS_Result + */ + public function search() { + $search = isset($_GET['search']) ? (string) $_GET['search'] : ''; + $itemType = isset($_GET['itemType']) ? (string) $_GET['itemType'] : null; + $page = isset($_GET['page']) ? (int) $_GET['page'] : 1; + $perPage = isset($_GET['perPage']) ? (int) $_GET['perPage'] : 200; + + if ($perPage <= 0) { + return new \OC_OCS_Result(null, Http::STATUS_BAD_REQUEST, 'Invalid perPage argument'); + } + if ($page <= 0) { + return new \OC_OCS_Result(null, Http::STATUS_BAD_REQUEST, 'Invalid page'); + } + + $shareTypes = [ + Share::SHARE_TYPE_USER, + ]; + + if ($this->shareManager->allowGroupSharing()) { + $shareTypes[] = Share::SHARE_TYPE_GROUP; + } + + $shareTypes[] = Share::SHARE_TYPE_REMOTE; + + if (isset($_GET['shareType']) && is_array($_GET['shareType'])) { + $shareTypes = array_intersect($shareTypes, $_GET['shareType']); + sort($shareTypes); + + } else if (isset($_GET['shareType']) && is_numeric($_GET['shareType'])) { + $shareTypes = array_intersect($shareTypes, [(int) $_GET['shareType']]); + sort($shareTypes); + } + + if (in_array(Share::SHARE_TYPE_REMOTE, $shareTypes) && !$this->isRemoteSharingAllowed($itemType)) { + // Remove remote shares from type array, because it is not allowed. + $shareTypes = array_diff($shareTypes, [Share::SHARE_TYPE_REMOTE]); + } + + $this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes'; + $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes'; + $this->limit = (int) $perPage; + $this->offset = $perPage * ($page - 1); + + return $this->searchSharees($search, $itemType, $shareTypes, $page, $perPage); + } + + /** + * Method to get out the static call for better testing + * + * @param string $itemType + * @return bool + */ + protected function isRemoteSharingAllowed($itemType) { + try { + $backend = 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 + * @return \OC_OCS_Result + */ + protected function searchSharees($search, $itemType, array $shareTypes, $page, $perPage) { + // Verify arguments + if ($itemType === null) { + return new \OC_OCS_Result(null, Http::STATUS_BAD_REQUEST, '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 remote + if (in_array(Share::SHARE_TYPE_REMOTE, $shareTypes)) { + $this->getRemote($search); + } + + $response = new \OC_OCS_Result($this->result); + $response->setItemsPerPage($perPage); + + if (sizeof($this->reachedEndFor) < 3) { + $response->addHeader('Link', $this->getPaginationLink($page, [ + 'search' => $search, + 'itemType' => $itemType, + 'shareType' => $shareTypes, + 'perPage' => $perPage, + ])); + } + + return $response; + } + + /** + * Generates a bunch of pagination links for the current page + * + * @param int $page Current page + * @param array $params Parameters for the URL + * @return string + */ + protected function getPaginationLink($page, array $params) { + if ($this->isV2()) { + $url = $this->urlGenerator->getAbsoluteURL('/ocs/v2.php/apps/files_sharing/api/v1/sharees') . '?'; + } else { + $url = $this->urlGenerator->getAbsoluteURL('/ocs/v1.php/apps/files_sharing/api/v1/sharees') . '?'; + } + $params['page'] = $page + 1; + $link = '<' . $url . http_build_query($params) . '>; rel="next"'; + + return $link; + } + + /** + * @return bool + */ + protected function isV2() { + return $this->request->getScriptName() === '/ocs/v2.php'; + } +} diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php new file mode 100644 index 00000000000..b17e213e2e2 --- /dev/null +++ b/apps/files_sharing/lib/AppInfo/Application.php @@ -0,0 +1,145 @@ + + * @author Lukas Reschke + * @author Robin Appelman + * @author Roeland Jago Douma + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\AppInfo; + +use OCA\FederatedFileSharing\DiscoveryManager; +use OCA\Files_Sharing\MountProvider; +use OCP\AppFramework\App; +use OC\AppFramework\Utility\SimpleContainer; +use OCA\Files_Sharing\Controllers\ExternalSharesController; +use OCA\Files_Sharing\Controllers\ShareController; +use OCA\Files_Sharing\Middleware\SharingCheckMiddleware; +use \OCP\IContainer; +use OCA\Files_Sharing\Capabilities; + +class Application extends App { + public function __construct(array $urlParams = array()) { + parent::__construct('files_sharing', $urlParams); + + $container = $this->getContainer(); + $server = $container->getServer(); + + /** + * Controllers + */ + $container->registerService('ShareController', function (SimpleContainer $c) use ($server) { + $federatedSharingApp = new \OCA\FederatedFileSharing\AppInfo\Application('federatedfilesharing'); + return new ShareController( + $c->query('AppName'), + $c->query('Request'), + $server->getConfig(), + $server->getURLGenerator(), + $server->getUserManager(), + $server->getLogger(), + $server->getActivityManager(), + $server->getShareManager(), + $server->getSession(), + $server->getPreviewManager(), + $server->getRootFolder(), + $federatedSharingApp->getFederatedShareProvider() + ); + }); + $container->registerService('ExternalSharesController', function (SimpleContainer $c) { + return new ExternalSharesController( + $c->query('AppName'), + $c->query('Request'), + $c->query('ExternalManager'), + $c->query('HttpClientService') + ); + }); + + /** + * Core class wrappers + */ + $container->registerService('HttpClientService', function (SimpleContainer $c) use ($server) { + return $server->getHTTPClientService(); + }); + $container->registerService('ExternalManager', function (SimpleContainer $c) use ($server) { + $user = $server->getUserSession()->getUser(); + $uid = $user ? $user->getUID() : null; + $discoveryManager = new DiscoveryManager( + \OC::$server->getMemCacheFactory(), + \OC::$server->getHTTPClientService() + ); + return new \OCA\Files_Sharing\External\Manager( + $server->getDatabaseConnection(), + \OC\Files\Filesystem::getMountManager(), + \OC\Files\Filesystem::getLoader(), + $server->getHTTPHelper(), + $server->getNotificationManager(), + $discoveryManager, + $uid + ); + }); + + /** + * Middleware + */ + $container->registerService('SharingCheckMiddleware', function (SimpleContainer $c) use ($server) { + return new SharingCheckMiddleware( + $c->query('AppName'), + $server->getConfig(), + $server->getAppManager(), + $c['ControllerMethodReflector'] + ); + }); + + // Execute middlewares + $container->registerMiddleware('SharingCheckMiddleware'); + + $container->registerService('MountProvider', function (IContainer $c) { + /** @var \OCP\IServerContainer $server */ + $server = $c->query('ServerContainer'); + return new MountProvider( + $server->getConfig(), + $server->getShareManager() + ); + }); + + $container->registerService('ExternalMountProvider', function (IContainer $c) { + /** @var \OCP\IServerContainer $server */ + $server = $c->query('ServerContainer'); + return new \OCA\Files_Sharing\External\MountProvider( + $server->getDatabaseConnection(), + function() use ($c) { + return $c->query('ExternalManager'); + } + ); + }); + + /* + * Register capabilities + */ + $container->registerCapability('OCA\Files_Sharing\Capabilities'); + } + + public function registerMountProviders() { + /** @var \OCP\IServerContainer $server */ + $server = $this->getContainer()->query('ServerContainer'); + $mountProviderCollection = $server->getMountProviderCollection(); + $mountProviderCollection->registerProvider($this->getContainer()->query('MountProvider')); + $mountProviderCollection->registerProvider($this->getContainer()->query('ExternalMountProvider')); + } +} diff --git a/apps/files_sharing/tests/testcase.php b/apps/files_sharing/tests/testcase.php index b1d6facafd6..9078a3d4578 100644 --- a/apps/files_sharing/tests/testcase.php +++ b/apps/files_sharing/tests/testcase.php @@ -32,7 +32,7 @@ namespace OCA\Files_Sharing\Tests; use OC\Files\Filesystem; use OCA\Files\Share; -use OCA\Files_Sharing\Appinfo\Application; +use OCA\Files_Sharing\AppInfo\Application; /** * Class Test_Files_Sharing_Base -- cgit v1.2.3 From 3a716ae91c20f48737ad5f9192b20967252e74ec Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 17 May 2016 10:36:56 +0200 Subject: Move lib/ to PSR-4 --- apps/federatedfilesharing/lib/Notifier.php | 93 ++++ apps/federatedfilesharing/lib/notifier.php | 93 ---- apps/files_sharing/lib/Activity.php | 483 +++++++++++++++++++ apps/files_sharing/lib/Cache.php | 105 +++++ apps/files_sharing/lib/Capabilities.php | 91 ++++ .../lib/Controllers/ExternalSharesController.php | 149 ++++++ .../lib/Controllers/ShareController.php | 511 +++++++++++++++++++++ apps/files_sharing/lib/Exceptions/BrokenPath.php | 32 ++ apps/files_sharing/lib/Exceptions/S2SException.php | 30 ++ apps/files_sharing/lib/ExpireSharesJob.php | 76 +++ apps/files_sharing/lib/External/Cache.php | 65 +++ apps/files_sharing/lib/External/Manager.php | 453 ++++++++++++++++++ apps/files_sharing/lib/External/Mount.php | 70 +++ apps/files_sharing/lib/External/MountProvider.php | 76 +++ apps/files_sharing/lib/External/Scanner.php | 127 +++++ apps/files_sharing/lib/External/Storage.php | 339 ++++++++++++++ apps/files_sharing/lib/Helper.php | 310 +++++++++++++ apps/files_sharing/lib/Hooks.php | 64 +++ apps/files_sharing/lib/ISharedStorage.php | 27 ++ apps/files_sharing/lib/Maintainer.php | 45 ++ .../lib/Middleware/SharingCheckMiddleware.php | 161 +++++++ apps/files_sharing/lib/Migration.php | 274 +++++++++++ apps/files_sharing/lib/MountProvider.php | 83 ++++ apps/files_sharing/lib/Scanner.php | 75 +++ apps/files_sharing/lib/SharedMount.php | 226 +++++++++ apps/files_sharing/lib/SharedPropagator.php | 42 ++ apps/files_sharing/lib/Updater.php | 109 +++++ apps/files_sharing/lib/activity.php | 483 ------------------- apps/files_sharing/lib/cache.php | 105 ----- apps/files_sharing/lib/capabilities.php | 91 ---- .../lib/controllers/externalsharescontroller.php | 149 ------ .../lib/controllers/sharecontroller.php | 511 --------------------- apps/files_sharing/lib/exceptions/brokenpath.php | 32 -- apps/files_sharing/lib/exceptions/s2sexception.php | 30 -- apps/files_sharing/lib/expiresharesjob.php | 76 --- apps/files_sharing/lib/external/cache.php | 65 --- apps/files_sharing/lib/external/manager.php | 453 ------------------ apps/files_sharing/lib/external/mount.php | 70 --- apps/files_sharing/lib/external/mountprovider.php | 76 --- apps/files_sharing/lib/external/scanner.php | 127 ----- apps/files_sharing/lib/external/storage.php | 339 -------------- apps/files_sharing/lib/helper.php | 310 ------------- apps/files_sharing/lib/hooks.php | 64 --- apps/files_sharing/lib/isharedstorage.php | 27 -- apps/files_sharing/lib/maintainer.php | 45 -- .../lib/middleware/sharingcheckmiddleware.php | 161 ------- apps/files_sharing/lib/migration.php | 274 ----------- apps/files_sharing/lib/mountprovider.php | 83 ---- apps/files_sharing/lib/scanner.php | 75 --- apps/files_sharing/lib/sharedmount.php | 226 --------- apps/files_sharing/lib/sharedpropagator.php | 42 -- apps/files_sharing/lib/updater.php | 109 ----- 52 files changed, 4116 insertions(+), 4116 deletions(-) create mode 100644 apps/federatedfilesharing/lib/Notifier.php delete mode 100644 apps/federatedfilesharing/lib/notifier.php create mode 100644 apps/files_sharing/lib/Activity.php create mode 100644 apps/files_sharing/lib/Cache.php create mode 100644 apps/files_sharing/lib/Capabilities.php create mode 100644 apps/files_sharing/lib/Controllers/ExternalSharesController.php create mode 100644 apps/files_sharing/lib/Controllers/ShareController.php create mode 100644 apps/files_sharing/lib/Exceptions/BrokenPath.php create mode 100644 apps/files_sharing/lib/Exceptions/S2SException.php create mode 100644 apps/files_sharing/lib/ExpireSharesJob.php create mode 100644 apps/files_sharing/lib/External/Cache.php create mode 100644 apps/files_sharing/lib/External/Manager.php create mode 100644 apps/files_sharing/lib/External/Mount.php create mode 100644 apps/files_sharing/lib/External/MountProvider.php create mode 100644 apps/files_sharing/lib/External/Scanner.php create mode 100644 apps/files_sharing/lib/External/Storage.php create mode 100644 apps/files_sharing/lib/Helper.php create mode 100644 apps/files_sharing/lib/Hooks.php create mode 100644 apps/files_sharing/lib/ISharedStorage.php create mode 100644 apps/files_sharing/lib/Maintainer.php create mode 100644 apps/files_sharing/lib/Middleware/SharingCheckMiddleware.php create mode 100644 apps/files_sharing/lib/Migration.php create mode 100644 apps/files_sharing/lib/MountProvider.php create mode 100644 apps/files_sharing/lib/Scanner.php create mode 100644 apps/files_sharing/lib/SharedMount.php create mode 100644 apps/files_sharing/lib/SharedPropagator.php create mode 100644 apps/files_sharing/lib/Updater.php delete mode 100644 apps/files_sharing/lib/activity.php delete mode 100644 apps/files_sharing/lib/cache.php delete mode 100644 apps/files_sharing/lib/capabilities.php delete mode 100644 apps/files_sharing/lib/controllers/externalsharescontroller.php delete mode 100644 apps/files_sharing/lib/controllers/sharecontroller.php delete mode 100644 apps/files_sharing/lib/exceptions/brokenpath.php delete mode 100644 apps/files_sharing/lib/exceptions/s2sexception.php delete mode 100644 apps/files_sharing/lib/expiresharesjob.php delete mode 100644 apps/files_sharing/lib/external/cache.php delete mode 100644 apps/files_sharing/lib/external/manager.php delete mode 100644 apps/files_sharing/lib/external/mount.php delete mode 100644 apps/files_sharing/lib/external/mountprovider.php delete mode 100644 apps/files_sharing/lib/external/scanner.php delete mode 100644 apps/files_sharing/lib/external/storage.php delete mode 100644 apps/files_sharing/lib/helper.php delete mode 100644 apps/files_sharing/lib/hooks.php delete mode 100644 apps/files_sharing/lib/isharedstorage.php delete mode 100644 apps/files_sharing/lib/maintainer.php delete mode 100644 apps/files_sharing/lib/middleware/sharingcheckmiddleware.php delete mode 100644 apps/files_sharing/lib/migration.php delete mode 100644 apps/files_sharing/lib/mountprovider.php delete mode 100644 apps/files_sharing/lib/scanner.php delete mode 100644 apps/files_sharing/lib/sharedmount.php delete mode 100644 apps/files_sharing/lib/sharedpropagator.php delete mode 100644 apps/files_sharing/lib/updater.php diff --git a/apps/federatedfilesharing/lib/Notifier.php b/apps/federatedfilesharing/lib/Notifier.php new file mode 100644 index 00000000000..1c8d92c7eca --- /dev/null +++ b/apps/federatedfilesharing/lib/Notifier.php @@ -0,0 +1,93 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\FederatedFileSharing; + + +use OCP\Notification\INotification; +use OCP\Notification\INotifier; + +class Notifier implements INotifier { + /** @var \OCP\L10N\IFactory */ + protected $factory; + + /** + * @param \OCP\L10N\IFactory $factory + */ + public function __construct(\OCP\L10N\IFactory $factory) { + $this->factory = $factory; + } + + /** + * @param INotification $notification + * @param string $languageCode The code of the language that should be used to prepare the notification + * @return INotification + */ + public function prepare(INotification $notification, $languageCode) { + if ($notification->getApp() !== 'files_sharing') { + // Not my app => throw + throw new \InvalidArgumentException(); + } + + // Read the language from the notification + $l = $this->factory->get('files_sharing', $languageCode); + + switch ($notification->getSubject()) { + // Deal with known subjects + case 'remote_share': + $params = $notification->getSubjectParameters(); + if ($params[0] !== $params[1] && $params[1] !== null) { + $notification->setParsedSubject( + (string) $l->t('You received "/%3$s" as a remote share from %1$s (on behalf of %2$s)', $params) + ); + } else { + $notification->setParsedSubject( + (string)$l->t('You received "/%3$s" as a remote share from %1$s', $params) + ); + } + + // Deal with the actions for a known subject + foreach ($notification->getActions() as $action) { + switch ($action->getLabel()) { + case 'accept': + $action->setParsedLabel( + (string) $l->t('Accept') + ) + ->setPrimary(true); + break; + + case 'decline': + $action->setParsedLabel( + (string) $l->t('Decline') + ); + break; + } + + $notification->addParsedAction($action); + } + return $notification; + + default: + // Unknown subject => Unknown notification => throw + throw new \InvalidArgumentException(); + } + } +} diff --git a/apps/federatedfilesharing/lib/notifier.php b/apps/federatedfilesharing/lib/notifier.php deleted file mode 100644 index 1c8d92c7eca..00000000000 --- a/apps/federatedfilesharing/lib/notifier.php +++ /dev/null @@ -1,93 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\FederatedFileSharing; - - -use OCP\Notification\INotification; -use OCP\Notification\INotifier; - -class Notifier implements INotifier { - /** @var \OCP\L10N\IFactory */ - protected $factory; - - /** - * @param \OCP\L10N\IFactory $factory - */ - public function __construct(\OCP\L10N\IFactory $factory) { - $this->factory = $factory; - } - - /** - * @param INotification $notification - * @param string $languageCode The code of the language that should be used to prepare the notification - * @return INotification - */ - public function prepare(INotification $notification, $languageCode) { - if ($notification->getApp() !== 'files_sharing') { - // Not my app => throw - throw new \InvalidArgumentException(); - } - - // Read the language from the notification - $l = $this->factory->get('files_sharing', $languageCode); - - switch ($notification->getSubject()) { - // Deal with known subjects - case 'remote_share': - $params = $notification->getSubjectParameters(); - if ($params[0] !== $params[1] && $params[1] !== null) { - $notification->setParsedSubject( - (string) $l->t('You received "/%3$s" as a remote share from %1$s (on behalf of %2$s)', $params) - ); - } else { - $notification->setParsedSubject( - (string)$l->t('You received "/%3$s" as a remote share from %1$s', $params) - ); - } - - // Deal with the actions for a known subject - foreach ($notification->getActions() as $action) { - switch ($action->getLabel()) { - case 'accept': - $action->setParsedLabel( - (string) $l->t('Accept') - ) - ->setPrimary(true); - break; - - case 'decline': - $action->setParsedLabel( - (string) $l->t('Decline') - ); - break; - } - - $notification->addParsedAction($action); - } - return $notification; - - default: - // Unknown subject => Unknown notification => throw - throw new \InvalidArgumentException(); - } - } -} diff --git a/apps/files_sharing/lib/Activity.php b/apps/files_sharing/lib/Activity.php new file mode 100644 index 00000000000..721379eb78f --- /dev/null +++ b/apps/files_sharing/lib/Activity.php @@ -0,0 +1,483 @@ + + * @author Joas Schilling + * @author Morris Jobke + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing; + +use OCP\Activity\IExtension; +use OCP\Activity\IManager; +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\L10N\IFactory; + +class Activity implements IExtension { + const FILES_SHARING_APP = 'files_sharing'; + /** + * Filter with all sharing related activities + */ + const FILTER_SHARES = 'shares'; + + /** + * Activity types known to this extension + */ + const TYPE_PUBLIC_LINKS = 'public_links'; + const TYPE_REMOTE_SHARE = 'remote_share'; + const TYPE_SHARED = 'shared'; + + /** + * Subject keys for translation of the subjections + */ + const SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED = 'public_shared_file_downloaded'; + const SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED = 'public_shared_folder_downloaded'; + + const SUBJECT_REMOTE_SHARE_ACCEPTED = 'remote_share_accepted'; + const SUBJECT_REMOTE_SHARE_DECLINED = 'remote_share_declined'; + const SUBJECT_REMOTE_SHARE_RECEIVED = 'remote_share_received'; + const SUBJECT_REMOTE_SHARE_UNSHARED = 'remote_share_unshared'; + + const SUBJECT_SHARED_USER_SELF = 'shared_user_self'; + const SUBJECT_RESHARED_USER_BY = 'reshared_user_by'; + const SUBJECT_UNSHARED_USER_SELF = 'unshared_user_self'; + const SUBJECT_UNSHARED_USER_BY = 'unshared_user_by'; + + const SUBJECT_SHARED_GROUP_SELF = 'shared_group_self'; + const SUBJECT_RESHARED_GROUP_BY = 'reshared_group_by'; + const SUBJECT_UNSHARED_GROUP_SELF = 'unshared_group_self'; + const SUBJECT_UNSHARED_GROUP_BY = 'unshared_group_by'; + + const SUBJECT_SHARED_LINK_SELF = 'shared_link_self'; + const SUBJECT_RESHARED_LINK_BY = 'reshared_link_by'; + const SUBJECT_UNSHARED_LINK_SELF = 'unshared_link_self'; + const SUBJECT_UNSHARED_LINK_BY = 'unshared_link_by'; + const SUBJECT_LINK_EXPIRED = 'link_expired'; + const SUBJECT_LINK_BY_EXPIRED = 'link_by_expired'; + + const SUBJECT_SHARED_EMAIL = 'shared_with_email'; + const SUBJECT_SHARED_WITH_BY = 'shared_with_by'; + const SUBJECT_UNSHARED_BY = 'unshared_by'; + + /** @var IFactory */ + protected $languageFactory; + + /** @var IURLGenerator */ + protected $URLGenerator; + + /** @var IManager */ + protected $activityManager; + + /** + * @param IFactory $languageFactory + * @param IURLGenerator $URLGenerator + * @param IManager $activityManager + */ + public function __construct(IFactory $languageFactory, IURLGenerator $URLGenerator, IManager $activityManager) { + $this->languageFactory = $languageFactory; + $this->URLGenerator = $URLGenerator; + $this->activityManager = $activityManager; + } + + protected function getL10N($languageCode = null) { + return $this->languageFactory->get(self::FILES_SHARING_APP, $languageCode); + } + + /** + * The extension can return an array of additional notification types. + * If no additional types are to be added false is to be returned + * + * @param string $languageCode + * @return array|false + */ + public function getNotificationTypes($languageCode) { + $l = $this->getL10N($languageCode); + + return array( + self::TYPE_SHARED => (string) $l->t('A file or folder has been shared'), + self::TYPE_REMOTE_SHARE => (string) $l->t('A file or folder was shared from another server'), + self::TYPE_PUBLIC_LINKS => (string) $l->t('A public shared file or folder was downloaded'), + ); + } + + /** + * For a given method additional types to be displayed in the settings can be returned. + * In case no additional types are to be added false is to be returned. + * + * @param string $method + * @return array|false + */ + public function getDefaultTypes($method) { + $defaultTypes = [ + self::TYPE_SHARED, + self::TYPE_REMOTE_SHARE, + ]; + + if ($method === self::METHOD_STREAM) { + $defaultTypes[] = self::TYPE_PUBLIC_LINKS; + } + + return $defaultTypes; + } + + /** + * A string naming the css class for the icon to be used can be returned. + * If no icon is known for the given type false is to be returned. + * + * @param string $type + * @return string|false + */ + public function getTypeIcon($type) { + switch ($type) { + case self::TYPE_SHARED: + case self::TYPE_REMOTE_SHARE: + return 'icon-share'; + case self::TYPE_PUBLIC_LINKS: + return 'icon-download'; + } + + return false; + } + + /** + * The extension can translate a given message to the requested languages. + * If no translation is available false is to be returned. + * + * @param string $app + * @param string $text + * @param array $params + * @param boolean $stripPath + * @param boolean $highlightParams + * @param string $languageCode + * @return string|false + */ + public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) { + if ($app !== self::FILES_SHARING_APP) { + return false; + } + + $l = $this->getL10N($languageCode); + + if ($this->activityManager->isFormattingFilteredObject()) { + $translation = $this->translateShort($text, $l, $params); + if ($translation !== false) { + return $translation; + } + } + + return $this->translateLong($text, $l, $params); + } + + /** + * @param string $text + * @param IL10N $l + * @param array $params + * @return bool|string + */ + protected function translateLong($text, IL10N $l, array $params) { + + switch ($text) { + case self::SUBJECT_REMOTE_SHARE_RECEIVED: + if (sizeof($params) === 2) { + // New activity ownCloud 8.2+ + return (string) $l->t('You received a new remote share %2$s from %1$s', $params); + } + return (string) $l->t('You received a new remote share from %s', $params); + case self::SUBJECT_REMOTE_SHARE_ACCEPTED: + return (string) $l->t('%1$s accepted remote share %2$s', $params); + case self::SUBJECT_REMOTE_SHARE_DECLINED: + return (string) $l->t('%1$s declined remote share %2$s', $params); + case self::SUBJECT_REMOTE_SHARE_UNSHARED: + return (string) $l->t('%1$s unshared %2$s from you', $params); + case self::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED: + return (string) $l->t('Public shared folder %1$s was downloaded', $params); + case self::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED: + return (string) $l->t('Public shared file %1$s was downloaded', $params); + + case self::SUBJECT_SHARED_USER_SELF: + return (string) $l->t('You shared %1$s with %2$s', $params); + case self::SUBJECT_RESHARED_USER_BY: + return (string) $l->t('%2$s shared %1$s with %3$s', $params); + case self::SUBJECT_UNSHARED_USER_SELF: + return (string) $l->t('You removed the share of %2$s for %1$s', $params); + case self::SUBJECT_UNSHARED_USER_BY: + return (string) $l->t('%2$s removed the share of %3$s for %1$s', $params); + + case self::SUBJECT_SHARED_GROUP_SELF: + return (string) $l->t('You shared %1$s with group %2$s', $params); + case self::SUBJECT_RESHARED_GROUP_BY: + return (string) $l->t('%2$s shared %1$s with group %3$s', $params); + case self::SUBJECT_UNSHARED_GROUP_SELF: + return (string) $l->t('You removed the share of group %2$s for %1$s', $params); + case self::SUBJECT_UNSHARED_GROUP_BY: + return (string) $l->t('%2$s removed the share of group %3$s for %1$s', $params); + + case self::SUBJECT_RESHARED_LINK_BY: + return (string) $l->t('%2$s shared %1$s via link', $params); + case self::SUBJECT_SHARED_LINK_SELF: + return (string) $l->t('You shared %1$s via link', $params); + case self::SUBJECT_UNSHARED_LINK_SELF: + return (string) $l->t('You removed the public link for %1$s', $params); + case self::SUBJECT_UNSHARED_LINK_BY: + return (string) $l->t('%2$s removed the public link for %1$s', $params); + case self::SUBJECT_LINK_EXPIRED: + return (string) $l->t('Your public link for %1$s expired', $params); + case self::SUBJECT_LINK_BY_EXPIRED: + return (string) $l->t('The public link of %2$s for %1$s expired', $params); + + case self::SUBJECT_SHARED_WITH_BY: + return (string) $l->t('%2$s shared %1$s with you', $params); + case self::SUBJECT_UNSHARED_BY: + return (string) $l->t('%2$s removed the share for %1$s', $params); + case self::SUBJECT_SHARED_EMAIL: + return (string) $l->t('You shared %1$s with %2$s', $params); + } + + return false; + } + + /** + * @param string $text + * @param IL10N $l + * @param array $params + * @return bool|string + */ + protected function translateShort($text, IL10N $l, array $params) { + switch ($text) { + case self::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED: + case self::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED: + return (string) $l->t('Downloaded via public link'); + + case self::SUBJECT_SHARED_USER_SELF: + return (string) $l->t('Shared with %2$s', $params); + case self::SUBJECT_RESHARED_USER_BY: + return (string) $l->t('Shared with %3$s by %2$s', $params); + case self::SUBJECT_UNSHARED_USER_SELF: + return (string) $l->t('Removed share for %2$s', $params); + case self::SUBJECT_UNSHARED_USER_BY: + return (string) $l->t('%2$s removed share for %3$s', $params); + + case self::SUBJECT_SHARED_GROUP_SELF: + return (string) $l->t('Shared with group %2$s', $params); + case self::SUBJECT_RESHARED_GROUP_BY: + return (string) $l->t('Shared with group %3$s by %2$s', $params); + case self::SUBJECT_UNSHARED_GROUP_SELF: + return (string) $l->t('Removed share of group %2$s', $params); + case self::SUBJECT_UNSHARED_GROUP_BY: + return (string) $l->t('%2$s removed share of group %3$s', $params); + + case self::SUBJECT_RESHARED_LINK_BY: + return (string) $l->t('Shared via link by %2$s', $params); + case self::SUBJECT_SHARED_LINK_SELF: + return (string) $l->t('Shared via public link'); + case self::SUBJECT_UNSHARED_LINK_SELF: + return (string) $l->t('Removed public link'); + case self::SUBJECT_UNSHARED_LINK_BY: + return (string) $l->t('%2$s removed public link'); + case self::SUBJECT_LINK_EXPIRED: + return (string) $l->t('Public link expired', $params); + case self::SUBJECT_LINK_BY_EXPIRED: + return (string) $l->t('Public link of %2$s expired', $params); + + case self::SUBJECT_SHARED_WITH_BY: + return (string) $l->t('Shared by %2$s', $params); + case self::SUBJECT_SHARED_EMAIL: + return (string) $l->t('Shared with %2$s', $params); + + default: + return false; + } + } + + /** + * The extension can define the type of parameters for translation + * + * Currently known types are: + * * file => will strip away the path of the file and add a tooltip with it + * * username => will add the avatar of the user + * + * @param string $app + * @param string $text + * @return array|false + */ + public function getSpecialParameterList($app, $text) { + if ($app === self::FILES_SHARING_APP) { + switch ($text) { + case self::SUBJECT_REMOTE_SHARE_RECEIVED: + case self::SUBJECT_REMOTE_SHARE_UNSHARED: + return array( + 0 => 'federated_cloud_id', + //1 => 'file', in theory its a file, but it does not exist yet/anymore + ); + case self::SUBJECT_REMOTE_SHARE_ACCEPTED: + case self::SUBJECT_REMOTE_SHARE_DECLINED: + return array( + 0 => 'federated_cloud_id', + 1 => 'file', + ); + case self::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED: + case self::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED: + return array( + 0 => 'file', + ); + case self::SUBJECT_SHARED_LINK_SELF: + case self::SUBJECT_UNSHARED_LINK_SELF: + case self::SUBJECT_LINK_EXPIRED: + return [0 => 'file']; + case self::SUBJECT_RESHARED_LINK_BY: + return [ + 0 => 'file', + 1 => 'username', + 2 => '', + ]; + case self::SUBJECT_SHARED_EMAIL: + return array( + 0 => 'file', + 1 => '',// 'email' is neither supported nor planned for now + ); + + case self::SUBJECT_SHARED_USER_SELF: + case self::SUBJECT_SHARED_WITH_BY: + case self::SUBJECT_UNSHARED_BY: + case self::SUBJECT_UNSHARED_LINK_BY: + case self::SUBJECT_LINK_BY_EXPIRED: + case self::SUBJECT_UNSHARED_USER_SELF: + return [0 => 'file', 1 => 'username']; + case self::SUBJECT_RESHARED_USER_BY: + case self::SUBJECT_UNSHARED_USER_BY: + return [ + 0 => 'file', + 1 => 'username', + 2 => 'username', + ]; + + case self::SUBJECT_SHARED_GROUP_SELF: + case self::SUBJECT_UNSHARED_GROUP_SELF: + return [ + 0 => 'file', + 1 => 'group', + ]; + + case self::SUBJECT_RESHARED_GROUP_BY: + case self::SUBJECT_UNSHARED_GROUP_BY: + return [ + 0 => 'file', + 1 => 'username', + 2 => 'group', + ]; + } + } + + return false; + } + + /** + * The extension can define the parameter grouping by returning the index as integer. + * In case no grouping is required false is to be returned. + * + * @param array $activity + * @return integer|false + */ + public function getGroupParameter($activity) { + if ($activity['app'] === self::FILES_SHARING_APP) { + switch ($activity['subject']) { + case self::SUBJECT_SHARED_LINK_SELF: + case self::SUBJECT_UNSHARED_LINK_SELF: + case self::SUBJECT_LINK_EXPIRED: + case self::SUBJECT_SHARED_WITH_BY: + case self::SUBJECT_UNSHARED_BY: + // Group by file name + return 0; + case self::SUBJECT_SHARED_USER_SELF: + case self::SUBJECT_SHARED_GROUP_SELF: + // Group by user/group + return 1; + } + } + + return false; + } + + /** + * The extension can define additional navigation entries. The array returned has to contain two keys 'top' + * and 'apps' which hold arrays with the relevant entries. + * If no further entries are to be added false is no be returned. + * + * @return array|false + */ + public function getNavigation() { + $l = $this->getL10N(); + return [ + 'apps' => [], + 'top' => [ + self::FILTER_SHARES => [ + 'id' => self::FILTER_SHARES, + 'name' => (string) $l->t('Shares'), + 'url' => $this->URLGenerator->linkToRoute('activity.Activities.showList', ['filter' => self::FILTER_SHARES]), + ], + ], + ]; + } + + /** + * The extension can check if a custom filter (given by a query string like filter=abc) is valid or not. + * + * @param string $filterValue + * @return boolean + */ + public function isFilterValid($filterValue) { + return $filterValue === self::FILTER_SHARES; + } + + /** + * The extension can filter the types based on the filter if required. + * In case no filter is to be applied false is to be returned unchanged. + * + * @param array $types + * @param string $filter + * @return array|false + */ + public function filterNotificationTypes($types, $filter) { + switch ($filter) { + case self::FILTER_SHARES: + return array_intersect([self::TYPE_SHARED, self::TYPE_REMOTE_SHARE], $types); + } + return false; + } + + /** + * For a given filter the extension can specify the sql query conditions including parameters for that query. + * In case the extension does not know the filter false is to be returned. + * The query condition and the parameters are to be returned as array with two elements. + * E.g. return array('`app` = ? and `message` like ?', array('mail', 'ownCloud%')); + * + * @param string $filter + * @return array|false + */ + public function getQueryForFilter($filter) { + if ($filter === self::FILTER_SHARES) { + return [ + '`app` = ?', + [self::FILES_SHARING_APP,], + ]; + } + return false; + } + +} diff --git a/apps/files_sharing/lib/Cache.php b/apps/files_sharing/lib/Cache.php new file mode 100644 index 00000000000..abd75282579 --- /dev/null +++ b/apps/files_sharing/lib/Cache.php @@ -0,0 +1,105 @@ + + * @author Jörn Friedrich Dreyer + * @author Michael Gapczynski + * @author Morris Jobke + * @author Robin Appelman + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing; + +use OC\Files\Cache\Wrapper\CacheJail; +use OCP\Files\Cache\ICacheEntry; +use OCP\Files\Storage\IStorage; + +/** + * Metadata cache for shared files + * + * don't use this class directly if you need to get metadata, use \OC\Files\Filesystem::getFileInfo instead + */ +class Cache extends CacheJail { + /** + * @var \OC\Files\Storage\Shared + */ + private $storage; + + /** + * @var IStorage + */ + private $sourceStorage; + + /** + * @var ICacheEntry + */ + private $sourceRootInfo; + + /** + * @var \OCP\Files\Cache\ICache + */ + private $sourceCache; + + /** + * @param \OC\Files\Storage\Shared $storage + * @param IStorage $sourceStorage + * @param ICacheEntry $sourceRootInfo + */ + public function __construct($storage, IStorage $sourceStorage, ICacheEntry $sourceRootInfo) { + $this->storage = $storage; + $this->sourceStorage = $sourceStorage; + $this->sourceRootInfo = $sourceRootInfo; + $this->sourceCache = $sourceStorage->getCache(); + parent::__construct( + $this->sourceCache, + $this->sourceRootInfo->getPath() + ); + } + + public function getNumericStorageId() { + if (isset($this->numericId)) { + return $this->numericId; + } else { + return false; + } + } + + protected function formatCacheEntry($entry) { + $path = $entry['path']; + $entry = parent::formatCacheEntry($entry); + $sharePermissions = $this->storage->getPermissions($path); + if (isset($entry['permissions'])) { + $entry['permissions'] &= $sharePermissions; + } else { + $entry['permissions'] = $sharePermissions; + } + $entry['uid_owner'] = $this->storage->getOwner($path); + $entry['displayname_owner'] = \OC_User::getDisplayName($entry['uid_owner']); + if ($path === '') { + $entry['is_share_mount_point'] = true; + } + return $entry; + } + + /** + * remove all entries for files that are stored on the storage from the cache + */ + public function clear() { + // Not a valid action for Shared Cache + } +} diff --git a/apps/files_sharing/lib/Capabilities.php b/apps/files_sharing/lib/Capabilities.php new file mode 100644 index 00000000000..5ec540ad4e0 --- /dev/null +++ b/apps/files_sharing/lib/Capabilities.php @@ -0,0 +1,91 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ +namespace OCA\Files_Sharing; + +use OCP\Capabilities\ICapability; +use \OCP\IConfig; + +/** + * Class Capabilities + * + * @package OCA\Files_Sharing + */ +class Capabilities implements ICapability { + + /** @var IConfig */ + private $config; + + public function __construct(IConfig $config) { + $this->config = $config; + } + + /** + * Return this classes capabilities + * + * @return array + */ + public function getCapabilities() { + $res = []; + + if ($this->config->getAppValue('core', 'shareapi_enabled', 'yes') !== 'yes') { + $res['api_enabled'] = false; + $res['public'] = ['enabled' => false]; + $res['user'] = ['send_mail' => false]; + $res['resharing'] = false; + } else { + $res['api_enabled'] = true; + + $public = []; + $public['enabled'] = $this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'yes'; + if ($public['enabled']) { + $public['password'] = []; + $public['password']['enforced'] = ($this->config->getAppValue('core', 'shareapi_enforce_links_password', 'no') === 'yes'); + + $public['expire_date'] = []; + $public['expire_date']['enabled'] = $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no') === 'yes'; + if ($public['expire_date']['enabled']) { + $public['expire_date']['days'] = $this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7'); + $public['expire_date']['enforced'] = $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes'; + } + + $public['send_mail'] = $this->config->getAppValue('core', 'shareapi_allow_public_notification', 'no') === 'yes'; + $public['upload'] = $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes') === 'yes'; + } + $res["public"] = $public; + + $res['user']['send_mail'] = $this->config->getAppValue('core', 'shareapi_allow_mail_notification', 'no') === 'yes'; + + $res['resharing'] = $this->config->getAppValue('core', 'shareapi_allow_resharing', 'yes') === 'yes'; + + $res['group_sharing'] = $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'yes'; + } + + //Federated sharing + $res['federation'] = [ + 'outgoing' => $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes', + 'incoming' => $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes') === 'yes' + ]; + + return [ + 'files_sharing' => $res, + ]; + } +} diff --git a/apps/files_sharing/lib/Controllers/ExternalSharesController.php b/apps/files_sharing/lib/Controllers/ExternalSharesController.php new file mode 100644 index 00000000000..beefb4d7027 --- /dev/null +++ b/apps/files_sharing/lib/Controllers/ExternalSharesController.php @@ -0,0 +1,149 @@ + + * @author Lukas Reschke + * @author Morris Jobke + * @author Robin Appelman + * @author Roeland Jago Douma + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Controllers; + +use OCP\AppFramework\Controller; +use OCP\IRequest; +use OCP\AppFramework\Http\JSONResponse; +use OCP\Http\Client\IClientService; +use OCP\AppFramework\Http\DataResponse; + +/** + * Class ExternalSharesController + * + * @package OCA\Files_Sharing\Controllers + */ +class ExternalSharesController extends Controller { + + /** @var \OCA\Files_Sharing\External\Manager */ + private $externalManager; + /** @var IClientService */ + private $clientService; + + /** + * @param string $appName + * @param IRequest $request + * @param \OCA\Files_Sharing\External\Manager $externalManager + * @param IClientService $clientService + */ + public function __construct($appName, + IRequest $request, + \OCA\Files_Sharing\External\Manager $externalManager, + IClientService $clientService) { + parent::__construct($appName, $request); + $this->externalManager = $externalManager; + $this->clientService = $clientService; + } + + /** + * @NoAdminRequired + * @NoOutgoingFederatedSharingRequired + * + * @return JSONResponse + */ + public function index() { + return new JSONResponse($this->externalManager->getOpenShares()); + } + + /** + * @NoAdminRequired + * @NoOutgoingFederatedSharingRequired + * + * @param int $id + * @return JSONResponse + */ + public function create($id) { + $this->externalManager->acceptShare($id); + return new JSONResponse(); + } + + /** + * @NoAdminRequired + * @NoOutgoingFederatedSharingRequired + * + * @param integer $id + * @return JSONResponse + */ + public function destroy($id) { + $this->externalManager->declineShare($id); + return new JSONResponse(); + } + + /** + * Test whether the specified remote is accessible + * + * @param string $remote + * @param bool $checkVersion + * @return bool + */ + protected function testUrl($remote, $checkVersion = false) { + try { + $client = $this->clientService->newClient(); + $response = json_decode($client->get( + $remote, + [ + 'timeout' => 3, + 'connect_timeout' => 3, + ] + )->getBody()); + + if ($checkVersion) { + return !empty($response->version) && version_compare($response->version, '7.0.0', '>='); + } else { + return is_object($response); + } + } catch (\Exception $e) { + return false; + } + } + + /** + * @PublicPage + * @NoOutgoingFederatedSharingRequired + * @NoIncomingFederatedSharingRequired + * + * @param string $remote + * @return DataResponse + */ + public function testRemote($remote) { + if ( + $this->testUrl('https://' . $remote . '/ocs-provider/') || + $this->testUrl('https://' . $remote . '/ocs-provider/index.php') || + $this->testUrl('https://' . $remote . '/status.php', true) + ) { + return new DataResponse('https'); + } elseif ( + $this->testUrl('http://' . $remote . '/ocs-provider/') || + $this->testUrl('http://' . $remote . '/ocs-provider/index.php') || + $this->testUrl('http://' . $remote . '/status.php', true) + ) { + return new DataResponse('http'); + } else { + return new DataResponse(false); + } + } + +} diff --git a/apps/files_sharing/lib/Controllers/ShareController.php b/apps/files_sharing/lib/Controllers/ShareController.php new file mode 100644 index 00000000000..04912d20afc --- /dev/null +++ b/apps/files_sharing/lib/Controllers/ShareController.php @@ -0,0 +1,511 @@ + + * @author Björn Schießle + * @author Georg Ehrke + * @author Joas Schilling + * @author Lukas Reschke + * @author Morris Jobke + * @author Robin Appelman + * @author Robin McCorkell + * @author Roeland Jago Douma + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Controllers; + +use OC; +use OC_Files; +use OC_Util; +use OCA\FederatedFileSharing\FederatedShareProvider; +use OCP; +use OCP\Template; +use OCP\Share; +use OCP\AppFramework\Controller; +use OCP\IRequest; +use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Http\RedirectResponse; +use OCP\AppFramework\Http\NotFoundResponse; +use OCP\IURLGenerator; +use OCP\IConfig; +use OCP\ILogger; +use OCP\IUserManager; +use OCP\ISession; +use OCP\IPreview; +use OCA\Files_Sharing\Helper; +use OCP\Util; +use OCA\Files_Sharing\Activity; +use \OCP\Files\NotFoundException; +use OCP\Files\IRootFolder; +use OCP\Share\Exceptions\ShareNotFound; + +/** + * Class ShareController + * + * @package OCA\Files_Sharing\Controllers + */ +class ShareController extends Controller { + + /** @var IConfig */ + protected $config; + /** @var IURLGenerator */ + protected $urlGenerator; + /** @var IUserManager */ + protected $userManager; + /** @var ILogger */ + protected $logger; + /** @var OCP\Activity\IManager */ + protected $activityManager; + /** @var OCP\Share\IManager */ + protected $shareManager; + /** @var ISession */ + protected $session; + /** @var IPreview */ + protected $previewManager; + /** @var IRootFolder */ + protected $rootFolder; + /** @var FederatedShareProvider */ + protected $federatedShareProvider; + + /** + * @param string $appName + * @param IRequest $request + * @param IConfig $config + * @param IURLGenerator $urlGenerator + * @param IUserManager $userManager + * @param ILogger $logger + * @param OCP\Activity\IManager $activityManager + * @param \OCP\Share\IManager $shareManager + * @param ISession $session + * @param IPreview $previewManager + * @param IRootFolder $rootFolder + * @param FederatedShareProvider $federatedShareProvider + */ + public function __construct($appName, + IRequest $request, + IConfig $config, + IURLGenerator $urlGenerator, + IUserManager $userManager, + ILogger $logger, + \OCP\Activity\IManager $activityManager, + \OCP\Share\IManager $shareManager, + ISession $session, + IPreview $previewManager, + IRootFolder $rootFolder, + FederatedShareProvider $federatedShareProvider) { + parent::__construct($appName, $request); + + $this->config = $config; + $this->urlGenerator = $urlGenerator; + $this->userManager = $userManager; + $this->logger = $logger; + $this->activityManager = $activityManager; + $this->shareManager = $shareManager; + $this->session = $session; + $this->previewManager = $previewManager; + $this->rootFolder = $rootFolder; + $this->federatedShareProvider = $federatedShareProvider; + } + + /** + * @PublicPage + * @NoCSRFRequired + * + * @param string $token + * @return TemplateResponse|RedirectResponse + */ + public function showAuthenticate($token) { + $share = $this->shareManager->getShareByToken($token); + + if($this->linkShareAuth($share)) { + return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token))); + } + + return new TemplateResponse($this->appName, 'authenticate', array(), 'guest'); + } + + /** + * @PublicPage + * @UseSession + * + * Authenticates against password-protected shares + * @param string $token + * @param string $password + * @return RedirectResponse|TemplateResponse + */ + public function authenticate($token, $password = '') { + + // Check whether share exists + try { + $share = $this->shareManager->getShareByToken($token); + } catch (ShareNotFound $e) { + return new NotFoundResponse(); + } + + $authenticate = $this->linkShareAuth($share, $password); + + if($authenticate === true) { + return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token))); + } + + return new TemplateResponse($this->appName, 'authenticate', array('wrongpw' => true), 'guest'); + } + + /** + * Authenticate a link item with the given password. + * Or use the session if no password is provided. + * + * This is a modified version of Helper::authenticate + * TODO: Try to merge back eventually with Helper::authenticate + * + * @param \OCP\Share\IShare $share + * @param string|null $password + * @return bool + */ + private function linkShareAuth(\OCP\Share\IShare $share, $password = null) { + if ($password !== null) { + if ($this->shareManager->checkPassword($share, $password)) { + $this->session->set('public_link_authenticated', (string)$share->getId()); + } else { + $this->emitAccessShareHook($share, 403, 'Wrong password'); + return false; + } + } else { + // not authenticated ? + if ( ! $this->session->exists('public_link_authenticated') + || $this->session->get('public_link_authenticated') !== (string)$share->getId()) { + return false; + } + } + return true; + } + + /** + * throws hooks when a share is attempted to be accessed + * + * @param \OCP\Share\IShare|string $share the Share instance if available, + * otherwise token + * @param int $errorCode + * @param string $errorMessage + * @throws OC\HintException + * @throws OC\ServerNotAvailableException + */ + protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') { + $itemType = $itemSource = $uidOwner = ''; + $token = $share; + $exception = null; + if($share instanceof \OCP\Share\IShare) { + try { + $token = $share->getToken(); + $uidOwner = $share->getSharedBy(); + $itemType = $share->getNodeType(); + $itemSource = $share->getNodeId(); + } catch (\Exception $e) { + // we log what we know and pass on the exception afterwards + $exception = $e; + } + } + \OC_Hook::emit('OCP\Share', 'share_link_access', [ + 'itemType' => $itemType, + 'itemSource' => $itemSource, + 'uidOwner' => $uidOwner, + 'token' => $token, + 'errorCode' => $errorCode, + 'errorMessage' => $errorMessage, + ]); + if(!is_null($exception)) { + throw $exception; + } + } + + /** + * Validate the permissions of the share + * + * @param Share\IShare $share + * @return bool + */ + private function validateShare(\OCP\Share\IShare $share) { + return $share->getNode()->isReadable() && $share->getNode()->isShareable(); + } + + /** + * @PublicPage + * @NoCSRFRequired + * + * @param string $token + * @param string $path + * @return TemplateResponse|RedirectResponse + * @throws NotFoundException + */ + public function showShare($token, $path = '') { + \OC_User::setIncognitoMode(true); + + // Check whether share exists + try { + $share = $this->shareManager->getShareByToken($token); + } catch (ShareNotFound $e) { + $this->emitAccessShareHook($token, 404, 'Share not found'); + return new NotFoundResponse(); + } + + // Share is password protected - check whether the user is permitted to access the share + if ($share->getPassword() !== null && !$this->linkShareAuth($share)) { + return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate', + array('token' => $token))); + } + + if (!$this->validateShare($share)) { + throw new NotFoundException(); + } + // We can't get the path of a file share + try { + if ($share->getNode() instanceof \OCP\Files\File && $path !== '') { + $this->emitAccessShareHook($share, 404, 'Share not found'); + throw new NotFoundException(); + } + } catch (\Exception $e) { + $this->emitAccessShareHook($share, 404, 'Share not found'); + throw $e; + } + + $rootFolder = null; + if ($share->getNode() instanceof \OCP\Files\Folder) { + /** @var \OCP\Files\Folder $rootFolder */ + $rootFolder = $share->getNode(); + + try { + $path = $rootFolder->get($path); + } catch (\OCP\Files\NotFoundException $e) { + $this->emitAccessShareHook($share, 404, 'Share not found'); + throw new NotFoundException(); + } + } + + $shareTmpl = []; + $shareTmpl['displayName'] = $this->userManager->get($share->getShareOwner())->getDisplayName(); + $shareTmpl['owner'] = $share->getShareOwner(); + $shareTmpl['filename'] = $share->getNode()->getName(); + $shareTmpl['directory_path'] = $share->getTarget(); + $shareTmpl['mimetype'] = $share->getNode()->getMimetype(); + $shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($share->getNode()->getMimetype()); + $shareTmpl['dirToken'] = $token; + $shareTmpl['sharingToken'] = $token; + $shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled(); + $shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false'; + $shareTmpl['dir'] = ''; + $shareTmpl['nonHumanFileSize'] = $share->getNode()->getSize(); + $shareTmpl['fileSize'] = \OCP\Util::humanFileSize($share->getNode()->getSize()); + + // Show file list + if ($share->getNode() instanceof \OCP\Files\Folder) { + $shareTmpl['dir'] = $rootFolder->getRelativePath($path->getPath()); + + /* + * The OC_Util methods require a view. This just uses the node API + */ + $freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath()); + if ($freeSpace !== \OCP\Files\FileInfo::SPACE_UNKNOWN) { + $freeSpace = max($freeSpace, 0); + } else { + $freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188 + } + + $uploadLimit = Util::uploadLimit(); + $maxUploadFilesize = min($freeSpace, $uploadLimit); + + $folder = new Template('files', 'list', ''); + $folder->assign('dir', $rootFolder->getRelativePath($path->getPath())); + $folder->assign('dirToken', $token); + $folder->assign('permissions', \OCP\Constants::PERMISSION_READ); + $folder->assign('isPublic', true); + $folder->assign('publicUploadEnabled', 'no'); + $folder->assign('uploadMaxFilesize', $maxUploadFilesize); + $folder->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize)); + $folder->assign('freeSpace', $freeSpace); + $folder->assign('uploadLimit', $uploadLimit); // PHP upload limit + $folder->assign('usedSpacePercent', 0); + $folder->assign('trash', false); + $shareTmpl['folder'] = $folder->fetchPage(); + } + + $shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', array('token' => $token)); + $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10); + $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true); + $shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024); + $shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024); + + $csp = new OCP\AppFramework\Http\ContentSecurityPolicy(); + $csp->addAllowedFrameDomain('\'self\''); + $response = new TemplateResponse($this->appName, 'public', $shareTmpl, 'base'); + $response->setContentSecurityPolicy($csp); + + $this->emitAccessShareHook($share); + + return $response; + } + + /** + * @PublicPage + * @NoCSRFRequired + * + * @param string $token + * @param string $files + * @param string $path + * @param string $downloadStartSecret + * @return void|RedirectResponse + */ + public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') { + \OC_User::setIncognitoMode(true); + + $share = $this->shareManager->getShareByToken($token); + + // Share is password protected - check whether the user is permitted to access the share + if ($share->getPassword() !== null && !$this->linkShareAuth($share)) { + return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate', + ['token' => $token])); + } + + $files_list = null; + if (!is_null($files)) { // download selected files + $files_list = json_decode($files); + // in case we get only a single file + if ($files_list === null) { + $files_list = [$files]; + } + } + + $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner()); + $originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath()); + + if (!$this->validateShare($share)) { + throw new NotFoundException(); + } + + // Single file share + if ($share->getNode() instanceof \OCP\Files\File) { + // Single file download + $event = $this->activityManager->generateEvent(); + $event->setApp('files_sharing') + ->setType(Activity::TYPE_PUBLIC_LINKS) + ->setSubject(Activity::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED, [$userFolder->getRelativePath($share->getNode()->getPath())]) + ->setAffectedUser($share->getShareOwner()) + ->setObject('files', $share->getNode()->getId(), $userFolder->getRelativePath($share->getNode()->getPath())); + $this->activityManager->publish($event); + } + // Directory share + else { + /** @var \OCP\Files\Folder $node */ + $node = $share->getNode(); + + // Try to get the path + if ($path !== '') { + try { + $node = $node->get($path); + } catch (NotFoundException $e) { + $this->emitAccessShareHook($share, 404, 'Share not found'); + return new NotFoundResponse(); + } + } + + $originalSharePath = $userFolder->getRelativePath($node->getPath()); + + if ($node instanceof \OCP\Files\File) { + // Single file download + $event = $this->activityManager->generateEvent(); + $event->setApp('files_sharing') + ->setType(Activity::TYPE_PUBLIC_LINKS) + ->setSubject(Activity::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED, [$userFolder->getRelativePath($node->getPath())]) + ->setAffectedUser($share->getShareOwner()) + ->setObject('files', $node->getId(), $userFolder->getRelativePath($node->getPath())); + $this->activityManager->publish($event); + } else if (!empty($files_list)) { + /** @var \OCP\Files\Folder $node */ + + // Subset of files is downloaded + foreach ($files_list as $file) { + $subNode = $node->get($file); + + $event = $this->activityManager->generateEvent(); + $event->setApp('files_sharing') + ->setType(Activity::TYPE_PUBLIC_LINKS) + ->setAffectedUser($share->getShareOwner()) + ->setObject('files', $subNode->getId(), $userFolder->getRelativePath($subNode->getPath())); + + if ($subNode instanceof \OCP\Files\File) { + $event->setSubject(Activity::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED, [$userFolder->getRelativePath($subNode->getPath())]); + } else { + $event->setSubject(Activity::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED, [$userFolder->getRelativePath($subNode->getPath())]); + } + + $this->activityManager->publish($event); + } + } else { + // The folder is downloaded + $event = $this->activityManager->generateEvent(); + $event->setApp('files_sharing') + ->setType(Activity::TYPE_PUBLIC_LINKS) + ->setSubject(Activity::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED, [$userFolder->getRelativePath($node->getPath())]) + ->setAffectedUser($share->getShareOwner()) + ->setObject('files', $node->getId(), $userFolder->getRelativePath($node->getPath())); + $this->activityManager->publish($event); + } + } + + /* FIXME: We should do this all nicely in OCP */ + OC_Util::tearDownFS(); + OC_Util::setupFS($share->getShareOwner()); + + /** + * this sets a cookie to be able to recognize the start of the download + * the content must not be longer than 32 characters and must only contain + * alphanumeric characters + */ + if (!empty($downloadStartSecret) + && !isset($downloadStartSecret[32]) + && preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) { + + // FIXME: set on the response once we use an actual app framework response + setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/'); + } + + $this->emitAccessShareHook($share); + + $server_params = array( 'head' => $this->request->getMethod() == 'HEAD' ); + + /** + * Http range requests support + */ + if (isset($_SERVER['HTTP_RANGE'])) { + $server_params['range'] = $this->request->getHeader('Range'); + } + + // download selected files + if (!is_null($files) && $files !== '') { + // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well + // after dispatching the request which results in a "Cannot modify header information" notice. + OC_Files::get($originalSharePath, $files_list, $server_params); + exit(); + } else { + // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well + // after dispatching the request which results in a "Cannot modify header information" notice. + OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params); + exit(); + } + } +} diff --git a/apps/files_sharing/lib/Exceptions/BrokenPath.php b/apps/files_sharing/lib/Exceptions/BrokenPath.php new file mode 100644 index 00000000000..4639d47c4a6 --- /dev/null +++ b/apps/files_sharing/lib/Exceptions/BrokenPath.php @@ -0,0 +1,32 @@ + + * @author Morris Jobke + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Exceptions; + +/** + * Expected path with a different root + * Possible Error Codes: + * 10 - Path not relative to data/ and point to the users file directory + + */ +class BrokenPath extends \Exception { +} diff --git a/apps/files_sharing/lib/Exceptions/S2SException.php b/apps/files_sharing/lib/Exceptions/S2SException.php new file mode 100644 index 00000000000..1ed6a9e2179 --- /dev/null +++ b/apps/files_sharing/lib/Exceptions/S2SException.php @@ -0,0 +1,30 @@ + + * @author Morris Jobke + * @author Roeland Jago Douma + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Exceptions; + +/** + * S2S sharing not allowed + */ +class S2SException extends \Exception { +} diff --git a/apps/files_sharing/lib/ExpireSharesJob.php b/apps/files_sharing/lib/ExpireSharesJob.php new file mode 100644 index 00000000000..479f407e68f --- /dev/null +++ b/apps/files_sharing/lib/ExpireSharesJob.php @@ -0,0 +1,76 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing; + +use OC\BackgroundJob\TimedJob; + +/** + * Delete all shares that are expired + */ +class ExpireSharesJob extends TimedJob { + + /** + * sets the correct interval for this timed job + */ + public function __construct() { + // Run once a day + $this->setInterval(24 * 60 * 60); + } + + /** + * Makes the background job do its work + * + * @param array $argument unused argument + */ + public function run($argument) { + $connection = \OC::$server->getDatabaseConnection(); + $logger = \OC::$server->getLogger(); + + //Current time + $now = new \DateTime(); + $now = $now->format('Y-m-d H:i:s'); + + /* + * Expire file link shares only (for now) + */ + $qb = $connection->getQueryBuilder(); + $qb->select('id', 'file_source', 'uid_owner', 'item_type') + ->from('share') + ->where( + $qb->expr()->andX( + $qb->expr()->eq('share_type', $qb->expr()->literal(\OCP\Share::SHARE_TYPE_LINK)), + $qb->expr()->lte('expiration', $qb->expr()->literal($now)), + $qb->expr()->orX( + $qb->expr()->eq('item_type', $qb->expr()->literal('file')), + $qb->expr()->eq('item_type', $qb->expr()->literal('folder')) + ) + ) + ); + + $shares = $qb->execute(); + while($share = $shares->fetch()) { + \OCP\Share::unshare($share['item_type'], $share['file_source'], \OCP\Share::SHARE_TYPE_LINK, null, $share['uid_owner']); + } + $shares->closeCursor(); + } + +} diff --git a/apps/files_sharing/lib/External/Cache.php b/apps/files_sharing/lib/External/Cache.php new file mode 100644 index 00000000000..da9bf83cdfa --- /dev/null +++ b/apps/files_sharing/lib/External/Cache.php @@ -0,0 +1,65 @@ + + * @author Robin Appelman + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\External; + +class Cache extends \OC\Files\Cache\Cache { + private $remote; + private $remoteUser; + private $storage; + + /** + * @param \OCA\Files_Sharing\External\Storage $storage + * @param string $remote + * @param string $remoteUser + */ + public function __construct($storage, $remote, $remoteUser) { + $this->storage = $storage; + list(, $remote) = explode('://', $remote, 2); + $this->remote = $remote; + $this->remoteUser = $remoteUser; + parent::__construct($storage); + } + + public function get($file) { + $result = parent::get($file); + if (!$result) { + return false; + } + $result['displayname_owner'] = $this->remoteUser . '@' . $this->remote; + if (!$file || $file === '') { + $result['is_share_mount_point'] = true; + $mountPoint = rtrim($this->storage->getMountPoint()); + $result['name'] = basename($mountPoint); + } + return $result; + } + + public function getFolderContentsById($id) { + $results = parent::getFolderContentsById($id); + foreach ($results as &$file) { + $file['displayname_owner'] = $this->remoteUser . '@' . $this->remote; + } + return $results; + } +} diff --git a/apps/files_sharing/lib/External/Manager.php b/apps/files_sharing/lib/External/Manager.php new file mode 100644 index 00000000000..5b7a13f1eb1 --- /dev/null +++ b/apps/files_sharing/lib/External/Manager.php @@ -0,0 +1,453 @@ + + * @author Joas Schilling + * @author Jörn Friedrich Dreyer + * @author Lukas Reschke + * @author Morris Jobke + * @author Robin Appelman + * @author Roeland Jago Douma + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\External; + +use OC\Files\Filesystem; +use OCA\FederatedFileSharing\DiscoveryManager; +use OCP\Files; +use OCP\Notification\IManager; + +class Manager { + const STORAGE = '\OCA\Files_Sharing\External\Storage'; + + /** + * @var string + */ + private $uid; + + /** + * @var \OCP\IDBConnection + */ + private $connection; + + /** + * @var \OC\Files\Mount\Manager + */ + private $mountManager; + + /** + * @var \OCP\Files\Storage\IStorageFactory + */ + private $storageLoader; + + /** + * @var \OC\HTTPHelper + */ + private $httpHelper; + + /** + * @var IManager + */ + private $notificationManager; + /** @var DiscoveryManager */ + private $discoveryManager; + + /** + * @param \OCP\IDBConnection $connection + * @param \OC\Files\Mount\Manager $mountManager + * @param \OCP\Files\Storage\IStorageFactory $storageLoader + * @param \OC\HTTPHelper $httpHelper + * @param IManager $notificationManager + * @param DiscoveryManager $discoveryManager + * @param string $uid + */ + public function __construct(\OCP\IDBConnection $connection, + \OC\Files\Mount\Manager $mountManager, + \OCP\Files\Storage\IStorageFactory $storageLoader, + \OC\HTTPHelper $httpHelper, + IManager $notificationManager, + DiscoveryManager $discoveryManager, + $uid) { + $this->connection = $connection; + $this->mountManager = $mountManager; + $this->storageLoader = $storageLoader; + $this->httpHelper = $httpHelper; + $this->uid = $uid; + $this->notificationManager = $notificationManager; + $this->discoveryManager = $discoveryManager; + } + + /** + * add new server-to-server share + * + * @param string $remote + * @param string $token + * @param string $password + * @param string $name + * @param string $owner + * @param boolean $accepted + * @param string $user + * @param int $remoteId + * @return Mount|null + */ + public function addShare($remote, $token, $password, $name, $owner, $accepted=false, $user = null, $remoteId = -1) { + + $user = $user ? $user : $this->uid; + $accepted = $accepted ? 1 : 0; + $name = Filesystem::normalizePath('/' . $name); + + if (!$accepted) { + // To avoid conflicts with the mount point generation later, + // we only use a temporary mount point name here. The real + // mount point name will be generated when accepting the share, + // using the original share item name. + $tmpMountPointName = '{{TemporaryMountPointName#' . $name . '}}'; + $mountPoint = $tmpMountPointName; + $hash = md5($tmpMountPointName); + $data = [ + 'remote' => $remote, + 'share_token' => $token, + 'password' => $password, + 'name' => $name, + 'owner' => $owner, + 'user' => $user, + 'mountpoint' => $mountPoint, + 'mountpoint_hash' => $hash, + 'accepted' => $accepted, + 'remote_id' => $remoteId, + ]; + + $i = 1; + while (!$this->connection->insertIfNotExist('*PREFIX*share_external', $data, ['user', 'mountpoint_hash'])) { + // The external share already exists for the user + $data['mountpoint'] = $tmpMountPointName . '-' . $i; + $data['mountpoint_hash'] = md5($data['mountpoint']); + $i++; + } + return null; + } + + $mountPoint = Files::buildNotExistingFileName('/', $name); + $mountPoint = Filesystem::normalizePath('/' . $mountPoint); + $hash = md5($mountPoint); + + $query = $this->connection->prepare(' + INSERT INTO `*PREFIX*share_external` + (`remote`, `share_token`, `password`, `name`, `owner`, `user`, `mountpoint`, `mountpoint_hash`, `accepted`, `remote_id`) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + '); + $query->execute(array($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId)); + + $options = array( + 'remote' => $remote, + 'token' => $token, + 'password' => $password, + 'mountpoint' => $mountPoint, + 'owner' => $owner + ); + return $this->mountShare($options); + } + + /** + * get share + * + * @param int $id share id + * @return mixed share of false + */ + public function getShare($id) { + $getShare = $this->connection->prepare(' + SELECT `id`, `remote`, `remote_id`, `share_token`, `name`, `owner`, `user`, `mountpoint`, `accepted` + FROM `*PREFIX*share_external` + WHERE `id` = ? AND `user` = ?'); + $result = $getShare->execute(array($id, $this->uid)); + + return $result ? $getShare->fetch() : false; + } + + /** + * accept server-to-server share + * + * @param int $id + * @return bool True if the share could be accepted, false otherwise + */ + public function acceptShare($id) { + + $share = $this->getShare($id); + + if ($share) { + $mountPoint = Files::buildNotExistingFileName('/', $share['name']); + $mountPoint = Filesystem::normalizePath('/' . $mountPoint); + $hash = md5($mountPoint); + + $acceptShare = $this->connection->prepare(' + UPDATE `*PREFIX*share_external` + SET `accepted` = ?, + `mountpoint` = ?, + `mountpoint_hash` = ? + WHERE `id` = ? AND `user` = ?'); + $acceptShare->execute(array(1, $mountPoint, $hash, $id, $this->uid)); + $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'accept'); + + \OC_Hook::emit('OCP\Share', 'federated_share_added', ['server' => $share['remote']]); + + $this->processNotification($id); + return true; + } + + return false; + } + + /** + * decline server-to-server share + * + * @param int $id + * @return bool True if the share could be declined, false otherwise + */ + public function declineShare($id) { + + $share = $this->getShare($id); + + if ($share) { + $removeShare = $this->connection->prepare(' + DELETE FROM `*PREFIX*share_external` WHERE `id` = ? AND `user` = ?'); + $removeShare->execute(array($id, $this->uid)); + $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline'); + + $this->processNotification($id); + return true; + } + + return false; + } + + /** + * @param int $remoteShare + */ + public function processNotification($remoteShare) { + $filter = $this->notificationManager->createNotification(); + $filter->setApp('files_sharing') + ->setUser($this->uid) + ->setObject('remote_share', (int) $remoteShare); + $this->notificationManager->markProcessed($filter); + } + + /** + * inform remote server whether server-to-server share was accepted/declined + * + * @param string $remote + * @param string $token + * @param int $remoteId Share id on the remote host + * @param string $feedback + * @return boolean + */ + private function sendFeedbackToRemote($remote, $token, $remoteId, $feedback) { + + $url = rtrim($remote, '/') . $this->discoveryManager->getShareEndpoint($remote) . '/' . $remoteId . '/' . $feedback . '?format=' . \OCP\Share::RESPONSE_FORMAT; + $fields = array('token' => $token); + + $result = $this->httpHelper->post($url, $fields); + $status = json_decode($result['result'], true); + + return ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200)); + } + + /** + * remove '/user/files' from the path and trailing slashes + * + * @param string $path + * @return string + */ + protected function stripPath($path) { + $prefix = '/' . $this->uid . '/files'; + return rtrim(substr($path, strlen($prefix)), '/'); + } + + public function getMount($data) { + $data['manager'] = $this; + $mountPoint = '/' . $this->uid . '/files' . $data['mountpoint']; + $data['mountpoint'] = $mountPoint; + $data['certificateManager'] = \OC::$server->getCertificateManager($this->uid); + return new Mount(self::STORAGE, $mountPoint, $data, $this, $this->storageLoader); + } + + /** + * @param array $data + * @return Mount + */ + protected function mountShare($data) { + $mount = $this->getMount($data); + $this->mountManager->addMount($mount); + return $mount; + } + + /** + * @return \OC\Files\Mount\Manager + */ + public function getMountManager() { + return $this->mountManager; + } + + /** + * @param string $source + * @param string $target + * @return bool + */ + public function setMountPoint($source, $target) { + $source = $this->stripPath($source); + $target = $this->stripPath($target); + $sourceHash = md5($source); + $targetHash = md5($target); + + $query = $this->connection->prepare(' + UPDATE `*PREFIX*share_external` + SET `mountpoint` = ?, `mountpoint_hash` = ? + WHERE `mountpoint_hash` = ? + AND `user` = ? + '); + $result = (bool)$query->execute(array($target, $targetHash, $sourceHash, $this->uid)); + + return $result; + } + + public function removeShare($mountPoint) { + + $mountPointObj = $this->mountManager->find($mountPoint); + $id = $mountPointObj->getStorage()->getCache()->getId(); + + $mountPoint = $this->stripPath($mountPoint); + $hash = md5($mountPoint); + + $getShare = $this->connection->prepare(' + SELECT `remote`, `share_token`, `remote_id` + FROM `*PREFIX*share_external` + WHERE `mountpoint_hash` = ? AND `user` = ?'); + $result = $getShare->execute(array($hash, $this->uid)); + + if ($result) { + $share = $getShare->fetch(); + $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline'); + } + $getShare->closeCursor(); + + $query = $this->connection->prepare(' + DELETE FROM `*PREFIX*share_external` + WHERE `mountpoint_hash` = ? + AND `user` = ? + '); + $result = (bool)$query->execute(array($hash, $this->uid)); + + if($result) { + $this->removeReShares($id); + } + + return $result; + } + + /** + * remove re-shares from share table and mapping in the federated_reshares table + * + * @param $mountPointId + */ + protected function removeReShares($mountPointId) { + $selectQuery = $this->connection->getQueryBuilder(); + $query = $this->connection->getQueryBuilder(); + $selectQuery->select('id')->from('share') + ->where($selectQuery->expr()->eq('file_source', $query->createNamedParameter($mountPointId))); + $select = $selectQuery->getSQL(); + + + $query->delete('federated_reshares') + ->where($query->expr()->in('share_id', $query->createFunction('(' . $select . ')'))); + $query->execute(); + + $deleteReShares = $this->connection->getQueryBuilder(); + $deleteReShares->delete('share') + ->where($deleteReShares->expr()->eq('file_source', $deleteReShares->createNamedParameter($mountPointId))); + $deleteReShares->execute(); + } + + /** + * remove all shares for user $uid if the user was deleted + * + * @param string $uid + * @return bool + */ + public function removeUserShares($uid) { + $getShare = $this->connection->prepare(' + SELECT `remote`, `share_token`, `remote_id` + FROM `*PREFIX*share_external` + WHERE `user` = ?'); + $result = $getShare->execute(array($uid)); + + if ($result) { + $shares = $getShare->fetchAll(); + foreach($shares as $share) { + $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline'); + } + } + + $query = $this->connection->prepare(' + DELETE FROM `*PREFIX*share_external` + WHERE `user` = ? + '); + return (bool)$query->execute(array($uid)); + } + + /** + * return a list of shares which are not yet accepted by the user + * + * @return array list of open server-to-server shares + */ + public function getOpenShares() { + return $this->getShares(false); + } + + /** + * return a list of shares which are accepted by the user + * + * @return array list of accepted server-to-server shares + */ + public function getAcceptedShares() { + return $this->getShares(true); + } + + /** + * return a list of shares for the user + * + * @param bool|null $accepted True for accepted only, + * false for not accepted, + * null for all shares of the user + * @return array list of open server-to-server shares + */ + private function getShares($accepted) { + $query = 'SELECT `id`, `remote`, `remote_id`, `share_token`, `name`, `owner`, `user`, `mountpoint`, `accepted` + FROM `*PREFIX*share_external` + WHERE `user` = ?'; + $parameters = [$this->uid]; + if (!is_null($accepted)) { + $query .= ' AND `accepted` = ?'; + $parameters[] = (int) $accepted; + } + $query .= ' ORDER BY `id` ASC'; + + $shares = $this->connection->prepare($query); + $result = $shares->execute($parameters); + + return $result ? $shares->fetchAll() : []; + } +} diff --git a/apps/files_sharing/lib/External/Mount.php b/apps/files_sharing/lib/External/Mount.php new file mode 100644 index 00000000000..9cf66d3f8f0 --- /dev/null +++ b/apps/files_sharing/lib/External/Mount.php @@ -0,0 +1,70 @@ + + * @author Morris Jobke + * @author Robin Appelman + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\External; + +use OC\Files\Mount\MountPoint; +use OC\Files\Mount\MoveableMount; + +class Mount extends MountPoint implements MoveableMount { + + /** + * @var \OCA\Files_Sharing\External\Manager + */ + protected $manager; + + /** + * @param string|\OC\Files\Storage\Storage $storage + * @param string $mountpoint + * @param array $options + * @param \OCA\Files_Sharing\External\Manager $manager + * @param \OC\Files\Storage\StorageFactory $loader + */ + public function __construct($storage, $mountpoint, $options, $manager, $loader = null) { + parent::__construct($storage, $mountpoint, $options, $loader); + $this->manager = $manager; + } + + /** + * Move the mount point to $target + * + * @param string $target the target mount point + * @return bool + */ + public function moveMount($target) { + $result = $this->manager->setMountPoint($this->mountPoint, $target); + $this->setMountPoint($target); + + return $result; + } + + /** + * Remove the mount points + * + * @return mixed + * @return bool + */ + public function removeMount() { + return $this->manager->removeShare($this->mountPoint); + } +} diff --git a/apps/files_sharing/lib/External/MountProvider.php b/apps/files_sharing/lib/External/MountProvider.php new file mode 100644 index 00000000000..67d85f27d81 --- /dev/null +++ b/apps/files_sharing/lib/External/MountProvider.php @@ -0,0 +1,76 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\External; + +use OCP\Files\Config\IMountProvider; +use OCP\Files\Storage\IStorageFactory; +use OCP\IDBConnection; +use OCP\IUser; + +class MountProvider implements IMountProvider { + const STORAGE = '\OCA\Files_Sharing\External\Storage'; + + /** + * @var \OCP\IDBConnection + */ + private $connection; + + /** + * @var callable + */ + private $managerProvider; + + /** + * @param \OCP\IDBConnection $connection + * @param callable $managerProvider due to setup order we need a callable that return the manager instead of the manager itself + */ + public function __construct(IDBConnection $connection, callable $managerProvider) { + $this->connection = $connection; + $this->managerProvider = $managerProvider; + } + + public function getMount(IUser $user, $data, IStorageFactory $storageFactory) { + $managerProvider = $this->managerProvider; + $manager = $managerProvider(); + $data['manager'] = $manager; + $mountPoint = '/' . $user->getUID() . '/files/' . ltrim($data['mountpoint'], '/'); + $data['mountpoint'] = $mountPoint; + $data['certificateManager'] = \OC::$server->getCertificateManager($user->getUID()); + return new Mount(self::STORAGE, $mountPoint, $data, $manager, $storageFactory); + } + + public function getMountsForUser(IUser $user, IStorageFactory $loader) { + $query = $this->connection->prepare(' + SELECT `remote`, `share_token`, `password`, `mountpoint`, `owner` + FROM `*PREFIX*share_external` + WHERE `user` = ? AND `accepted` = ? + '); + $query->execute([$user->getUID(), 1]); + $mounts = []; + while ($row = $query->fetch()) { + $row['manager'] = $this; + $row['token'] = $row['share_token']; + $mounts[] = $this->getMount($user, $row, $loader); + } + return $mounts; + } +} diff --git a/apps/files_sharing/lib/External/Scanner.php b/apps/files_sharing/lib/External/Scanner.php new file mode 100644 index 00000000000..1cc6cf8f5f9 --- /dev/null +++ b/apps/files_sharing/lib/External/Scanner.php @@ -0,0 +1,127 @@ + + * @author Morris Jobke + * @author Olivier Paroz + * @author Robin Appelman + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\External; + +use OC\ForbiddenException; +use OCP\Files\NotFoundException; +use OCP\Files\StorageInvalidException; +use OCP\Files\StorageNotAvailableException; + +class Scanner extends \OC\Files\Cache\Scanner { + /** @var \OCA\Files_Sharing\External\Storage */ + protected $storage; + + /** {@inheritDoc} */ + public function scan($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $lock = true) { + if(!$this->storage->remoteIsOwnCloud()) { + return parent::scan($path, $recursive, $recursive, $lock); + } + + $this->scanAll(); + } + + /** + * Scan a single file and store it in the cache. + * If an exception happened while accessing the external storage, + * the storage will be checked for availability and removed + * if it is not available any more. + * + * @param string $file file to scan + * @param int $reuseExisting + * @param int $parentId + * @param array | null $cacheData existing data in the cache for the file to be scanned + * @param bool $lock set to false to disable getting an additional read lock during scanning + * @return array an array of metadata of the scanned file + */ + public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true) { + try { + return parent::scanFile($file, $reuseExisting); + } catch (ForbiddenException $e) { + $this->storage->checkStorageAvailability(); + } catch (NotFoundException $e) { + // if the storage isn't found, the call to + // checkStorageAvailable() will verify it and remove it + // if appropriate + $this->storage->checkStorageAvailability(); + } catch (StorageInvalidException $e) { + $this->storage->checkStorageAvailability(); + } catch (StorageNotAvailableException $e) { + $this->storage->checkStorageAvailability(); + } + } + + /** + * Checks the remote share for changes. + * If changes are available, scan them and update + * the cache. + * @throws NotFoundException + * @throws StorageInvalidException + * @throws \Exception + */ + public function scanAll() { + try { + $data = $this->storage->getShareInfo(); + } catch (\Exception $e) { + $this->storage->checkStorageAvailability(); + throw new \Exception( + 'Error while scanning remote share: "' . + $this->storage->getRemote() . '" ' . + $e->getMessage() + ); + } + if ($data['status'] === 'success') { + $this->addResult($data['data'], ''); + } else { + throw new \Exception( + 'Error while scanning remote share: "' . + $this->storage->getRemote() . '"' + ); + } + } + + /** + * @param array $data + * @param string $path + */ + private function addResult($data, $path) { + $id = $this->cache->put($path, $data); + if (isset($data['children'])) { + $children = []; + foreach ($data['children'] as $child) { + $children[$child['name']] = true; + $this->addResult($child, ltrim($path . '/' . $child['name'], '/')); + } + + $existingCache = $this->cache->getFolderContentsById($id); + foreach ($existingCache as $existingChild) { + // if an existing child is not in the new data, remove it + if (!isset($children[$existingChild['name']])) { + $this->cache->remove(ltrim($path . '/' . $existingChild['name'], '/')); + } + } + } + } +} diff --git a/apps/files_sharing/lib/External/Storage.php b/apps/files_sharing/lib/External/Storage.php new file mode 100644 index 00000000000..4382dcab0c3 --- /dev/null +++ b/apps/files_sharing/lib/External/Storage.php @@ -0,0 +1,339 @@ + + * @author Morris Jobke + * @author Robin Appelman + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\External; + +use GuzzleHttp\Exception\ClientException; +use GuzzleHttp\Exception\ConnectException; +use OC\Files\Storage\DAV; +use OC\ForbiddenException; +use OCA\FederatedFileSharing\DiscoveryManager; +use OCA\Files_Sharing\ISharedStorage; +use OCP\Files\NotFoundException; +use OCP\Files\StorageInvalidException; +use OCP\Files\StorageNotAvailableException; + +class Storage extends DAV implements ISharedStorage { + /** @var string */ + private $remoteUser; + /** @var string */ + private $remote; + /** @var string */ + private $mountPoint; + /** @var string */ + private $token; + /** @var \OCP\ICacheFactory */ + private $memcacheFactory; + /** @var \OCP\Http\Client\IClientService */ + private $httpClient; + /** @var \OCP\ICertificateManager */ + private $certificateManager; + /** @var bool */ + private $updateChecked = false; + + /** + * @var \OCA\Files_Sharing\External\Manager + */ + private $manager; + + public function __construct($options) { + $this->memcacheFactory = \OC::$server->getMemCacheFactory(); + $this->httpClient = \OC::$server->getHTTPClientService(); + $discoveryManager = new DiscoveryManager( + $this->memcacheFactory, + \OC::$server->getHTTPClientService() + ); + + $this->manager = $options['manager']; + $this->certificateManager = $options['certificateManager']; + $this->remote = $options['remote']; + $this->remoteUser = $options['owner']; + list($protocol, $remote) = explode('://', $this->remote); + if (strpos($remote, '/')) { + list($host, $root) = explode('/', $remote, 2); + } else { + $host = $remote; + $root = ''; + } + $secure = $protocol === 'https'; + $root = rtrim($root, '/') . $discoveryManager->getWebDavEndpoint($this->remote); + $this->mountPoint = $options['mountpoint']; + $this->token = $options['token']; + parent::__construct(array( + 'secure' => $secure, + 'host' => $host, + 'root' => $root, + 'user' => $options['token'], + 'password' => (string)$options['password'] + )); + + $this->getWatcher()->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE); + } + + public function getRemoteUser() { + return $this->remoteUser; + } + + public function getRemote() { + return $this->remote; + } + + public function getMountPoint() { + return $this->mountPoint; + } + + public function getToken() { + return $this->token; + } + + public function getPassword() { + return $this->password; + } + + /** + * @brief get id of the mount point + * @return string + */ + public function getId() { + return 'shared::' . md5($this->token . '@' . $this->remote); + } + + public function getCache($path = '', $storage = null) { + if (is_null($this->cache)) { + $this->cache = new Cache($this, $this->remote, $this->remoteUser); + } + return $this->cache; + } + + /** + * @param string $path + * @param \OC\Files\Storage\Storage $storage + * @return \OCA\Files_Sharing\External\Scanner + */ + public function getScanner($path = '', $storage = null) { + if (!$storage) { + $storage = $this; + } + if (!isset($this->scanner)) { + $this->scanner = new Scanner($storage); + } + return $this->scanner; + } + + /** + * check if a file or folder has been updated since $time + * + * @param string $path + * @param int $time + * @throws \OCP\Files\StorageNotAvailableException + * @throws \OCP\Files\StorageInvalidException + * @return bool + */ + public function hasUpdated($path, $time) { + // since for owncloud webdav servers we can rely on etag propagation we only need to check the root of the storage + // because of that we only do one check for the entire storage per request + if ($this->updateChecked) { + return false; + } + $this->updateChecked = true; + try { + return parent::hasUpdated('', $time); + } catch (StorageInvalidException $e) { + // check if it needs to be removed + $this->checkStorageAvailability(); + throw $e; + } catch (StorageNotAvailableException $e) { + // check if it needs to be removed or just temp unavailable + $this->checkStorageAvailability(); + throw $e; + } + } + + /** + * Check whether this storage is permanently or temporarily + * unavailable + * + * @throws \OCP\Files\StorageNotAvailableException + * @throws \OCP\Files\StorageInvalidException + */ + public function checkStorageAvailability() { + // see if we can find out why the share is unavailable + try { + $this->getShareInfo(); + } catch (NotFoundException $e) { + // a 404 can either mean that the share no longer exists or there is no ownCloud on the remote + if ($this->testRemote()) { + // valid ownCloud instance means that the public share no longer exists + // since this is permanent (re-sharing the file will create a new token) + // we remove the invalid storage + $this->manager->removeShare($this->mountPoint); + $this->manager->getMountManager()->removeMount($this->mountPoint); + throw new StorageInvalidException(); + } else { + // ownCloud instance is gone, likely to be a temporary server configuration error + throw new StorageNotAvailableException(); + } + } catch (ForbiddenException $e) { + // auth error, remove share for now (provide a dialog in the future) + $this->manager->removeShare($this->mountPoint); + $this->manager->getMountManager()->removeMount($this->mountPoint); + throw new StorageInvalidException(); + } catch (\GuzzleHttp\Exception\ConnectException $e) { + throw new StorageNotAvailableException(); + } catch (\GuzzleHttp\Exception\RequestException $e) { + throw new StorageNotAvailableException(); + } catch (\Exception $e) { + throw $e; + } + } + + public function file_exists($path) { + if ($path === '') { + return true; + } else { + return parent::file_exists($path); + } + } + + /** + * check if the configured remote is a valid federated share provider + * + * @return bool + */ + protected function testRemote() { + try { + return $this->testRemoteUrl($this->remote . '/ocs-provider/index.php') + || $this->testRemoteUrl($this->remote . '/ocs-provider/') + || $this->testRemoteUrl($this->remote . '/status.php'); + } catch (\Exception $e) { + return false; + } + } + + /** + * @param string $url + * @return bool + */ + private function testRemoteUrl($url) { + $cache = $this->memcacheFactory->create('files_sharing_remote_url'); + if($cache->hasKey($url)) { + return (bool)$cache->get($url); + } + + $client = $this->httpClient->newClient(); + try { + $result = $client->get($url)->getBody(); + $data = json_decode($result); + $returnValue = (is_object($data) && !empty($data->version)); + } catch (ConnectException $e) { + $returnValue = false; + } catch (ClientException $e) { + $returnValue = false; + } + + $cache->set($url, $returnValue); + return $returnValue; + } + + /** + * Whether the remote is an ownCloud, used since some sharing features are not + * standardized. Let's use this to detect whether to use it. + * + * @return bool + */ + public function remoteIsOwnCloud() { + if(defined('PHPUNIT_RUN') || !$this->testRemoteUrl($this->getRemote() . '/status.php')) { + return false; + } + return true; + } + + /** + * @return mixed + * @throws ForbiddenException + * @throws NotFoundException + * @throws \Exception + */ + public function getShareInfo() { + $remote = $this->getRemote(); + $token = $this->getToken(); + $password = $this->getPassword(); + + // If remote is not an ownCloud do not try to get any share info + if(!$this->remoteIsOwnCloud()) { + return ['status' => 'unsupported']; + } + + $url = rtrim($remote, '/') . '/index.php/apps/files_sharing/shareinfo?t=' . $token; + + // TODO: DI + $client = \OC::$server->getHTTPClientService()->newClient(); + try { + $response = $client->post($url, ['body' => ['password' => $password]]); + } catch (\GuzzleHttp\Exception\RequestException $e) { + if ($e->getCode() === 401 || $e->getCode() === 403) { + throw new ForbiddenException(); + } + if ($e->getCode() === 404) { + throw new NotFoundException(); + } + // throw this to be on the safe side: the share will still be visible + // in the UI in case the failure is intermittent, and the user will + // be able to decide whether to remove it if it's really gone + throw new StorageNotAvailableException(); + } + + return json_decode($response->getBody(), true); + } + + public function getOwner($path) { + list(, $remote) = explode('://', $this->remote, 2); + return $this->remoteUser . '@' . $remote; + } + + public function isSharable($path) { + if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) { + return false; + } + return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_SHARE); + } + + public function getPermissions($path) { + $response = $this->propfind($path); + if (isset($response['{http://open-collaboration-services.org/ns}share-permissions'])) { + $permissions = $response['{http://open-collaboration-services.org/ns}share-permissions']; + } else { + // use default permission if remote server doesn't provide the share permissions + if ($this->is_dir($path)) { + $permissions = \OCP\Constants::PERMISSION_ALL; + } else { + $permissions = \OCP\Constants::PERMISSION_ALL & ~\OCP\Constants::PERMISSION_CREATE; + } + } + + return $permissions; + } + +} diff --git a/apps/files_sharing/lib/Helper.php b/apps/files_sharing/lib/Helper.php new file mode 100644 index 00000000000..500d82cb2d2 --- /dev/null +++ b/apps/files_sharing/lib/Helper.php @@ -0,0 +1,310 @@ + + * @author Björn Schießle + * @author Joas Schilling + * @author Jörn Friedrich Dreyer + * @author Lukas Reschke + * @author Morris Jobke + * @author Robin Appelman + * @author Roeland Jago Douma + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ +namespace OCA\Files_Sharing; + +use OC\Files\Filesystem; +use OC\Files\View; +use OCP\Files\NotFoundException; +use OCP\User; + +class Helper { + + public static function registerHooks() { + \OCP\Util::connectHook('OC_Filesystem', 'post_rename', '\OCA\Files_Sharing\Updater', 'renameHook'); + \OCP\Util::connectHook('OC_Filesystem', 'post_delete', '\OCA\Files_Sharing\Hooks', 'unshareChildren'); + \OCP\Util::connectHook('OC_Appconfig', 'post_set_value', '\OCA\Files_Sharing\Maintainer', 'configChangeHook'); + + \OCP\Util::connectHook('OC_User', 'post_deleteUser', '\OCA\Files_Sharing\Hooks', 'deleteUser'); + } + + /** + * Sets up the filesystem and user for public sharing + * @param string $token string share token + * @param string $relativePath optional path relative to the share + * @param string $password optional password + * @return array + */ + public static function setupFromToken($token, $relativePath = null, $password = null) { + \OC_User::setIncognitoMode(true); + + $linkItem = \OCP\Share::getShareByToken($token, !$password); + if($linkItem === false || ($linkItem['item_type'] !== 'file' && $linkItem['item_type'] !== 'folder')) { + \OC_Response::setStatus(404); + \OCP\Util::writeLog('core-preview', 'Passed token parameter is not valid', \OCP\Util::DEBUG); + exit; + } + + if(!isset($linkItem['uid_owner']) || !isset($linkItem['file_source'])) { + \OC_Response::setStatus(500); + \OCP\Util::writeLog('core-preview', 'Passed token seems to be valid, but it does not contain all necessary information . ("' . $token . '")', \OCP\Util::WARN); + exit; + } + + $rootLinkItem = \OCP\Share::resolveReShare($linkItem); + $path = null; + if (isset($rootLinkItem['uid_owner'])) { + \OCP\JSON::checkUserExists($rootLinkItem['uid_owner']); + \OC_Util::tearDownFS(); + \OC_Util::setupFS($rootLinkItem['uid_owner']); + } + + try { + $path = Filesystem::getPath($linkItem['file_source']); + } catch (NotFoundException $e) { + \OCP\Util::writeLog('share', 'could not resolve linkItem', \OCP\Util::DEBUG); + \OC_Response::setStatus(404); + \OCP\JSON::error(array('success' => false)); + exit(); + } + + if (!isset($linkItem['item_type'])) { + \OCP\Util::writeLog('share', 'No item type set for share id: ' . $linkItem['id'], \OCP\Util::ERROR); + \OC_Response::setStatus(404); + \OCP\JSON::error(array('success' => false)); + exit(); + } + + if (isset($linkItem['share_with']) && (int)$linkItem['share_type'] === \OCP\Share::SHARE_TYPE_LINK) { + if (!self::authenticate($linkItem, $password)) { + \OC_Response::setStatus(403); + \OCP\JSON::error(array('success' => false)); + exit(); + } + } + + $basePath = $path; + + if ($relativePath !== null && Filesystem::isReadable($basePath . $relativePath)) { + $path .= Filesystem::normalizePath($relativePath); + } + + return array( + 'linkItem' => $linkItem, + 'basePath' => $basePath, + 'realPath' => $path + ); + } + + /** + * Authenticate link item with the given password + * or with the session if no password was given. + * @param array $linkItem link item array + * @param string $password optional password + * + * @return boolean true if authorized, false otherwise + */ + public static function authenticate($linkItem, $password = null) { + if ($password !== null) { + if ($linkItem['share_type'] == \OCP\Share::SHARE_TYPE_LINK) { + // Check Password + $newHash = ''; + if(\OC::$server->getHasher()->verify($password, $linkItem['share_with'], $newHash)) { + // Save item id in session for future requests + \OC::$server->getSession()->set('public_link_authenticated', $linkItem['id']); + + /** + * FIXME: Migrate old hashes to new hash format + * Due to the fact that there is no reasonable functionality to update the password + * of an existing share no migration is yet performed there. + * The only possibility is to update the existing share which will result in a new + * share ID and is a major hack. + * + * In the future the migration should be performed once there is a proper method + * to update the share's password. (for example `$share->updatePassword($password)` + * + * @link https://github.com/owncloud/core/issues/10671 + */ + if(!empty($newHash)) { + + } + } else { + return false; + } + } else { + \OCP\Util::writeLog('share', 'Unknown share type '.$linkItem['share_type'] + .' for share id '.$linkItem['id'], \OCP\Util::ERROR); + return false; + } + + } + else { + // not authenticated ? + if ( ! \OC::$server->getSession()->exists('public_link_authenticated') + || \OC::$server->getSession()->get('public_link_authenticated') !== $linkItem['id']) { + return false; + } + } + return true; + } + + public static function getSharesFromItem($target) { + $result = array(); + $owner = Filesystem::getOwner($target); + Filesystem::initMountPoints($owner); + $info = Filesystem::getFileInfo($target); + $ownerView = new View('/'.$owner.'/files'); + if ( $owner != User::getUser() ) { + $path = $ownerView->getPath($info['fileid']); + } else { + $path = $target; + } + + + $ids = array(); + while ($path !== dirname($path)) { + $info = $ownerView->getFileInfo($path); + if ($info instanceof \OC\Files\FileInfo) { + $ids[] = $info['fileid']; + } else { + \OCP\Util::writeLog('sharing', 'No fileinfo available for: ' . $path, \OCP\Util::WARN); + } + $path = dirname($path); + } + + if (!empty($ids)) { + + $idList = array_chunk($ids, 99, true); + + foreach ($idList as $subList) { + $statement = "SELECT `share_with`, `share_type`, `file_target` FROM `*PREFIX*share` WHERE `file_source` IN (" . implode(',', $subList) . ") AND `share_type` IN (0, 1, 2)"; + $query = \OCP\DB::prepare($statement); + $r = $query->execute(); + $result = array_merge($result, $r->fetchAll()); + } + } + + return $result; + } + + /** + * get the UID of the owner of the file and the path to the file relative to + * owners files folder + * + * @param $filename + * @return array + * @throws \OC\User\NoUserException + */ + public static function getUidAndFilename($filename) { + $uid = Filesystem::getOwner($filename); + $userManager = \OC::$server->getUserManager(); + // if the user with the UID doesn't exists, e.g. because the UID points + // to a remote user with a federated cloud ID we use the current logged-in + // user. We need a valid local user to create the share + if (!$userManager->userExists($uid)) { + $uid = User::getUser(); + } + Filesystem::initMountPoints($uid); + if ( $uid != User::getUser() ) { + $info = Filesystem::getFileInfo($filename); + $ownerView = new View('/'.$uid.'/files'); + try { + $filename = $ownerView->getPath($info['fileid']); + } catch (NotFoundException $e) { + $filename = null; + } + } + return [$uid, $filename]; + } + + /** + * Format a path to be relative to the /user/files/ directory + * @param string $path the absolute path + * @return string e.g. turns '/admin/files/test.txt' into 'test.txt' + */ + public static function stripUserFilesPath($path) { + $trimmed = ltrim($path, '/'); + $split = explode('/', $trimmed); + + // it is not a file relative to data/user/files + if (count($split) < 3 || $split[1] !== 'files') { + return false; + } + + $sliced = array_slice($split, 2); + $relPath = implode('/', $sliced); + + return $relPath; + } + + /** + * check if file name already exists and generate unique target + * + * @param string $path + * @param array $excludeList + * @param View $view + * @return string $path + */ + public static function generateUniqueTarget($path, $excludeList, $view) { + $pathinfo = pathinfo($path); + $ext = (isset($pathinfo['extension'])) ? '.'.$pathinfo['extension'] : ''; + $name = $pathinfo['filename']; + $dir = $pathinfo['dirname']; + $i = 2; + while ($view->file_exists($path) || in_array($path, $excludeList)) { + $path = Filesystem::normalizePath($dir . '/' . $name . ' ('.$i.')' . $ext); + $i++; + } + + return $path; + } + + /** + * get default share folder + * + * @return string + */ + public static function getShareFolder() { + $shareFolder = \OC::$server->getConfig()->getSystemValue('share_folder', '/'); + $shareFolder = Filesystem::normalizePath($shareFolder); + + if (!Filesystem::file_exists($shareFolder)) { + $dir = ''; + $subdirs = explode('/', $shareFolder); + foreach ($subdirs as $subdir) { + $dir = $dir . '/' . $subdir; + if (!Filesystem::is_dir($dir)) { + Filesystem::mkdir($dir); + } + } + } + + return $shareFolder; + + } + + /** + * set default share folder + * + * @param string $shareFolder + */ + public static function setShareFolder($shareFolder) { + \OC::$server->getConfig()->setSystemValue('share_folder', $shareFolder); + } + +} diff --git a/apps/files_sharing/lib/Hooks.php b/apps/files_sharing/lib/Hooks.php new file mode 100644 index 00000000000..4882ffcb001 --- /dev/null +++ b/apps/files_sharing/lib/Hooks.php @@ -0,0 +1,64 @@ + + * @author Joas Schilling + * @author Lukas Reschke + * @author Morris Jobke + * @author Robin Appelman + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing; + +use OC\Files\Filesystem; +use OCA\FederatedFileSharing\DiscoveryManager; + +class Hooks { + + public static function deleteUser($params) { + $discoveryManager = new DiscoveryManager( + \OC::$server->getMemCacheFactory(), + \OC::$server->getHTTPClientService() + ); + $manager = new External\Manager( + \OC::$server->getDatabaseConnection(), + \OC\Files\Filesystem::getMountManager(), + \OC\Files\Filesystem::getLoader(), + \OC::$server->getHTTPHelper(), + \OC::$server->getNotificationManager(), + $discoveryManager, + $params['uid']); + + $manager->removeUserShares($params['uid']); + } + + public static function unshareChildren($params) { + $path = Filesystem::getView()->getAbsolutePath($params['path']); + $view = new \OC\Files\View('/'); + + // find share mount points within $path and unmount them + $mountManager = \OC\Files\Filesystem::getMountManager(); + $mountedShares = $mountManager->findIn($path); + foreach ($mountedShares as $mount) { + if ($mount->getStorage()->instanceOfStorage('OCA\Files_Sharing\ISharedStorage')) { + $mountPoint = $mount->getMountPoint(); + $view->unlink($mountPoint); + } + } + } +} diff --git a/apps/files_sharing/lib/ISharedStorage.php b/apps/files_sharing/lib/ISharedStorage.php new file mode 100644 index 00000000000..bb47b011f48 --- /dev/null +++ b/apps/files_sharing/lib/ISharedStorage.php @@ -0,0 +1,27 @@ + + * @author Robin Appelman + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing; + +interface ISharedStorage{ + +} diff --git a/apps/files_sharing/lib/Maintainer.php b/apps/files_sharing/lib/Maintainer.php new file mode 100644 index 00000000000..1d06a34bd0c --- /dev/null +++ b/apps/files_sharing/lib/Maintainer.php @@ -0,0 +1,45 @@ + + * @author Robin McCorkell + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing; + +/** + * Maintains stuff around the sharing functionality + * + * for example: on disable of "allow links" it removes all link shares + */ + +class Maintainer { + + /** + * Keeps track of the "allow links" config setting + * and removes all link shares if the config option is set to "no" + * + * @param array $params array with app, key, value as named values + */ + static public function configChangeHook($params) { + if($params['app'] === 'core' && $params['key'] === 'shareapi_allow_links' && $params['value'] === 'no') { + \OCP\Share::removeAllLinkShares(); + } + } + +} diff --git a/apps/files_sharing/lib/Middleware/SharingCheckMiddleware.php b/apps/files_sharing/lib/Middleware/SharingCheckMiddleware.php new file mode 100644 index 00000000000..a4a968b37fa --- /dev/null +++ b/apps/files_sharing/lib/Middleware/SharingCheckMiddleware.php @@ -0,0 +1,161 @@ + + * @author Morris Jobke + * @author Roeland Jago Douma + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Middleware; + +use OCP\App\IAppManager; +use OCP\AppFramework\Http\NotFoundResponse; +use OCP\AppFramework\Middleware; +use OCP\Files\NotFoundException; +use OCP\IConfig; +use OCP\AppFramework\Utility\IControllerMethodReflector; +use OCA\Files_Sharing\Exceptions\S2SException; +use OCP\AppFramework\Http\JSONResponse; + +/** + * Checks whether the "sharing check" is enabled + * + * @package OCA\Files_Sharing\Middleware + */ +class SharingCheckMiddleware extends Middleware { + + /** @var string */ + protected $appName; + /** @var IConfig */ + protected $config; + /** @var IAppManager */ + protected $appManager; + /** @var IControllerMethodReflector */ + protected $reflector; + + /*** + * @param string $appName + * @param IConfig $config + * @param IAppManager $appManager + */ + public function __construct($appName, + IConfig $config, + IAppManager $appManager, + IControllerMethodReflector $reflector + ) { + $this->appName = $appName; + $this->config = $config; + $this->appManager = $appManager; + $this->reflector = $reflector; + } + + /** + * Check if sharing is enabled before the controllers is executed + * + * @param \OCP\AppFramework\Controller $controller + * @param string $methodName + * @throws NotFoundException + */ + public function beforeController($controller, $methodName) { + if(!$this->isSharingEnabled()) { + throw new NotFoundException('Sharing is disabled.'); + } + + if ($controller instanceof \OCA\Files_Sharing\Controllers\ExternalSharesController && + !$this->externalSharesChecks()) { + throw new S2SException('Federated sharing not allowed'); + } else if ($controller instanceof \OCA\Files_Sharing\Controllers\ShareController && + !$this->isLinkSharingEnabled()) { + throw new NotFoundException('Link sharing is disabled'); + } + } + + /** + * Return 404 page in case of a not found exception + * + * @param \OCP\AppFramework\Controller $controller + * @param string $methodName + * @param \Exception $exception + * @return NotFoundResponse + * @throws \Exception + */ + public function afterException($controller, $methodName, \Exception $exception) { + if(is_a($exception, '\OCP\Files\NotFoundException')) { + return new NotFoundResponse(); + } + + if (is_a($exception, '\OCA\Files_Sharing\Exceptions\S2SException')) { + return new JSONResponse($exception->getMessage(), 405); + } + + throw $exception; + } + + /** + * Checks for externalshares controller + * @return bool + */ + private function externalSharesChecks() { + + if (!$this->reflector->hasAnnotation('NoIncomingFederatedSharingRequired') && + $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes') !== 'yes') { + return false; + } + + if (!$this->reflector->hasAnnotation('NoOutgoingFederatedSharingRequired') && + $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') !== 'yes') { + return false; + } + + return true; + } + + /** + * Check whether sharing is enabled + * @return bool + */ + private function isSharingEnabled() { + // FIXME: This check is done here since the route is globally defined and not inside the files_sharing app + // Check whether the sharing application is enabled + if(!$this->appManager->isEnabledForUser($this->appName)) { + return false; + } + + return true; + } + + /** + * Check if link sharing is allowed + * @return bool + */ + private function isLinkSharingEnabled() { + // Check if the shareAPI is enabled + if ($this->config->getAppValue('core', 'shareapi_enabled', 'yes') !== 'yes') { + return false; + } + + // Check whether public sharing is enabled + if($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') !== 'yes') { + return false; + } + + return true; + } + +} diff --git a/apps/files_sharing/lib/Migration.php b/apps/files_sharing/lib/Migration.php new file mode 100644 index 00000000000..766a7ebd52a --- /dev/null +++ b/apps/files_sharing/lib/Migration.php @@ -0,0 +1,274 @@ + + * @author Morris Jobke + * @author Roeland Jago Douma + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing; + +use Doctrine\DBAL\Connection; +use OCP\IDBConnection; +use OC\Cache\CappedMemoryCache; + +/** + * Class Migration + * + * @package OCA\Files_Sharing + * @group DB + */ +class Migration { + + /** @var IDBConnection */ + private $connection; + + /** @var array with all shares we already saw */ + private $shareCache; + + /** @var string */ + private $table = 'share'; + + public function __construct(IDBConnection $connection) { + $this->connection = $connection; + + // We cache up to 10k share items (~20MB) + $this->shareCache = new CappedMemoryCache(10000); + } + + /** + * move all re-shares to the owner in order to have a flat list of shares + * upgrade from oC 8.2 to 9.0 with the new sharing + */ + public function removeReShares() { + + $stmt = $this->getReShares(); + + $owners = []; + while($share = $stmt->fetch()) { + + $this->shareCache[$share['id']] = $share; + + $owners[$share['id']] = [ + 'owner' => $this->findOwner($share), + 'initiator' => $share['uid_owner'], + 'type' => $share['share_type'], + ]; + + if (count($owners) === 1000) { + $this->updateOwners($owners); + $owners = []; + } + } + + $stmt->closeCursor(); + + if (count($owners)) { + $this->updateOwners($owners); + } + } + + /** + * update all owner information so that all shares have an owner + * and an initiator for the upgrade from oC 8.2 to 9.0 with the new sharing + */ + public function updateInitiatorInfo() { + while (true) { + $shares = $this->getMissingInitiator(1000); + + if (empty($shares)) { + break; + } + + $owners = []; + foreach ($shares as $share) { + $owners[$share['id']] = [ + 'owner' => $share['uid_owner'], + 'initiator' => $share['uid_owner'], + 'type' => $share['share_type'], + ]; + } + $this->updateOwners($owners); + } + } + + /** + * find the owner of a re-shared file/folder + * + * @param array $share + * @return array + */ + private function findOwner($share) { + $currentShare = $share; + while(!is_null($currentShare['parent'])) { + if (isset($this->shareCache[$currentShare['parent']])) { + $currentShare = $this->shareCache[$currentShare['parent']]; + } else { + $currentShare = $this->getShare((int)$currentShare['parent']); + $this->shareCache[$currentShare['id']] = $currentShare; + } + } + + return $currentShare['uid_owner']; + } + + /** + * Get $n re-shares from the database + * + * @param int $n The max number of shares to fetch + * @return \Doctrine\DBAL\Driver\Statement + */ + private function getReShares() { + $query = $this->connection->getQueryBuilder(); + $query->select(['id', 'parent', 'uid_owner', 'share_type']) + ->from($this->table) + ->where($query->expr()->in( + 'share_type', + $query->createNamedParameter( + [ + \OCP\Share::SHARE_TYPE_USER, + \OCP\Share::SHARE_TYPE_GROUP, + \OCP\Share::SHARE_TYPE_LINK, + \OCP\Share::SHARE_TYPE_REMOTE, + ], + Connection::PARAM_INT_ARRAY + ) + )) + ->andWhere($query->expr()->in( + 'item_type', + $query->createNamedParameter( + ['file', 'folder'], + Connection::PARAM_STR_ARRAY + ) + )) + ->andWhere($query->expr()->isNotNull('parent')) + ->orderBy('id', 'asc'); + return $query->execute(); + + + $shares = $result->fetchAll(); + $result->closeCursor(); + + $ordered = []; + foreach ($shares as $share) { + $ordered[(int)$share['id']] = $share; + } + + return $ordered; + } + + /** + * Get $n re-shares from the database + * + * @param int $n The max number of shares to fetch + * @return array + */ + private function getMissingInitiator($n = 1000) { + $query = $this->connection->getQueryBuilder(); + $query->select(['id', 'uid_owner', 'share_type']) + ->from($this->table) + ->where($query->expr()->in( + 'share_type', + $query->createNamedParameter( + [ + \OCP\Share::SHARE_TYPE_USER, + \OCP\Share::SHARE_TYPE_GROUP, + \OCP\Share::SHARE_TYPE_LINK, + \OCP\Share::SHARE_TYPE_REMOTE, + ], + Connection::PARAM_INT_ARRAY + ) + )) + ->andWhere($query->expr()->in( + 'item_type', + $query->createNamedParameter( + ['file', 'folder'], + Connection::PARAM_STR_ARRAY + ) + )) + ->andWhere($query->expr()->isNull('uid_initiator')) + ->orderBy('id', 'asc') + ->setMaxResults($n); + $result = $query->execute(); + $shares = $result->fetchAll(); + $result->closeCursor(); + + $ordered = []; + foreach ($shares as $share) { + $ordered[(int)$share['id']] = $share; + } + + return $ordered; + } + + /** + * get a specific share + * + * @param int $id + * @return array + */ + private function getShare($id) { + $query = $this->connection->getQueryBuilder(); + $query->select(['id', 'parent', 'uid_owner']) + ->from($this->table) + ->where($query->expr()->eq('id', $query->createNamedParameter($id))); + $result = $query->execute(); + $share = $result->fetchAll(); + $result->closeCursor(); + + return $share[0]; + } + + /** + * update database with the new owners + * + * @param array $owners + * @throws \Exception + */ + private function updateOwners($owners) { + + $this->connection->beginTransaction(); + + try { + + foreach ($owners as $id => $owner) { + $query = $this->connection->getQueryBuilder(); + $query->update($this->table) + ->set('uid_owner', $query->createNamedParameter($owner['owner'])) + ->set('uid_initiator', $query->createNamedParameter($owner['initiator'])); + + + if ((int)$owner['type'] !== \OCP\Share::SHARE_TYPE_LINK) { + $query->set('parent', $query->createNamedParameter(null)); + } + + $query->where($query->expr()->eq('id', $query->createNamedParameter($id))); + + $query->execute(); + } + + $this->connection->commit(); + + } catch (\Exception $e) { + $this->connection->rollBack(); + throw $e; + } + + } + +} diff --git a/apps/files_sharing/lib/MountProvider.php b/apps/files_sharing/lib/MountProvider.php new file mode 100644 index 00000000000..8e133951293 --- /dev/null +++ b/apps/files_sharing/lib/MountProvider.php @@ -0,0 +1,83 @@ + + * @author Robin Appelman + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing; + +use OCP\Files\Config\IMountProvider; +use OCP\Files\Storage\IStorageFactory; +use OCP\IConfig; +use OCP\IUser; +use OCP\Share\IManager; + +class MountProvider implements IMountProvider { + /** + * @var \OCP\IConfig + */ + protected $config; + + /** + * @var IManager + */ + protected $shareManager; + + /** + * @param \OCP\IConfig $config + * @param IManager $shareManager + */ + public function __construct(IConfig $config, IManager $shareManager) { + $this->config = $config; + $this->shareManager = $shareManager; + } + + + /** + * Get all mountpoints applicable for the user and check for shares where we need to update the etags + * + * @param \OCP\IUser $user + * @param \OCP\Files\Storage\IStorageFactory $storageFactory + * @return \OCP\Files\Mount\IMountPoint[] + */ + public function getMountsForUser(IUser $user, IStorageFactory $storageFactory) { + $shares = $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_USER, null, -1); + $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_GROUP, null, -1)); + $shares = array_filter($shares, function (\OCP\Share\IShare $share) { + return $share->getPermissions() > 0; + }); + + $mounts = []; + foreach ($shares as $share) { + + $mounts[] = new SharedMount( + '\OC\Files\Storage\Shared', + $mounts, + [ + 'user' => $user->getUID(), + 'newShare' => $share, + ], + $storageFactory + ); + } + + // array_filter removes the null values from the array + return array_filter($mounts); + } +} diff --git a/apps/files_sharing/lib/Scanner.php b/apps/files_sharing/lib/Scanner.php new file mode 100644 index 00000000000..215c0a7b6ae --- /dev/null +++ b/apps/files_sharing/lib/Scanner.php @@ -0,0 +1,75 @@ + + * @author Robin Appelman + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing; + +use OC\Files\ObjectStore\NoopScanner; + +/** + * Scanner for SharedStorage + */ +class Scanner extends \OC\Files\Cache\Scanner { + private $sourceScanner; + + /** + * Returns metadata from the shared storage, but + * with permissions from the source storage. + * + * @param string $path path of the file for which to retrieve metadata + * + * @return array an array of metadata of the file + */ + public function getData($path) { + $data = parent::getData($path); + if ($data === null) { + return null; + } + list($sourceStorage, $internalPath) = $this->storage->resolvePath($path); + $data['permissions'] = $sourceStorage->getPermissions($internalPath); + return $data; + } + + private function getSourceScanner() { + if ($this->sourceScanner) { + return $this->sourceScanner; + } + if ($this->storage->instanceOfStorage('\OC\Files\Storage\Shared')) { + /** @var \OC\Files\Storage\Storage $storage */ + list($storage) = $this->storage->resolvePath(''); + $this->sourceScanner = $storage->getScanner(); + return $this->sourceScanner; + } else { + return null; + } + } + + public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true) { + $sourceScanner = $this->getSourceScanner(); + if ($sourceScanner instanceof NoopScanner) { + return []; + } else { + return parent::scanFile($file, $reuseExisting, $parentId, $cacheData, $lock); + } + } +} + diff --git a/apps/files_sharing/lib/SharedMount.php b/apps/files_sharing/lib/SharedMount.php new file mode 100644 index 00000000000..4aed80b12b2 --- /dev/null +++ b/apps/files_sharing/lib/SharedMount.php @@ -0,0 +1,226 @@ + + * @author Joas Schilling + * @author Morris Jobke + * @author Robin Appelman + * @author Roeland Jago Douma + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing; + +use OC\Files\Filesystem; +use OC\Files\Mount\MountPoint; +use OC\Files\Mount\MoveableMount; +use OC\Files\View; + +/** + * Shared mount points can be moved by the user + */ +class SharedMount extends MountPoint implements MoveableMount { + /** + * @var \OC\Files\Storage\Shared $storage + */ + protected $storage = null; + + /** + * @var \OC\Files\View + */ + private $recipientView; + + /** + * @var string + */ + private $user; + + /** @var \OCP\Share\IShare */ + private $share; + + /** + * @param string $storage + * @param SharedMount[] $mountpoints + * @param array|null $arguments + * @param \OCP\Files\Storage\IStorageFactory $loader + */ + public function __construct($storage, array $mountpoints, $arguments = null, $loader = null) { + $this->user = $arguments['user']; + $this->recipientView = new View('/' . $this->user . '/files'); + $this->share = $arguments['newShare']; + $newMountPoint = $this->verifyMountPoint($this->share, $mountpoints); + $absMountPoint = '/' . $this->user . '/files' . $newMountPoint; + $arguments['ownerView'] = new View('/' . $this->share->getShareOwner() . '/files'); + parent::__construct($storage, $absMountPoint, $arguments, $loader); + } + + /** + * check if the parent folder exists otherwise move the mount point up + * + * @param \OCP\Share\IShare $share + * @param SharedMount[] $mountpoints + * @return string + */ + private function verifyMountPoint(\OCP\Share\IShare $share, array $mountpoints) { + + $mountPoint = basename($share->getTarget()); + $parent = dirname($share->getTarget()); + + if (!$this->recipientView->is_dir($parent)) { + $parent = Helper::getShareFolder(); + } + + $newMountPoint = $this->generateUniqueTarget( + \OC\Files\Filesystem::normalizePath($parent . '/' . $mountPoint), + $this->recipientView, + $mountpoints + ); + + if ($newMountPoint !== $share->getTarget()) { + $this->updateFileTarget($newMountPoint, $share); + } + + return $newMountPoint; + } + + /** + * update fileTarget in the database if the mount point changed + * + * @param string $newPath + * @param \OCP\Share\IShare $share + * @return bool + */ + private function updateFileTarget($newPath, &$share) { + $share->setTarget($newPath); + \OC::$server->getShareManager()->moveShare($share, $this->user); + } + + + /** + * @param string $path + * @param View $view + * @param SharedMount[] $mountpoints + * @return mixed + */ + private function generateUniqueTarget($path, $view, array $mountpoints) { + $pathinfo = pathinfo($path); + $ext = (isset($pathinfo['extension'])) ? '.'.$pathinfo['extension'] : ''; + $name = $pathinfo['filename']; + $dir = $pathinfo['dirname']; + + // Helper function to find existing mount points + $mountpointExists = function($path) use ($mountpoints) { + foreach ($mountpoints as $mountpoint) { + if ($mountpoint->getShare()->getTarget() === $path) { + return true; + } + } + return false; + }; + + $i = 2; + while ($view->file_exists($path) || $mountpointExists($path)) { + $path = Filesystem::normalizePath($dir . '/' . $name . ' ('.$i.')' . $ext); + $i++; + } + + return $path; + } + + /** + * Format a path to be relative to the /user/files/ directory + * + * @param string $path the absolute path + * @return string e.g. turns '/admin/files/test.txt' into '/test.txt' + * @throws \OCA\Files_Sharing\Exceptions\BrokenPath + */ + protected function stripUserFilesPath($path) { + $trimmed = ltrim($path, '/'); + $split = explode('/', $trimmed); + + // it is not a file relative to data/user/files + if (count($split) < 3 || $split[1] !== 'files') { + \OCP\Util::writeLog('file sharing', + 'Can not strip userid and "files/" from path: ' . $path, + \OCP\Util::ERROR); + throw new \OCA\Files_Sharing\Exceptions\BrokenPath('Path does not start with /user/files', 10); + } + + // skip 'user' and 'files' + $sliced = array_slice($split, 2); + $relPath = implode('/', $sliced); + + return '/' . $relPath; + } + + /** + * Move the mount point to $target + * + * @param string $target the target mount point + * @return bool + */ + public function moveMount($target) { + + $relTargetPath = $this->stripUserFilesPath($target); + $share = $this->storage->getShare(); + + $result = true; + + try { + $this->updateFileTarget($relTargetPath, $share); + $this->setMountPoint($target); + $this->storage->setMountPoint($relTargetPath); + } catch (\Exception $e) { + \OCP\Util::writeLog('file sharing', + 'Could not rename mount point for shared folder "' . $this->getMountPoint() . '" to "' . $target . '"', + \OCP\Util::ERROR); + } + + return $result; + } + + /** + * Remove the mount points + * + * @return bool + */ + public function removeMount() { + $mountManager = \OC\Files\Filesystem::getMountManager(); + /** @var $storage \OC\Files\Storage\Shared */ + $storage = $this->getStorage(); + $result = $storage->unshareStorage(); + $mountManager->removeMount($this->mountPoint); + + return $result; + } + + /** + * @return \OCP\Share\IShare + */ + public function getShare() { + return $this->share; + } + + /** + * Get the file id of the root of the storage + * + * @return int + */ + public function getStorageRootId() { + return $this->share->getNodeId(); + } +} diff --git a/apps/files_sharing/lib/SharedPropagator.php b/apps/files_sharing/lib/SharedPropagator.php new file mode 100644 index 00000000000..f17cfc3a75b --- /dev/null +++ b/apps/files_sharing/lib/SharedPropagator.php @@ -0,0 +1,42 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing; + +use OC\Files\Cache\Propagator; + +class SharedPropagator extends Propagator { + /** + * @var \OC\Files\Storage\Shared + */ + protected $storage; + + /** + * @param string $internalPath + * @param int $time + * @param int $sizeDifference + */ + public function propagateChange($internalPath, $time, $sizeDifference = 0) { + /** @var \OC\Files\Storage\Storage $storage */ + list($storage, $sourceInternalPath) = $this->storage->resolvePath($internalPath); + return $storage->getPropagator()->propagateChange($sourceInternalPath, $time, $sizeDifference); + } +} diff --git a/apps/files_sharing/lib/Updater.php b/apps/files_sharing/lib/Updater.php new file mode 100644 index 00000000000..02c349e94b6 --- /dev/null +++ b/apps/files_sharing/lib/Updater.php @@ -0,0 +1,109 @@ + + * @author Joas Schilling + * @author Michael Gapczynski + * @author Morris Jobke + * @author Robin Appelman + * @author Roeland Jago Douma + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing; + +class Updater { + + /** + * @param array $params + */ + static public function renameHook($params) { + self::renameChildren($params['oldpath'], $params['newpath']); + self::moveShareToShare($params['newpath']); + } + + /** + * Fix for https://github.com/owncloud/core/issues/20769 + * + * The owner is allowed to move their files (if they are shared) into a receiving folder + * In this case we need to update the parent of the moved share. Since they are + * effectively handing over ownership of the file the rest of the code needs to know + * they need to build up the reshare tree. + * + * @param string $path + */ + static private function moveShareToShare($path) { + $userFolder = \OC::$server->getUserFolder(); + + // If the user folder can't be constructed (e.g. link share) just return. + if ($userFolder === null) { + return; + } + + $src = $userFolder->get($path); + + $shareManager = \OC::$server->getShareManager(); + + $shares = $shareManager->getSharesBy($userFolder->getOwner()->getUID(), \OCP\Share::SHARE_TYPE_USER, $src, false, -1); + $shares = array_merge($shares, $shareManager->getSharesBy($userFolder->getOwner()->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $src, false, -1)); + + // If the path we move is not a share we don't care + if (empty($shares)) { + return; + } + + // Check if the destination is inside a share + $mountManager = \OC::$server->getMountManager(); + $dstMount = $mountManager->find($src->getPath()); + if (!($dstMount instanceof \OCA\Files_Sharing\SharedMount)) { + return; + } + + $newOwner = $dstMount->getShare()->getShareOwner(); + + //Ownership is moved over + foreach ($shares as $share) { + /** @var \OCP\Share\IShare $share */ + $share->setShareOwner($newOwner); + $shareManager->updateShare($share); + } + } + + /** + * rename mount point from the children if the parent was renamed + * + * @param string $oldPath old path relative to data/user/files + * @param string $newPath new path relative to data/user/files + */ + static private function renameChildren($oldPath, $newPath) { + + $absNewPath = \OC\Files\Filesystem::normalizePath('/' . \OCP\User::getUser() . '/files/' . $newPath); + $absOldPath = \OC\Files\Filesystem::normalizePath('/' . \OCP\User::getUser() . '/files/' . $oldPath); + + $mountManager = \OC\Files\Filesystem::getMountManager(); + $mountedShares = $mountManager->findIn('/' . \OCP\User::getUser() . '/files/' . $oldPath); + foreach ($mountedShares as $mount) { + if ($mount->getStorage()->instanceOfStorage('OCA\Files_Sharing\ISharedStorage')) { + $mountPoint = $mount->getMountPoint(); + $target = str_replace($absOldPath, $absNewPath, $mountPoint); + $mount->moveMount($target); + } + } + } + +} diff --git a/apps/files_sharing/lib/activity.php b/apps/files_sharing/lib/activity.php deleted file mode 100644 index 721379eb78f..00000000000 --- a/apps/files_sharing/lib/activity.php +++ /dev/null @@ -1,483 +0,0 @@ - - * @author Joas Schilling - * @author Morris Jobke - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing; - -use OCP\Activity\IExtension; -use OCP\Activity\IManager; -use OCP\IL10N; -use OCP\IURLGenerator; -use OCP\L10N\IFactory; - -class Activity implements IExtension { - const FILES_SHARING_APP = 'files_sharing'; - /** - * Filter with all sharing related activities - */ - const FILTER_SHARES = 'shares'; - - /** - * Activity types known to this extension - */ - const TYPE_PUBLIC_LINKS = 'public_links'; - const TYPE_REMOTE_SHARE = 'remote_share'; - const TYPE_SHARED = 'shared'; - - /** - * Subject keys for translation of the subjections - */ - const SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED = 'public_shared_file_downloaded'; - const SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED = 'public_shared_folder_downloaded'; - - const SUBJECT_REMOTE_SHARE_ACCEPTED = 'remote_share_accepted'; - const SUBJECT_REMOTE_SHARE_DECLINED = 'remote_share_declined'; - const SUBJECT_REMOTE_SHARE_RECEIVED = 'remote_share_received'; - const SUBJECT_REMOTE_SHARE_UNSHARED = 'remote_share_unshared'; - - const SUBJECT_SHARED_USER_SELF = 'shared_user_self'; - const SUBJECT_RESHARED_USER_BY = 'reshared_user_by'; - const SUBJECT_UNSHARED_USER_SELF = 'unshared_user_self'; - const SUBJECT_UNSHARED_USER_BY = 'unshared_user_by'; - - const SUBJECT_SHARED_GROUP_SELF = 'shared_group_self'; - const SUBJECT_RESHARED_GROUP_BY = 'reshared_group_by'; - const SUBJECT_UNSHARED_GROUP_SELF = 'unshared_group_self'; - const SUBJECT_UNSHARED_GROUP_BY = 'unshared_group_by'; - - const SUBJECT_SHARED_LINK_SELF = 'shared_link_self'; - const SUBJECT_RESHARED_LINK_BY = 'reshared_link_by'; - const SUBJECT_UNSHARED_LINK_SELF = 'unshared_link_self'; - const SUBJECT_UNSHARED_LINK_BY = 'unshared_link_by'; - const SUBJECT_LINK_EXPIRED = 'link_expired'; - const SUBJECT_LINK_BY_EXPIRED = 'link_by_expired'; - - const SUBJECT_SHARED_EMAIL = 'shared_with_email'; - const SUBJECT_SHARED_WITH_BY = 'shared_with_by'; - const SUBJECT_UNSHARED_BY = 'unshared_by'; - - /** @var IFactory */ - protected $languageFactory; - - /** @var IURLGenerator */ - protected $URLGenerator; - - /** @var IManager */ - protected $activityManager; - - /** - * @param IFactory $languageFactory - * @param IURLGenerator $URLGenerator - * @param IManager $activityManager - */ - public function __construct(IFactory $languageFactory, IURLGenerator $URLGenerator, IManager $activityManager) { - $this->languageFactory = $languageFactory; - $this->URLGenerator = $URLGenerator; - $this->activityManager = $activityManager; - } - - protected function getL10N($languageCode = null) { - return $this->languageFactory->get(self::FILES_SHARING_APP, $languageCode); - } - - /** - * The extension can return an array of additional notification types. - * If no additional types are to be added false is to be returned - * - * @param string $languageCode - * @return array|false - */ - public function getNotificationTypes($languageCode) { - $l = $this->getL10N($languageCode); - - return array( - self::TYPE_SHARED => (string) $l->t('A file or folder has been shared'), - self::TYPE_REMOTE_SHARE => (string) $l->t('A file or folder was shared from another server'), - self::TYPE_PUBLIC_LINKS => (string) $l->t('A public shared file or folder was downloaded'), - ); - } - - /** - * For a given method additional types to be displayed in the settings can be returned. - * In case no additional types are to be added false is to be returned. - * - * @param string $method - * @return array|false - */ - public function getDefaultTypes($method) { - $defaultTypes = [ - self::TYPE_SHARED, - self::TYPE_REMOTE_SHARE, - ]; - - if ($method === self::METHOD_STREAM) { - $defaultTypes[] = self::TYPE_PUBLIC_LINKS; - } - - return $defaultTypes; - } - - /** - * A string naming the css class for the icon to be used can be returned. - * If no icon is known for the given type false is to be returned. - * - * @param string $type - * @return string|false - */ - public function getTypeIcon($type) { - switch ($type) { - case self::TYPE_SHARED: - case self::TYPE_REMOTE_SHARE: - return 'icon-share'; - case self::TYPE_PUBLIC_LINKS: - return 'icon-download'; - } - - return false; - } - - /** - * The extension can translate a given message to the requested languages. - * If no translation is available false is to be returned. - * - * @param string $app - * @param string $text - * @param array $params - * @param boolean $stripPath - * @param boolean $highlightParams - * @param string $languageCode - * @return string|false - */ - public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) { - if ($app !== self::FILES_SHARING_APP) { - return false; - } - - $l = $this->getL10N($languageCode); - - if ($this->activityManager->isFormattingFilteredObject()) { - $translation = $this->translateShort($text, $l, $params); - if ($translation !== false) { - return $translation; - } - } - - return $this->translateLong($text, $l, $params); - } - - /** - * @param string $text - * @param IL10N $l - * @param array $params - * @return bool|string - */ - protected function translateLong($text, IL10N $l, array $params) { - - switch ($text) { - case self::SUBJECT_REMOTE_SHARE_RECEIVED: - if (sizeof($params) === 2) { - // New activity ownCloud 8.2+ - return (string) $l->t('You received a new remote share %2$s from %1$s', $params); - } - return (string) $l->t('You received a new remote share from %s', $params); - case self::SUBJECT_REMOTE_SHARE_ACCEPTED: - return (string) $l->t('%1$s accepted remote share %2$s', $params); - case self::SUBJECT_REMOTE_SHARE_DECLINED: - return (string) $l->t('%1$s declined remote share %2$s', $params); - case self::SUBJECT_REMOTE_SHARE_UNSHARED: - return (string) $l->t('%1$s unshared %2$s from you', $params); - case self::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED: - return (string) $l->t('Public shared folder %1$s was downloaded', $params); - case self::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED: - return (string) $l->t('Public shared file %1$s was downloaded', $params); - - case self::SUBJECT_SHARED_USER_SELF: - return (string) $l->t('You shared %1$s with %2$s', $params); - case self::SUBJECT_RESHARED_USER_BY: - return (string) $l->t('%2$s shared %1$s with %3$s', $params); - case self::SUBJECT_UNSHARED_USER_SELF: - return (string) $l->t('You removed the share of %2$s for %1$s', $params); - case self::SUBJECT_UNSHARED_USER_BY: - return (string) $l->t('%2$s removed the share of %3$s for %1$s', $params); - - case self::SUBJECT_SHARED_GROUP_SELF: - return (string) $l->t('You shared %1$s with group %2$s', $params); - case self::SUBJECT_RESHARED_GROUP_BY: - return (string) $l->t('%2$s shared %1$s with group %3$s', $params); - case self::SUBJECT_UNSHARED_GROUP_SELF: - return (string) $l->t('You removed the share of group %2$s for %1$s', $params); - case self::SUBJECT_UNSHARED_GROUP_BY: - return (string) $l->t('%2$s removed the share of group %3$s for %1$s', $params); - - case self::SUBJECT_RESHARED_LINK_BY: - return (string) $l->t('%2$s shared %1$s via link', $params); - case self::SUBJECT_SHARED_LINK_SELF: - return (string) $l->t('You shared %1$s via link', $params); - case self::SUBJECT_UNSHARED_LINK_SELF: - return (string) $l->t('You removed the public link for %1$s', $params); - case self::SUBJECT_UNSHARED_LINK_BY: - return (string) $l->t('%2$s removed the public link for %1$s', $params); - case self::SUBJECT_LINK_EXPIRED: - return (string) $l->t('Your public link for %1$s expired', $params); - case self::SUBJECT_LINK_BY_EXPIRED: - return (string) $l->t('The public link of %2$s for %1$s expired', $params); - - case self::SUBJECT_SHARED_WITH_BY: - return (string) $l->t('%2$s shared %1$s with you', $params); - case self::SUBJECT_UNSHARED_BY: - return (string) $l->t('%2$s removed the share for %1$s', $params); - case self::SUBJECT_SHARED_EMAIL: - return (string) $l->t('You shared %1$s with %2$s', $params); - } - - return false; - } - - /** - * @param string $text - * @param IL10N $l - * @param array $params - * @return bool|string - */ - protected function translateShort($text, IL10N $l, array $params) { - switch ($text) { - case self::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED: - case self::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED: - return (string) $l->t('Downloaded via public link'); - - case self::SUBJECT_SHARED_USER_SELF: - return (string) $l->t('Shared with %2$s', $params); - case self::SUBJECT_RESHARED_USER_BY: - return (string) $l->t('Shared with %3$s by %2$s', $params); - case self::SUBJECT_UNSHARED_USER_SELF: - return (string) $l->t('Removed share for %2$s', $params); - case self::SUBJECT_UNSHARED_USER_BY: - return (string) $l->t('%2$s removed share for %3$s', $params); - - case self::SUBJECT_SHARED_GROUP_SELF: - return (string) $l->t('Shared with group %2$s', $params); - case self::SUBJECT_RESHARED_GROUP_BY: - return (string) $l->t('Shared with group %3$s by %2$s', $params); - case self::SUBJECT_UNSHARED_GROUP_SELF: - return (string) $l->t('Removed share of group %2$s', $params); - case self::SUBJECT_UNSHARED_GROUP_BY: - return (string) $l->t('%2$s removed share of group %3$s', $params); - - case self::SUBJECT_RESHARED_LINK_BY: - return (string) $l->t('Shared via link by %2$s', $params); - case self::SUBJECT_SHARED_LINK_SELF: - return (string) $l->t('Shared via public link'); - case self::SUBJECT_UNSHARED_LINK_SELF: - return (string) $l->t('Removed public link'); - case self::SUBJECT_UNSHARED_LINK_BY: - return (string) $l->t('%2$s removed public link'); - case self::SUBJECT_LINK_EXPIRED: - return (string) $l->t('Public link expired', $params); - case self::SUBJECT_LINK_BY_EXPIRED: - return (string) $l->t('Public link of %2$s expired', $params); - - case self::SUBJECT_SHARED_WITH_BY: - return (string) $l->t('Shared by %2$s', $params); - case self::SUBJECT_SHARED_EMAIL: - return (string) $l->t('Shared with %2$s', $params); - - default: - return false; - } - } - - /** - * The extension can define the type of parameters for translation - * - * Currently known types are: - * * file => will strip away the path of the file and add a tooltip with it - * * username => will add the avatar of the user - * - * @param string $app - * @param string $text - * @return array|false - */ - public function getSpecialParameterList($app, $text) { - if ($app === self::FILES_SHARING_APP) { - switch ($text) { - case self::SUBJECT_REMOTE_SHARE_RECEIVED: - case self::SUBJECT_REMOTE_SHARE_UNSHARED: - return array( - 0 => 'federated_cloud_id', - //1 => 'file', in theory its a file, but it does not exist yet/anymore - ); - case self::SUBJECT_REMOTE_SHARE_ACCEPTED: - case self::SUBJECT_REMOTE_SHARE_DECLINED: - return array( - 0 => 'federated_cloud_id', - 1 => 'file', - ); - case self::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED: - case self::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED: - return array( - 0 => 'file', - ); - case self::SUBJECT_SHARED_LINK_SELF: - case self::SUBJECT_UNSHARED_LINK_SELF: - case self::SUBJECT_LINK_EXPIRED: - return [0 => 'file']; - case self::SUBJECT_RESHARED_LINK_BY: - return [ - 0 => 'file', - 1 => 'username', - 2 => '', - ]; - case self::SUBJECT_SHARED_EMAIL: - return array( - 0 => 'file', - 1 => '',// 'email' is neither supported nor planned for now - ); - - case self::SUBJECT_SHARED_USER_SELF: - case self::SUBJECT_SHARED_WITH_BY: - case self::SUBJECT_UNSHARED_BY: - case self::SUBJECT_UNSHARED_LINK_BY: - case self::SUBJECT_LINK_BY_EXPIRED: - case self::SUBJECT_UNSHARED_USER_SELF: - return [0 => 'file', 1 => 'username']; - case self::SUBJECT_RESHARED_USER_BY: - case self::SUBJECT_UNSHARED_USER_BY: - return [ - 0 => 'file', - 1 => 'username', - 2 => 'username', - ]; - - case self::SUBJECT_SHARED_GROUP_SELF: - case self::SUBJECT_UNSHARED_GROUP_SELF: - return [ - 0 => 'file', - 1 => 'group', - ]; - - case self::SUBJECT_RESHARED_GROUP_BY: - case self::SUBJECT_UNSHARED_GROUP_BY: - return [ - 0 => 'file', - 1 => 'username', - 2 => 'group', - ]; - } - } - - return false; - } - - /** - * The extension can define the parameter grouping by returning the index as integer. - * In case no grouping is required false is to be returned. - * - * @param array $activity - * @return integer|false - */ - public function getGroupParameter($activity) { - if ($activity['app'] === self::FILES_SHARING_APP) { - switch ($activity['subject']) { - case self::SUBJECT_SHARED_LINK_SELF: - case self::SUBJECT_UNSHARED_LINK_SELF: - case self::SUBJECT_LINK_EXPIRED: - case self::SUBJECT_SHARED_WITH_BY: - case self::SUBJECT_UNSHARED_BY: - // Group by file name - return 0; - case self::SUBJECT_SHARED_USER_SELF: - case self::SUBJECT_SHARED_GROUP_SELF: - // Group by user/group - return 1; - } - } - - return false; - } - - /** - * The extension can define additional navigation entries. The array returned has to contain two keys 'top' - * and 'apps' which hold arrays with the relevant entries. - * If no further entries are to be added false is no be returned. - * - * @return array|false - */ - public function getNavigation() { - $l = $this->getL10N(); - return [ - 'apps' => [], - 'top' => [ - self::FILTER_SHARES => [ - 'id' => self::FILTER_SHARES, - 'name' => (string) $l->t('Shares'), - 'url' => $this->URLGenerator->linkToRoute('activity.Activities.showList', ['filter' => self::FILTER_SHARES]), - ], - ], - ]; - } - - /** - * The extension can check if a custom filter (given by a query string like filter=abc) is valid or not. - * - * @param string $filterValue - * @return boolean - */ - public function isFilterValid($filterValue) { - return $filterValue === self::FILTER_SHARES; - } - - /** - * The extension can filter the types based on the filter if required. - * In case no filter is to be applied false is to be returned unchanged. - * - * @param array $types - * @param string $filter - * @return array|false - */ - public function filterNotificationTypes($types, $filter) { - switch ($filter) { - case self::FILTER_SHARES: - return array_intersect([self::TYPE_SHARED, self::TYPE_REMOTE_SHARE], $types); - } - return false; - } - - /** - * For a given filter the extension can specify the sql query conditions including parameters for that query. - * In case the extension does not know the filter false is to be returned. - * The query condition and the parameters are to be returned as array with two elements. - * E.g. return array('`app` = ? and `message` like ?', array('mail', 'ownCloud%')); - * - * @param string $filter - * @return array|false - */ - public function getQueryForFilter($filter) { - if ($filter === self::FILTER_SHARES) { - return [ - '`app` = ?', - [self::FILES_SHARING_APP,], - ]; - } - return false; - } - -} diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php deleted file mode 100644 index abd75282579..00000000000 --- a/apps/files_sharing/lib/cache.php +++ /dev/null @@ -1,105 +0,0 @@ - - * @author Jörn Friedrich Dreyer - * @author Michael Gapczynski - * @author Morris Jobke - * @author Robin Appelman - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing; - -use OC\Files\Cache\Wrapper\CacheJail; -use OCP\Files\Cache\ICacheEntry; -use OCP\Files\Storage\IStorage; - -/** - * Metadata cache for shared files - * - * don't use this class directly if you need to get metadata, use \OC\Files\Filesystem::getFileInfo instead - */ -class Cache extends CacheJail { - /** - * @var \OC\Files\Storage\Shared - */ - private $storage; - - /** - * @var IStorage - */ - private $sourceStorage; - - /** - * @var ICacheEntry - */ - private $sourceRootInfo; - - /** - * @var \OCP\Files\Cache\ICache - */ - private $sourceCache; - - /** - * @param \OC\Files\Storage\Shared $storage - * @param IStorage $sourceStorage - * @param ICacheEntry $sourceRootInfo - */ - public function __construct($storage, IStorage $sourceStorage, ICacheEntry $sourceRootInfo) { - $this->storage = $storage; - $this->sourceStorage = $sourceStorage; - $this->sourceRootInfo = $sourceRootInfo; - $this->sourceCache = $sourceStorage->getCache(); - parent::__construct( - $this->sourceCache, - $this->sourceRootInfo->getPath() - ); - } - - public function getNumericStorageId() { - if (isset($this->numericId)) { - return $this->numericId; - } else { - return false; - } - } - - protected function formatCacheEntry($entry) { - $path = $entry['path']; - $entry = parent::formatCacheEntry($entry); - $sharePermissions = $this->storage->getPermissions($path); - if (isset($entry['permissions'])) { - $entry['permissions'] &= $sharePermissions; - } else { - $entry['permissions'] = $sharePermissions; - } - $entry['uid_owner'] = $this->storage->getOwner($path); - $entry['displayname_owner'] = \OC_User::getDisplayName($entry['uid_owner']); - if ($path === '') { - $entry['is_share_mount_point'] = true; - } - return $entry; - } - - /** - * remove all entries for files that are stored on the storage from the cache - */ - public function clear() { - // Not a valid action for Shared Cache - } -} diff --git a/apps/files_sharing/lib/capabilities.php b/apps/files_sharing/lib/capabilities.php deleted file mode 100644 index 5ec540ad4e0..00000000000 --- a/apps/files_sharing/lib/capabilities.php +++ /dev/null @@ -1,91 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -namespace OCA\Files_Sharing; - -use OCP\Capabilities\ICapability; -use \OCP\IConfig; - -/** - * Class Capabilities - * - * @package OCA\Files_Sharing - */ -class Capabilities implements ICapability { - - /** @var IConfig */ - private $config; - - public function __construct(IConfig $config) { - $this->config = $config; - } - - /** - * Return this classes capabilities - * - * @return array - */ - public function getCapabilities() { - $res = []; - - if ($this->config->getAppValue('core', 'shareapi_enabled', 'yes') !== 'yes') { - $res['api_enabled'] = false; - $res['public'] = ['enabled' => false]; - $res['user'] = ['send_mail' => false]; - $res['resharing'] = false; - } else { - $res['api_enabled'] = true; - - $public = []; - $public['enabled'] = $this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'yes'; - if ($public['enabled']) { - $public['password'] = []; - $public['password']['enforced'] = ($this->config->getAppValue('core', 'shareapi_enforce_links_password', 'no') === 'yes'); - - $public['expire_date'] = []; - $public['expire_date']['enabled'] = $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no') === 'yes'; - if ($public['expire_date']['enabled']) { - $public['expire_date']['days'] = $this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7'); - $public['expire_date']['enforced'] = $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes'; - } - - $public['send_mail'] = $this->config->getAppValue('core', 'shareapi_allow_public_notification', 'no') === 'yes'; - $public['upload'] = $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes') === 'yes'; - } - $res["public"] = $public; - - $res['user']['send_mail'] = $this->config->getAppValue('core', 'shareapi_allow_mail_notification', 'no') === 'yes'; - - $res['resharing'] = $this->config->getAppValue('core', 'shareapi_allow_resharing', 'yes') === 'yes'; - - $res['group_sharing'] = $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'yes'; - } - - //Federated sharing - $res['federation'] = [ - 'outgoing' => $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes', - 'incoming' => $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes') === 'yes' - ]; - - return [ - 'files_sharing' => $res, - ]; - } -} diff --git a/apps/files_sharing/lib/controllers/externalsharescontroller.php b/apps/files_sharing/lib/controllers/externalsharescontroller.php deleted file mode 100644 index beefb4d7027..00000000000 --- a/apps/files_sharing/lib/controllers/externalsharescontroller.php +++ /dev/null @@ -1,149 +0,0 @@ - - * @author Lukas Reschke - * @author Morris Jobke - * @author Robin Appelman - * @author Roeland Jago Douma - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\Controllers; - -use OCP\AppFramework\Controller; -use OCP\IRequest; -use OCP\AppFramework\Http\JSONResponse; -use OCP\Http\Client\IClientService; -use OCP\AppFramework\Http\DataResponse; - -/** - * Class ExternalSharesController - * - * @package OCA\Files_Sharing\Controllers - */ -class ExternalSharesController extends Controller { - - /** @var \OCA\Files_Sharing\External\Manager */ - private $externalManager; - /** @var IClientService */ - private $clientService; - - /** - * @param string $appName - * @param IRequest $request - * @param \OCA\Files_Sharing\External\Manager $externalManager - * @param IClientService $clientService - */ - public function __construct($appName, - IRequest $request, - \OCA\Files_Sharing\External\Manager $externalManager, - IClientService $clientService) { - parent::__construct($appName, $request); - $this->externalManager = $externalManager; - $this->clientService = $clientService; - } - - /** - * @NoAdminRequired - * @NoOutgoingFederatedSharingRequired - * - * @return JSONResponse - */ - public function index() { - return new JSONResponse($this->externalManager->getOpenShares()); - } - - /** - * @NoAdminRequired - * @NoOutgoingFederatedSharingRequired - * - * @param int $id - * @return JSONResponse - */ - public function create($id) { - $this->externalManager->acceptShare($id); - return new JSONResponse(); - } - - /** - * @NoAdminRequired - * @NoOutgoingFederatedSharingRequired - * - * @param integer $id - * @return JSONResponse - */ - public function destroy($id) { - $this->externalManager->declineShare($id); - return new JSONResponse(); - } - - /** - * Test whether the specified remote is accessible - * - * @param string $remote - * @param bool $checkVersion - * @return bool - */ - protected function testUrl($remote, $checkVersion = false) { - try { - $client = $this->clientService->newClient(); - $response = json_decode($client->get( - $remote, - [ - 'timeout' => 3, - 'connect_timeout' => 3, - ] - )->getBody()); - - if ($checkVersion) { - return !empty($response->version) && version_compare($response->version, '7.0.0', '>='); - } else { - return is_object($response); - } - } catch (\Exception $e) { - return false; - } - } - - /** - * @PublicPage - * @NoOutgoingFederatedSharingRequired - * @NoIncomingFederatedSharingRequired - * - * @param string $remote - * @return DataResponse - */ - public function testRemote($remote) { - if ( - $this->testUrl('https://' . $remote . '/ocs-provider/') || - $this->testUrl('https://' . $remote . '/ocs-provider/index.php') || - $this->testUrl('https://' . $remote . '/status.php', true) - ) { - return new DataResponse('https'); - } elseif ( - $this->testUrl('http://' . $remote . '/ocs-provider/') || - $this->testUrl('http://' . $remote . '/ocs-provider/index.php') || - $this->testUrl('http://' . $remote . '/status.php', true) - ) { - return new DataResponse('http'); - } else { - return new DataResponse(false); - } - } - -} diff --git a/apps/files_sharing/lib/controllers/sharecontroller.php b/apps/files_sharing/lib/controllers/sharecontroller.php deleted file mode 100644 index 04912d20afc..00000000000 --- a/apps/files_sharing/lib/controllers/sharecontroller.php +++ /dev/null @@ -1,511 +0,0 @@ - - * @author Björn Schießle - * @author Georg Ehrke - * @author Joas Schilling - * @author Lukas Reschke - * @author Morris Jobke - * @author Robin Appelman - * @author Robin McCorkell - * @author Roeland Jago Douma - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\Controllers; - -use OC; -use OC_Files; -use OC_Util; -use OCA\FederatedFileSharing\FederatedShareProvider; -use OCP; -use OCP\Template; -use OCP\Share; -use OCP\AppFramework\Controller; -use OCP\IRequest; -use OCP\AppFramework\Http\TemplateResponse; -use OCP\AppFramework\Http\RedirectResponse; -use OCP\AppFramework\Http\NotFoundResponse; -use OCP\IURLGenerator; -use OCP\IConfig; -use OCP\ILogger; -use OCP\IUserManager; -use OCP\ISession; -use OCP\IPreview; -use OCA\Files_Sharing\Helper; -use OCP\Util; -use OCA\Files_Sharing\Activity; -use \OCP\Files\NotFoundException; -use OCP\Files\IRootFolder; -use OCP\Share\Exceptions\ShareNotFound; - -/** - * Class ShareController - * - * @package OCA\Files_Sharing\Controllers - */ -class ShareController extends Controller { - - /** @var IConfig */ - protected $config; - /** @var IURLGenerator */ - protected $urlGenerator; - /** @var IUserManager */ - protected $userManager; - /** @var ILogger */ - protected $logger; - /** @var OCP\Activity\IManager */ - protected $activityManager; - /** @var OCP\Share\IManager */ - protected $shareManager; - /** @var ISession */ - protected $session; - /** @var IPreview */ - protected $previewManager; - /** @var IRootFolder */ - protected $rootFolder; - /** @var FederatedShareProvider */ - protected $federatedShareProvider; - - /** - * @param string $appName - * @param IRequest $request - * @param IConfig $config - * @param IURLGenerator $urlGenerator - * @param IUserManager $userManager - * @param ILogger $logger - * @param OCP\Activity\IManager $activityManager - * @param \OCP\Share\IManager $shareManager - * @param ISession $session - * @param IPreview $previewManager - * @param IRootFolder $rootFolder - * @param FederatedShareProvider $federatedShareProvider - */ - public function __construct($appName, - IRequest $request, - IConfig $config, - IURLGenerator $urlGenerator, - IUserManager $userManager, - ILogger $logger, - \OCP\Activity\IManager $activityManager, - \OCP\Share\IManager $shareManager, - ISession $session, - IPreview $previewManager, - IRootFolder $rootFolder, - FederatedShareProvider $federatedShareProvider) { - parent::__construct($appName, $request); - - $this->config = $config; - $this->urlGenerator = $urlGenerator; - $this->userManager = $userManager; - $this->logger = $logger; - $this->activityManager = $activityManager; - $this->shareManager = $shareManager; - $this->session = $session; - $this->previewManager = $previewManager; - $this->rootFolder = $rootFolder; - $this->federatedShareProvider = $federatedShareProvider; - } - - /** - * @PublicPage - * @NoCSRFRequired - * - * @param string $token - * @return TemplateResponse|RedirectResponse - */ - public function showAuthenticate($token) { - $share = $this->shareManager->getShareByToken($token); - - if($this->linkShareAuth($share)) { - return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token))); - } - - return new TemplateResponse($this->appName, 'authenticate', array(), 'guest'); - } - - /** - * @PublicPage - * @UseSession - * - * Authenticates against password-protected shares - * @param string $token - * @param string $password - * @return RedirectResponse|TemplateResponse - */ - public function authenticate($token, $password = '') { - - // Check whether share exists - try { - $share = $this->shareManager->getShareByToken($token); - } catch (ShareNotFound $e) { - return new NotFoundResponse(); - } - - $authenticate = $this->linkShareAuth($share, $password); - - if($authenticate === true) { - return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token))); - } - - return new TemplateResponse($this->appName, 'authenticate', array('wrongpw' => true), 'guest'); - } - - /** - * Authenticate a link item with the given password. - * Or use the session if no password is provided. - * - * This is a modified version of Helper::authenticate - * TODO: Try to merge back eventually with Helper::authenticate - * - * @param \OCP\Share\IShare $share - * @param string|null $password - * @return bool - */ - private function linkShareAuth(\OCP\Share\IShare $share, $password = null) { - if ($password !== null) { - if ($this->shareManager->checkPassword($share, $password)) { - $this->session->set('public_link_authenticated', (string)$share->getId()); - } else { - $this->emitAccessShareHook($share, 403, 'Wrong password'); - return false; - } - } else { - // not authenticated ? - if ( ! $this->session->exists('public_link_authenticated') - || $this->session->get('public_link_authenticated') !== (string)$share->getId()) { - return false; - } - } - return true; - } - - /** - * throws hooks when a share is attempted to be accessed - * - * @param \OCP\Share\IShare|string $share the Share instance if available, - * otherwise token - * @param int $errorCode - * @param string $errorMessage - * @throws OC\HintException - * @throws OC\ServerNotAvailableException - */ - protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') { - $itemType = $itemSource = $uidOwner = ''; - $token = $share; - $exception = null; - if($share instanceof \OCP\Share\IShare) { - try { - $token = $share->getToken(); - $uidOwner = $share->getSharedBy(); - $itemType = $share->getNodeType(); - $itemSource = $share->getNodeId(); - } catch (\Exception $e) { - // we log what we know and pass on the exception afterwards - $exception = $e; - } - } - \OC_Hook::emit('OCP\Share', 'share_link_access', [ - 'itemType' => $itemType, - 'itemSource' => $itemSource, - 'uidOwner' => $uidOwner, - 'token' => $token, - 'errorCode' => $errorCode, - 'errorMessage' => $errorMessage, - ]); - if(!is_null($exception)) { - throw $exception; - } - } - - /** - * Validate the permissions of the share - * - * @param Share\IShare $share - * @return bool - */ - private function validateShare(\OCP\Share\IShare $share) { - return $share->getNode()->isReadable() && $share->getNode()->isShareable(); - } - - /** - * @PublicPage - * @NoCSRFRequired - * - * @param string $token - * @param string $path - * @return TemplateResponse|RedirectResponse - * @throws NotFoundException - */ - public function showShare($token, $path = '') { - \OC_User::setIncognitoMode(true); - - // Check whether share exists - try { - $share = $this->shareManager->getShareByToken($token); - } catch (ShareNotFound $e) { - $this->emitAccessShareHook($token, 404, 'Share not found'); - return new NotFoundResponse(); - } - - // Share is password protected - check whether the user is permitted to access the share - if ($share->getPassword() !== null && !$this->linkShareAuth($share)) { - return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate', - array('token' => $token))); - } - - if (!$this->validateShare($share)) { - throw new NotFoundException(); - } - // We can't get the path of a file share - try { - if ($share->getNode() instanceof \OCP\Files\File && $path !== '') { - $this->emitAccessShareHook($share, 404, 'Share not found'); - throw new NotFoundException(); - } - } catch (\Exception $e) { - $this->emitAccessShareHook($share, 404, 'Share not found'); - throw $e; - } - - $rootFolder = null; - if ($share->getNode() instanceof \OCP\Files\Folder) { - /** @var \OCP\Files\Folder $rootFolder */ - $rootFolder = $share->getNode(); - - try { - $path = $rootFolder->get($path); - } catch (\OCP\Files\NotFoundException $e) { - $this->emitAccessShareHook($share, 404, 'Share not found'); - throw new NotFoundException(); - } - } - - $shareTmpl = []; - $shareTmpl['displayName'] = $this->userManager->get($share->getShareOwner())->getDisplayName(); - $shareTmpl['owner'] = $share->getShareOwner(); - $shareTmpl['filename'] = $share->getNode()->getName(); - $shareTmpl['directory_path'] = $share->getTarget(); - $shareTmpl['mimetype'] = $share->getNode()->getMimetype(); - $shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($share->getNode()->getMimetype()); - $shareTmpl['dirToken'] = $token; - $shareTmpl['sharingToken'] = $token; - $shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled(); - $shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false'; - $shareTmpl['dir'] = ''; - $shareTmpl['nonHumanFileSize'] = $share->getNode()->getSize(); - $shareTmpl['fileSize'] = \OCP\Util::humanFileSize($share->getNode()->getSize()); - - // Show file list - if ($share->getNode() instanceof \OCP\Files\Folder) { - $shareTmpl['dir'] = $rootFolder->getRelativePath($path->getPath()); - - /* - * The OC_Util methods require a view. This just uses the node API - */ - $freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath()); - if ($freeSpace !== \OCP\Files\FileInfo::SPACE_UNKNOWN) { - $freeSpace = max($freeSpace, 0); - } else { - $freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188 - } - - $uploadLimit = Util::uploadLimit(); - $maxUploadFilesize = min($freeSpace, $uploadLimit); - - $folder = new Template('files', 'list', ''); - $folder->assign('dir', $rootFolder->getRelativePath($path->getPath())); - $folder->assign('dirToken', $token); - $folder->assign('permissions', \OCP\Constants::PERMISSION_READ); - $folder->assign('isPublic', true); - $folder->assign('publicUploadEnabled', 'no'); - $folder->assign('uploadMaxFilesize', $maxUploadFilesize); - $folder->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize)); - $folder->assign('freeSpace', $freeSpace); - $folder->assign('uploadLimit', $uploadLimit); // PHP upload limit - $folder->assign('usedSpacePercent', 0); - $folder->assign('trash', false); - $shareTmpl['folder'] = $folder->fetchPage(); - } - - $shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', array('token' => $token)); - $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10); - $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true); - $shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024); - $shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024); - - $csp = new OCP\AppFramework\Http\ContentSecurityPolicy(); - $csp->addAllowedFrameDomain('\'self\''); - $response = new TemplateResponse($this->appName, 'public', $shareTmpl, 'base'); - $response->setContentSecurityPolicy($csp); - - $this->emitAccessShareHook($share); - - return $response; - } - - /** - * @PublicPage - * @NoCSRFRequired - * - * @param string $token - * @param string $files - * @param string $path - * @param string $downloadStartSecret - * @return void|RedirectResponse - */ - public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') { - \OC_User::setIncognitoMode(true); - - $share = $this->shareManager->getShareByToken($token); - - // Share is password protected - check whether the user is permitted to access the share - if ($share->getPassword() !== null && !$this->linkShareAuth($share)) { - return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate', - ['token' => $token])); - } - - $files_list = null; - if (!is_null($files)) { // download selected files - $files_list = json_decode($files); - // in case we get only a single file - if ($files_list === null) { - $files_list = [$files]; - } - } - - $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner()); - $originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath()); - - if (!$this->validateShare($share)) { - throw new NotFoundException(); - } - - // Single file share - if ($share->getNode() instanceof \OCP\Files\File) { - // Single file download - $event = $this->activityManager->generateEvent(); - $event->setApp('files_sharing') - ->setType(Activity::TYPE_PUBLIC_LINKS) - ->setSubject(Activity::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED, [$userFolder->getRelativePath($share->getNode()->getPath())]) - ->setAffectedUser($share->getShareOwner()) - ->setObject('files', $share->getNode()->getId(), $userFolder->getRelativePath($share->getNode()->getPath())); - $this->activityManager->publish($event); - } - // Directory share - else { - /** @var \OCP\Files\Folder $node */ - $node = $share->getNode(); - - // Try to get the path - if ($path !== '') { - try { - $node = $node->get($path); - } catch (NotFoundException $e) { - $this->emitAccessShareHook($share, 404, 'Share not found'); - return new NotFoundResponse(); - } - } - - $originalSharePath = $userFolder->getRelativePath($node->getPath()); - - if ($node instanceof \OCP\Files\File) { - // Single file download - $event = $this->activityManager->generateEvent(); - $event->setApp('files_sharing') - ->setType(Activity::TYPE_PUBLIC_LINKS) - ->setSubject(Activity::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED, [$userFolder->getRelativePath($node->getPath())]) - ->setAffectedUser($share->getShareOwner()) - ->setObject('files', $node->getId(), $userFolder->getRelativePath($node->getPath())); - $this->activityManager->publish($event); - } else if (!empty($files_list)) { - /** @var \OCP\Files\Folder $node */ - - // Subset of files is downloaded - foreach ($files_list as $file) { - $subNode = $node->get($file); - - $event = $this->activityManager->generateEvent(); - $event->setApp('files_sharing') - ->setType(Activity::TYPE_PUBLIC_LINKS) - ->setAffectedUser($share->getShareOwner()) - ->setObject('files', $subNode->getId(), $userFolder->getRelativePath($subNode->getPath())); - - if ($subNode instanceof \OCP\Files\File) { - $event->setSubject(Activity::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED, [$userFolder->getRelativePath($subNode->getPath())]); - } else { - $event->setSubject(Activity::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED, [$userFolder->getRelativePath($subNode->getPath())]); - } - - $this->activityManager->publish($event); - } - } else { - // The folder is downloaded - $event = $this->activityManager->generateEvent(); - $event->setApp('files_sharing') - ->setType(Activity::TYPE_PUBLIC_LINKS) - ->setSubject(Activity::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED, [$userFolder->getRelativePath($node->getPath())]) - ->setAffectedUser($share->getShareOwner()) - ->setObject('files', $node->getId(), $userFolder->getRelativePath($node->getPath())); - $this->activityManager->publish($event); - } - } - - /* FIXME: We should do this all nicely in OCP */ - OC_Util::tearDownFS(); - OC_Util::setupFS($share->getShareOwner()); - - /** - * this sets a cookie to be able to recognize the start of the download - * the content must not be longer than 32 characters and must only contain - * alphanumeric characters - */ - if (!empty($downloadStartSecret) - && !isset($downloadStartSecret[32]) - && preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) { - - // FIXME: set on the response once we use an actual app framework response - setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/'); - } - - $this->emitAccessShareHook($share); - - $server_params = array( 'head' => $this->request->getMethod() == 'HEAD' ); - - /** - * Http range requests support - */ - if (isset($_SERVER['HTTP_RANGE'])) { - $server_params['range'] = $this->request->getHeader('Range'); - } - - // download selected files - if (!is_null($files) && $files !== '') { - // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well - // after dispatching the request which results in a "Cannot modify header information" notice. - OC_Files::get($originalSharePath, $files_list, $server_params); - exit(); - } else { - // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well - // after dispatching the request which results in a "Cannot modify header information" notice. - OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params); - exit(); - } - } -} diff --git a/apps/files_sharing/lib/exceptions/brokenpath.php b/apps/files_sharing/lib/exceptions/brokenpath.php deleted file mode 100644 index 4639d47c4a6..00000000000 --- a/apps/files_sharing/lib/exceptions/brokenpath.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @author Morris Jobke - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\Exceptions; - -/** - * Expected path with a different root - * Possible Error Codes: - * 10 - Path not relative to data/ and point to the users file directory - - */ -class BrokenPath extends \Exception { -} diff --git a/apps/files_sharing/lib/exceptions/s2sexception.php b/apps/files_sharing/lib/exceptions/s2sexception.php deleted file mode 100644 index 1ed6a9e2179..00000000000 --- a/apps/files_sharing/lib/exceptions/s2sexception.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @author Morris Jobke - * @author Roeland Jago Douma - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\Exceptions; - -/** - * S2S sharing not allowed - */ -class S2SException extends \Exception { -} diff --git a/apps/files_sharing/lib/expiresharesjob.php b/apps/files_sharing/lib/expiresharesjob.php deleted file mode 100644 index 479f407e68f..00000000000 --- a/apps/files_sharing/lib/expiresharesjob.php +++ /dev/null @@ -1,76 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing; - -use OC\BackgroundJob\TimedJob; - -/** - * Delete all shares that are expired - */ -class ExpireSharesJob extends TimedJob { - - /** - * sets the correct interval for this timed job - */ - public function __construct() { - // Run once a day - $this->setInterval(24 * 60 * 60); - } - - /** - * Makes the background job do its work - * - * @param array $argument unused argument - */ - public function run($argument) { - $connection = \OC::$server->getDatabaseConnection(); - $logger = \OC::$server->getLogger(); - - //Current time - $now = new \DateTime(); - $now = $now->format('Y-m-d H:i:s'); - - /* - * Expire file link shares only (for now) - */ - $qb = $connection->getQueryBuilder(); - $qb->select('id', 'file_source', 'uid_owner', 'item_type') - ->from('share') - ->where( - $qb->expr()->andX( - $qb->expr()->eq('share_type', $qb->expr()->literal(\OCP\Share::SHARE_TYPE_LINK)), - $qb->expr()->lte('expiration', $qb->expr()->literal($now)), - $qb->expr()->orX( - $qb->expr()->eq('item_type', $qb->expr()->literal('file')), - $qb->expr()->eq('item_type', $qb->expr()->literal('folder')) - ) - ) - ); - - $shares = $qb->execute(); - while($share = $shares->fetch()) { - \OCP\Share::unshare($share['item_type'], $share['file_source'], \OCP\Share::SHARE_TYPE_LINK, null, $share['uid_owner']); - } - $shares->closeCursor(); - } - -} diff --git a/apps/files_sharing/lib/external/cache.php b/apps/files_sharing/lib/external/cache.php deleted file mode 100644 index da9bf83cdfa..00000000000 --- a/apps/files_sharing/lib/external/cache.php +++ /dev/null @@ -1,65 +0,0 @@ - - * @author Robin Appelman - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\External; - -class Cache extends \OC\Files\Cache\Cache { - private $remote; - private $remoteUser; - private $storage; - - /** - * @param \OCA\Files_Sharing\External\Storage $storage - * @param string $remote - * @param string $remoteUser - */ - public function __construct($storage, $remote, $remoteUser) { - $this->storage = $storage; - list(, $remote) = explode('://', $remote, 2); - $this->remote = $remote; - $this->remoteUser = $remoteUser; - parent::__construct($storage); - } - - public function get($file) { - $result = parent::get($file); - if (!$result) { - return false; - } - $result['displayname_owner'] = $this->remoteUser . '@' . $this->remote; - if (!$file || $file === '') { - $result['is_share_mount_point'] = true; - $mountPoint = rtrim($this->storage->getMountPoint()); - $result['name'] = basename($mountPoint); - } - return $result; - } - - public function getFolderContentsById($id) { - $results = parent::getFolderContentsById($id); - foreach ($results as &$file) { - $file['displayname_owner'] = $this->remoteUser . '@' . $this->remote; - } - return $results; - } -} diff --git a/apps/files_sharing/lib/external/manager.php b/apps/files_sharing/lib/external/manager.php deleted file mode 100644 index 5b7a13f1eb1..00000000000 --- a/apps/files_sharing/lib/external/manager.php +++ /dev/null @@ -1,453 +0,0 @@ - - * @author Joas Schilling - * @author Jörn Friedrich Dreyer - * @author Lukas Reschke - * @author Morris Jobke - * @author Robin Appelman - * @author Roeland Jago Douma - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\External; - -use OC\Files\Filesystem; -use OCA\FederatedFileSharing\DiscoveryManager; -use OCP\Files; -use OCP\Notification\IManager; - -class Manager { - const STORAGE = '\OCA\Files_Sharing\External\Storage'; - - /** - * @var string - */ - private $uid; - - /** - * @var \OCP\IDBConnection - */ - private $connection; - - /** - * @var \OC\Files\Mount\Manager - */ - private $mountManager; - - /** - * @var \OCP\Files\Storage\IStorageFactory - */ - private $storageLoader; - - /** - * @var \OC\HTTPHelper - */ - private $httpHelper; - - /** - * @var IManager - */ - private $notificationManager; - /** @var DiscoveryManager */ - private $discoveryManager; - - /** - * @param \OCP\IDBConnection $connection - * @param \OC\Files\Mount\Manager $mountManager - * @param \OCP\Files\Storage\IStorageFactory $storageLoader - * @param \OC\HTTPHelper $httpHelper - * @param IManager $notificationManager - * @param DiscoveryManager $discoveryManager - * @param string $uid - */ - public function __construct(\OCP\IDBConnection $connection, - \OC\Files\Mount\Manager $mountManager, - \OCP\Files\Storage\IStorageFactory $storageLoader, - \OC\HTTPHelper $httpHelper, - IManager $notificationManager, - DiscoveryManager $discoveryManager, - $uid) { - $this->connection = $connection; - $this->mountManager = $mountManager; - $this->storageLoader = $storageLoader; - $this->httpHelper = $httpHelper; - $this->uid = $uid; - $this->notificationManager = $notificationManager; - $this->discoveryManager = $discoveryManager; - } - - /** - * add new server-to-server share - * - * @param string $remote - * @param string $token - * @param string $password - * @param string $name - * @param string $owner - * @param boolean $accepted - * @param string $user - * @param int $remoteId - * @return Mount|null - */ - public function addShare($remote, $token, $password, $name, $owner, $accepted=false, $user = null, $remoteId = -1) { - - $user = $user ? $user : $this->uid; - $accepted = $accepted ? 1 : 0; - $name = Filesystem::normalizePath('/' . $name); - - if (!$accepted) { - // To avoid conflicts with the mount point generation later, - // we only use a temporary mount point name here. The real - // mount point name will be generated when accepting the share, - // using the original share item name. - $tmpMountPointName = '{{TemporaryMountPointName#' . $name . '}}'; - $mountPoint = $tmpMountPointName; - $hash = md5($tmpMountPointName); - $data = [ - 'remote' => $remote, - 'share_token' => $token, - 'password' => $password, - 'name' => $name, - 'owner' => $owner, - 'user' => $user, - 'mountpoint' => $mountPoint, - 'mountpoint_hash' => $hash, - 'accepted' => $accepted, - 'remote_id' => $remoteId, - ]; - - $i = 1; - while (!$this->connection->insertIfNotExist('*PREFIX*share_external', $data, ['user', 'mountpoint_hash'])) { - // The external share already exists for the user - $data['mountpoint'] = $tmpMountPointName . '-' . $i; - $data['mountpoint_hash'] = md5($data['mountpoint']); - $i++; - } - return null; - } - - $mountPoint = Files::buildNotExistingFileName('/', $name); - $mountPoint = Filesystem::normalizePath('/' . $mountPoint); - $hash = md5($mountPoint); - - $query = $this->connection->prepare(' - INSERT INTO `*PREFIX*share_external` - (`remote`, `share_token`, `password`, `name`, `owner`, `user`, `mountpoint`, `mountpoint_hash`, `accepted`, `remote_id`) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - '); - $query->execute(array($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId)); - - $options = array( - 'remote' => $remote, - 'token' => $token, - 'password' => $password, - 'mountpoint' => $mountPoint, - 'owner' => $owner - ); - return $this->mountShare($options); - } - - /** - * get share - * - * @param int $id share id - * @return mixed share of false - */ - public function getShare($id) { - $getShare = $this->connection->prepare(' - SELECT `id`, `remote`, `remote_id`, `share_token`, `name`, `owner`, `user`, `mountpoint`, `accepted` - FROM `*PREFIX*share_external` - WHERE `id` = ? AND `user` = ?'); - $result = $getShare->execute(array($id, $this->uid)); - - return $result ? $getShare->fetch() : false; - } - - /** - * accept server-to-server share - * - * @param int $id - * @return bool True if the share could be accepted, false otherwise - */ - public function acceptShare($id) { - - $share = $this->getShare($id); - - if ($share) { - $mountPoint = Files::buildNotExistingFileName('/', $share['name']); - $mountPoint = Filesystem::normalizePath('/' . $mountPoint); - $hash = md5($mountPoint); - - $acceptShare = $this->connection->prepare(' - UPDATE `*PREFIX*share_external` - SET `accepted` = ?, - `mountpoint` = ?, - `mountpoint_hash` = ? - WHERE `id` = ? AND `user` = ?'); - $acceptShare->execute(array(1, $mountPoint, $hash, $id, $this->uid)); - $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'accept'); - - \OC_Hook::emit('OCP\Share', 'federated_share_added', ['server' => $share['remote']]); - - $this->processNotification($id); - return true; - } - - return false; - } - - /** - * decline server-to-server share - * - * @param int $id - * @return bool True if the share could be declined, false otherwise - */ - public function declineShare($id) { - - $share = $this->getShare($id); - - if ($share) { - $removeShare = $this->connection->prepare(' - DELETE FROM `*PREFIX*share_external` WHERE `id` = ? AND `user` = ?'); - $removeShare->execute(array($id, $this->uid)); - $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline'); - - $this->processNotification($id); - return true; - } - - return false; - } - - /** - * @param int $remoteShare - */ - public function processNotification($remoteShare) { - $filter = $this->notificationManager->createNotification(); - $filter->setApp('files_sharing') - ->setUser($this->uid) - ->setObject('remote_share', (int) $remoteShare); - $this->notificationManager->markProcessed($filter); - } - - /** - * inform remote server whether server-to-server share was accepted/declined - * - * @param string $remote - * @param string $token - * @param int $remoteId Share id on the remote host - * @param string $feedback - * @return boolean - */ - private function sendFeedbackToRemote($remote, $token, $remoteId, $feedback) { - - $url = rtrim($remote, '/') . $this->discoveryManager->getShareEndpoint($remote) . '/' . $remoteId . '/' . $feedback . '?format=' . \OCP\Share::RESPONSE_FORMAT; - $fields = array('token' => $token); - - $result = $this->httpHelper->post($url, $fields); - $status = json_decode($result['result'], true); - - return ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200)); - } - - /** - * remove '/user/files' from the path and trailing slashes - * - * @param string $path - * @return string - */ - protected function stripPath($path) { - $prefix = '/' . $this->uid . '/files'; - return rtrim(substr($path, strlen($prefix)), '/'); - } - - public function getMount($data) { - $data['manager'] = $this; - $mountPoint = '/' . $this->uid . '/files' . $data['mountpoint']; - $data['mountpoint'] = $mountPoint; - $data['certificateManager'] = \OC::$server->getCertificateManager($this->uid); - return new Mount(self::STORAGE, $mountPoint, $data, $this, $this->storageLoader); - } - - /** - * @param array $data - * @return Mount - */ - protected function mountShare($data) { - $mount = $this->getMount($data); - $this->mountManager->addMount($mount); - return $mount; - } - - /** - * @return \OC\Files\Mount\Manager - */ - public function getMountManager() { - return $this->mountManager; - } - - /** - * @param string $source - * @param string $target - * @return bool - */ - public function setMountPoint($source, $target) { - $source = $this->stripPath($source); - $target = $this->stripPath($target); - $sourceHash = md5($source); - $targetHash = md5($target); - - $query = $this->connection->prepare(' - UPDATE `*PREFIX*share_external` - SET `mountpoint` = ?, `mountpoint_hash` = ? - WHERE `mountpoint_hash` = ? - AND `user` = ? - '); - $result = (bool)$query->execute(array($target, $targetHash, $sourceHash, $this->uid)); - - return $result; - } - - public function removeShare($mountPoint) { - - $mountPointObj = $this->mountManager->find($mountPoint); - $id = $mountPointObj->getStorage()->getCache()->getId(); - - $mountPoint = $this->stripPath($mountPoint); - $hash = md5($mountPoint); - - $getShare = $this->connection->prepare(' - SELECT `remote`, `share_token`, `remote_id` - FROM `*PREFIX*share_external` - WHERE `mountpoint_hash` = ? AND `user` = ?'); - $result = $getShare->execute(array($hash, $this->uid)); - - if ($result) { - $share = $getShare->fetch(); - $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline'); - } - $getShare->closeCursor(); - - $query = $this->connection->prepare(' - DELETE FROM `*PREFIX*share_external` - WHERE `mountpoint_hash` = ? - AND `user` = ? - '); - $result = (bool)$query->execute(array($hash, $this->uid)); - - if($result) { - $this->removeReShares($id); - } - - return $result; - } - - /** - * remove re-shares from share table and mapping in the federated_reshares table - * - * @param $mountPointId - */ - protected function removeReShares($mountPointId) { - $selectQuery = $this->connection->getQueryBuilder(); - $query = $this->connection->getQueryBuilder(); - $selectQuery->select('id')->from('share') - ->where($selectQuery->expr()->eq('file_source', $query->createNamedParameter($mountPointId))); - $select = $selectQuery->getSQL(); - - - $query->delete('federated_reshares') - ->where($query->expr()->in('share_id', $query->createFunction('(' . $select . ')'))); - $query->execute(); - - $deleteReShares = $this->connection->getQueryBuilder(); - $deleteReShares->delete('share') - ->where($deleteReShares->expr()->eq('file_source', $deleteReShares->createNamedParameter($mountPointId))); - $deleteReShares->execute(); - } - - /** - * remove all shares for user $uid if the user was deleted - * - * @param string $uid - * @return bool - */ - public function removeUserShares($uid) { - $getShare = $this->connection->prepare(' - SELECT `remote`, `share_token`, `remote_id` - FROM `*PREFIX*share_external` - WHERE `user` = ?'); - $result = $getShare->execute(array($uid)); - - if ($result) { - $shares = $getShare->fetchAll(); - foreach($shares as $share) { - $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline'); - } - } - - $query = $this->connection->prepare(' - DELETE FROM `*PREFIX*share_external` - WHERE `user` = ? - '); - return (bool)$query->execute(array($uid)); - } - - /** - * return a list of shares which are not yet accepted by the user - * - * @return array list of open server-to-server shares - */ - public function getOpenShares() { - return $this->getShares(false); - } - - /** - * return a list of shares which are accepted by the user - * - * @return array list of accepted server-to-server shares - */ - public function getAcceptedShares() { - return $this->getShares(true); - } - - /** - * return a list of shares for the user - * - * @param bool|null $accepted True for accepted only, - * false for not accepted, - * null for all shares of the user - * @return array list of open server-to-server shares - */ - private function getShares($accepted) { - $query = 'SELECT `id`, `remote`, `remote_id`, `share_token`, `name`, `owner`, `user`, `mountpoint`, `accepted` - FROM `*PREFIX*share_external` - WHERE `user` = ?'; - $parameters = [$this->uid]; - if (!is_null($accepted)) { - $query .= ' AND `accepted` = ?'; - $parameters[] = (int) $accepted; - } - $query .= ' ORDER BY `id` ASC'; - - $shares = $this->connection->prepare($query); - $result = $shares->execute($parameters); - - return $result ? $shares->fetchAll() : []; - } -} diff --git a/apps/files_sharing/lib/external/mount.php b/apps/files_sharing/lib/external/mount.php deleted file mode 100644 index 9cf66d3f8f0..00000000000 --- a/apps/files_sharing/lib/external/mount.php +++ /dev/null @@ -1,70 +0,0 @@ - - * @author Morris Jobke - * @author Robin Appelman - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\External; - -use OC\Files\Mount\MountPoint; -use OC\Files\Mount\MoveableMount; - -class Mount extends MountPoint implements MoveableMount { - - /** - * @var \OCA\Files_Sharing\External\Manager - */ - protected $manager; - - /** - * @param string|\OC\Files\Storage\Storage $storage - * @param string $mountpoint - * @param array $options - * @param \OCA\Files_Sharing\External\Manager $manager - * @param \OC\Files\Storage\StorageFactory $loader - */ - public function __construct($storage, $mountpoint, $options, $manager, $loader = null) { - parent::__construct($storage, $mountpoint, $options, $loader); - $this->manager = $manager; - } - - /** - * Move the mount point to $target - * - * @param string $target the target mount point - * @return bool - */ - public function moveMount($target) { - $result = $this->manager->setMountPoint($this->mountPoint, $target); - $this->setMountPoint($target); - - return $result; - } - - /** - * Remove the mount points - * - * @return mixed - * @return bool - */ - public function removeMount() { - return $this->manager->removeShare($this->mountPoint); - } -} diff --git a/apps/files_sharing/lib/external/mountprovider.php b/apps/files_sharing/lib/external/mountprovider.php deleted file mode 100644 index 67d85f27d81..00000000000 --- a/apps/files_sharing/lib/external/mountprovider.php +++ /dev/null @@ -1,76 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\External; - -use OCP\Files\Config\IMountProvider; -use OCP\Files\Storage\IStorageFactory; -use OCP\IDBConnection; -use OCP\IUser; - -class MountProvider implements IMountProvider { - const STORAGE = '\OCA\Files_Sharing\External\Storage'; - - /** - * @var \OCP\IDBConnection - */ - private $connection; - - /** - * @var callable - */ - private $managerProvider; - - /** - * @param \OCP\IDBConnection $connection - * @param callable $managerProvider due to setup order we need a callable that return the manager instead of the manager itself - */ - public function __construct(IDBConnection $connection, callable $managerProvider) { - $this->connection = $connection; - $this->managerProvider = $managerProvider; - } - - public function getMount(IUser $user, $data, IStorageFactory $storageFactory) { - $managerProvider = $this->managerProvider; - $manager = $managerProvider(); - $data['manager'] = $manager; - $mountPoint = '/' . $user->getUID() . '/files/' . ltrim($data['mountpoint'], '/'); - $data['mountpoint'] = $mountPoint; - $data['certificateManager'] = \OC::$server->getCertificateManager($user->getUID()); - return new Mount(self::STORAGE, $mountPoint, $data, $manager, $storageFactory); - } - - public function getMountsForUser(IUser $user, IStorageFactory $loader) { - $query = $this->connection->prepare(' - SELECT `remote`, `share_token`, `password`, `mountpoint`, `owner` - FROM `*PREFIX*share_external` - WHERE `user` = ? AND `accepted` = ? - '); - $query->execute([$user->getUID(), 1]); - $mounts = []; - while ($row = $query->fetch()) { - $row['manager'] = $this; - $row['token'] = $row['share_token']; - $mounts[] = $this->getMount($user, $row, $loader); - } - return $mounts; - } -} diff --git a/apps/files_sharing/lib/external/scanner.php b/apps/files_sharing/lib/external/scanner.php deleted file mode 100644 index 1cc6cf8f5f9..00000000000 --- a/apps/files_sharing/lib/external/scanner.php +++ /dev/null @@ -1,127 +0,0 @@ - - * @author Morris Jobke - * @author Olivier Paroz - * @author Robin Appelman - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\External; - -use OC\ForbiddenException; -use OCP\Files\NotFoundException; -use OCP\Files\StorageInvalidException; -use OCP\Files\StorageNotAvailableException; - -class Scanner extends \OC\Files\Cache\Scanner { - /** @var \OCA\Files_Sharing\External\Storage */ - protected $storage; - - /** {@inheritDoc} */ - public function scan($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $lock = true) { - if(!$this->storage->remoteIsOwnCloud()) { - return parent::scan($path, $recursive, $recursive, $lock); - } - - $this->scanAll(); - } - - /** - * Scan a single file and store it in the cache. - * If an exception happened while accessing the external storage, - * the storage will be checked for availability and removed - * if it is not available any more. - * - * @param string $file file to scan - * @param int $reuseExisting - * @param int $parentId - * @param array | null $cacheData existing data in the cache for the file to be scanned - * @param bool $lock set to false to disable getting an additional read lock during scanning - * @return array an array of metadata of the scanned file - */ - public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true) { - try { - return parent::scanFile($file, $reuseExisting); - } catch (ForbiddenException $e) { - $this->storage->checkStorageAvailability(); - } catch (NotFoundException $e) { - // if the storage isn't found, the call to - // checkStorageAvailable() will verify it and remove it - // if appropriate - $this->storage->checkStorageAvailability(); - } catch (StorageInvalidException $e) { - $this->storage->checkStorageAvailability(); - } catch (StorageNotAvailableException $e) { - $this->storage->checkStorageAvailability(); - } - } - - /** - * Checks the remote share for changes. - * If changes are available, scan them and update - * the cache. - * @throws NotFoundException - * @throws StorageInvalidException - * @throws \Exception - */ - public function scanAll() { - try { - $data = $this->storage->getShareInfo(); - } catch (\Exception $e) { - $this->storage->checkStorageAvailability(); - throw new \Exception( - 'Error while scanning remote share: "' . - $this->storage->getRemote() . '" ' . - $e->getMessage() - ); - } - if ($data['status'] === 'success') { - $this->addResult($data['data'], ''); - } else { - throw new \Exception( - 'Error while scanning remote share: "' . - $this->storage->getRemote() . '"' - ); - } - } - - /** - * @param array $data - * @param string $path - */ - private function addResult($data, $path) { - $id = $this->cache->put($path, $data); - if (isset($data['children'])) { - $children = []; - foreach ($data['children'] as $child) { - $children[$child['name']] = true; - $this->addResult($child, ltrim($path . '/' . $child['name'], '/')); - } - - $existingCache = $this->cache->getFolderContentsById($id); - foreach ($existingCache as $existingChild) { - // if an existing child is not in the new data, remove it - if (!isset($children[$existingChild['name']])) { - $this->cache->remove(ltrim($path . '/' . $existingChild['name'], '/')); - } - } - } - } -} diff --git a/apps/files_sharing/lib/external/storage.php b/apps/files_sharing/lib/external/storage.php deleted file mode 100644 index 4382dcab0c3..00000000000 --- a/apps/files_sharing/lib/external/storage.php +++ /dev/null @@ -1,339 +0,0 @@ - - * @author Morris Jobke - * @author Robin Appelman - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\External; - -use GuzzleHttp\Exception\ClientException; -use GuzzleHttp\Exception\ConnectException; -use OC\Files\Storage\DAV; -use OC\ForbiddenException; -use OCA\FederatedFileSharing\DiscoveryManager; -use OCA\Files_Sharing\ISharedStorage; -use OCP\Files\NotFoundException; -use OCP\Files\StorageInvalidException; -use OCP\Files\StorageNotAvailableException; - -class Storage extends DAV implements ISharedStorage { - /** @var string */ - private $remoteUser; - /** @var string */ - private $remote; - /** @var string */ - private $mountPoint; - /** @var string */ - private $token; - /** @var \OCP\ICacheFactory */ - private $memcacheFactory; - /** @var \OCP\Http\Client\IClientService */ - private $httpClient; - /** @var \OCP\ICertificateManager */ - private $certificateManager; - /** @var bool */ - private $updateChecked = false; - - /** - * @var \OCA\Files_Sharing\External\Manager - */ - private $manager; - - public function __construct($options) { - $this->memcacheFactory = \OC::$server->getMemCacheFactory(); - $this->httpClient = \OC::$server->getHTTPClientService(); - $discoveryManager = new DiscoveryManager( - $this->memcacheFactory, - \OC::$server->getHTTPClientService() - ); - - $this->manager = $options['manager']; - $this->certificateManager = $options['certificateManager']; - $this->remote = $options['remote']; - $this->remoteUser = $options['owner']; - list($protocol, $remote) = explode('://', $this->remote); - if (strpos($remote, '/')) { - list($host, $root) = explode('/', $remote, 2); - } else { - $host = $remote; - $root = ''; - } - $secure = $protocol === 'https'; - $root = rtrim($root, '/') . $discoveryManager->getWebDavEndpoint($this->remote); - $this->mountPoint = $options['mountpoint']; - $this->token = $options['token']; - parent::__construct(array( - 'secure' => $secure, - 'host' => $host, - 'root' => $root, - 'user' => $options['token'], - 'password' => (string)$options['password'] - )); - - $this->getWatcher()->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE); - } - - public function getRemoteUser() { - return $this->remoteUser; - } - - public function getRemote() { - return $this->remote; - } - - public function getMountPoint() { - return $this->mountPoint; - } - - public function getToken() { - return $this->token; - } - - public function getPassword() { - return $this->password; - } - - /** - * @brief get id of the mount point - * @return string - */ - public function getId() { - return 'shared::' . md5($this->token . '@' . $this->remote); - } - - public function getCache($path = '', $storage = null) { - if (is_null($this->cache)) { - $this->cache = new Cache($this, $this->remote, $this->remoteUser); - } - return $this->cache; - } - - /** - * @param string $path - * @param \OC\Files\Storage\Storage $storage - * @return \OCA\Files_Sharing\External\Scanner - */ - public function getScanner($path = '', $storage = null) { - if (!$storage) { - $storage = $this; - } - if (!isset($this->scanner)) { - $this->scanner = new Scanner($storage); - } - return $this->scanner; - } - - /** - * check if a file or folder has been updated since $time - * - * @param string $path - * @param int $time - * @throws \OCP\Files\StorageNotAvailableException - * @throws \OCP\Files\StorageInvalidException - * @return bool - */ - public function hasUpdated($path, $time) { - // since for owncloud webdav servers we can rely on etag propagation we only need to check the root of the storage - // because of that we only do one check for the entire storage per request - if ($this->updateChecked) { - return false; - } - $this->updateChecked = true; - try { - return parent::hasUpdated('', $time); - } catch (StorageInvalidException $e) { - // check if it needs to be removed - $this->checkStorageAvailability(); - throw $e; - } catch (StorageNotAvailableException $e) { - // check if it needs to be removed or just temp unavailable - $this->checkStorageAvailability(); - throw $e; - } - } - - /** - * Check whether this storage is permanently or temporarily - * unavailable - * - * @throws \OCP\Files\StorageNotAvailableException - * @throws \OCP\Files\StorageInvalidException - */ - public function checkStorageAvailability() { - // see if we can find out why the share is unavailable - try { - $this->getShareInfo(); - } catch (NotFoundException $e) { - // a 404 can either mean that the share no longer exists or there is no ownCloud on the remote - if ($this->testRemote()) { - // valid ownCloud instance means that the public share no longer exists - // since this is permanent (re-sharing the file will create a new token) - // we remove the invalid storage - $this->manager->removeShare($this->mountPoint); - $this->manager->getMountManager()->removeMount($this->mountPoint); - throw new StorageInvalidException(); - } else { - // ownCloud instance is gone, likely to be a temporary server configuration error - throw new StorageNotAvailableException(); - } - } catch (ForbiddenException $e) { - // auth error, remove share for now (provide a dialog in the future) - $this->manager->removeShare($this->mountPoint); - $this->manager->getMountManager()->removeMount($this->mountPoint); - throw new StorageInvalidException(); - } catch (\GuzzleHttp\Exception\ConnectException $e) { - throw new StorageNotAvailableException(); - } catch (\GuzzleHttp\Exception\RequestException $e) { - throw new StorageNotAvailableException(); - } catch (\Exception $e) { - throw $e; - } - } - - public function file_exists($path) { - if ($path === '') { - return true; - } else { - return parent::file_exists($path); - } - } - - /** - * check if the configured remote is a valid federated share provider - * - * @return bool - */ - protected function testRemote() { - try { - return $this->testRemoteUrl($this->remote . '/ocs-provider/index.php') - || $this->testRemoteUrl($this->remote . '/ocs-provider/') - || $this->testRemoteUrl($this->remote . '/status.php'); - } catch (\Exception $e) { - return false; - } - } - - /** - * @param string $url - * @return bool - */ - private function testRemoteUrl($url) { - $cache = $this->memcacheFactory->create('files_sharing_remote_url'); - if($cache->hasKey($url)) { - return (bool)$cache->get($url); - } - - $client = $this->httpClient->newClient(); - try { - $result = $client->get($url)->getBody(); - $data = json_decode($result); - $returnValue = (is_object($data) && !empty($data->version)); - } catch (ConnectException $e) { - $returnValue = false; - } catch (ClientException $e) { - $returnValue = false; - } - - $cache->set($url, $returnValue); - return $returnValue; - } - - /** - * Whether the remote is an ownCloud, used since some sharing features are not - * standardized. Let's use this to detect whether to use it. - * - * @return bool - */ - public function remoteIsOwnCloud() { - if(defined('PHPUNIT_RUN') || !$this->testRemoteUrl($this->getRemote() . '/status.php')) { - return false; - } - return true; - } - - /** - * @return mixed - * @throws ForbiddenException - * @throws NotFoundException - * @throws \Exception - */ - public function getShareInfo() { - $remote = $this->getRemote(); - $token = $this->getToken(); - $password = $this->getPassword(); - - // If remote is not an ownCloud do not try to get any share info - if(!$this->remoteIsOwnCloud()) { - return ['status' => 'unsupported']; - } - - $url = rtrim($remote, '/') . '/index.php/apps/files_sharing/shareinfo?t=' . $token; - - // TODO: DI - $client = \OC::$server->getHTTPClientService()->newClient(); - try { - $response = $client->post($url, ['body' => ['password' => $password]]); - } catch (\GuzzleHttp\Exception\RequestException $e) { - if ($e->getCode() === 401 || $e->getCode() === 403) { - throw new ForbiddenException(); - } - if ($e->getCode() === 404) { - throw new NotFoundException(); - } - // throw this to be on the safe side: the share will still be visible - // in the UI in case the failure is intermittent, and the user will - // be able to decide whether to remove it if it's really gone - throw new StorageNotAvailableException(); - } - - return json_decode($response->getBody(), true); - } - - public function getOwner($path) { - list(, $remote) = explode('://', $this->remote, 2); - return $this->remoteUser . '@' . $remote; - } - - public function isSharable($path) { - if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) { - return false; - } - return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_SHARE); - } - - public function getPermissions($path) { - $response = $this->propfind($path); - if (isset($response['{http://open-collaboration-services.org/ns}share-permissions'])) { - $permissions = $response['{http://open-collaboration-services.org/ns}share-permissions']; - } else { - // use default permission if remote server doesn't provide the share permissions - if ($this->is_dir($path)) { - $permissions = \OCP\Constants::PERMISSION_ALL; - } else { - $permissions = \OCP\Constants::PERMISSION_ALL & ~\OCP\Constants::PERMISSION_CREATE; - } - } - - return $permissions; - } - -} diff --git a/apps/files_sharing/lib/helper.php b/apps/files_sharing/lib/helper.php deleted file mode 100644 index 500d82cb2d2..00000000000 --- a/apps/files_sharing/lib/helper.php +++ /dev/null @@ -1,310 +0,0 @@ - - * @author Björn Schießle - * @author Joas Schilling - * @author Jörn Friedrich Dreyer - * @author Lukas Reschke - * @author Morris Jobke - * @author Robin Appelman - * @author Roeland Jago Douma - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -namespace OCA\Files_Sharing; - -use OC\Files\Filesystem; -use OC\Files\View; -use OCP\Files\NotFoundException; -use OCP\User; - -class Helper { - - public static function registerHooks() { - \OCP\Util::connectHook('OC_Filesystem', 'post_rename', '\OCA\Files_Sharing\Updater', 'renameHook'); - \OCP\Util::connectHook('OC_Filesystem', 'post_delete', '\OCA\Files_Sharing\Hooks', 'unshareChildren'); - \OCP\Util::connectHook('OC_Appconfig', 'post_set_value', '\OCA\Files_Sharing\Maintainer', 'configChangeHook'); - - \OCP\Util::connectHook('OC_User', 'post_deleteUser', '\OCA\Files_Sharing\Hooks', 'deleteUser'); - } - - /** - * Sets up the filesystem and user for public sharing - * @param string $token string share token - * @param string $relativePath optional path relative to the share - * @param string $password optional password - * @return array - */ - public static function setupFromToken($token, $relativePath = null, $password = null) { - \OC_User::setIncognitoMode(true); - - $linkItem = \OCP\Share::getShareByToken($token, !$password); - if($linkItem === false || ($linkItem['item_type'] !== 'file' && $linkItem['item_type'] !== 'folder')) { - \OC_Response::setStatus(404); - \OCP\Util::writeLog('core-preview', 'Passed token parameter is not valid', \OCP\Util::DEBUG); - exit; - } - - if(!isset($linkItem['uid_owner']) || !isset($linkItem['file_source'])) { - \OC_Response::setStatus(500); - \OCP\Util::writeLog('core-preview', 'Passed token seems to be valid, but it does not contain all necessary information . ("' . $token . '")', \OCP\Util::WARN); - exit; - } - - $rootLinkItem = \OCP\Share::resolveReShare($linkItem); - $path = null; - if (isset($rootLinkItem['uid_owner'])) { - \OCP\JSON::checkUserExists($rootLinkItem['uid_owner']); - \OC_Util::tearDownFS(); - \OC_Util::setupFS($rootLinkItem['uid_owner']); - } - - try { - $path = Filesystem::getPath($linkItem['file_source']); - } catch (NotFoundException $e) { - \OCP\Util::writeLog('share', 'could not resolve linkItem', \OCP\Util::DEBUG); - \OC_Response::setStatus(404); - \OCP\JSON::error(array('success' => false)); - exit(); - } - - if (!isset($linkItem['item_type'])) { - \OCP\Util::writeLog('share', 'No item type set for share id: ' . $linkItem['id'], \OCP\Util::ERROR); - \OC_Response::setStatus(404); - \OCP\JSON::error(array('success' => false)); - exit(); - } - - if (isset($linkItem['share_with']) && (int)$linkItem['share_type'] === \OCP\Share::SHARE_TYPE_LINK) { - if (!self::authenticate($linkItem, $password)) { - \OC_Response::setStatus(403); - \OCP\JSON::error(array('success' => false)); - exit(); - } - } - - $basePath = $path; - - if ($relativePath !== null && Filesystem::isReadable($basePath . $relativePath)) { - $path .= Filesystem::normalizePath($relativePath); - } - - return array( - 'linkItem' => $linkItem, - 'basePath' => $basePath, - 'realPath' => $path - ); - } - - /** - * Authenticate link item with the given password - * or with the session if no password was given. - * @param array $linkItem link item array - * @param string $password optional password - * - * @return boolean true if authorized, false otherwise - */ - public static function authenticate($linkItem, $password = null) { - if ($password !== null) { - if ($linkItem['share_type'] == \OCP\Share::SHARE_TYPE_LINK) { - // Check Password - $newHash = ''; - if(\OC::$server->getHasher()->verify($password, $linkItem['share_with'], $newHash)) { - // Save item id in session for future requests - \OC::$server->getSession()->set('public_link_authenticated', $linkItem['id']); - - /** - * FIXME: Migrate old hashes to new hash format - * Due to the fact that there is no reasonable functionality to update the password - * of an existing share no migration is yet performed there. - * The only possibility is to update the existing share which will result in a new - * share ID and is a major hack. - * - * In the future the migration should be performed once there is a proper method - * to update the share's password. (for example `$share->updatePassword($password)` - * - * @link https://github.com/owncloud/core/issues/10671 - */ - if(!empty($newHash)) { - - } - } else { - return false; - } - } else { - \OCP\Util::writeLog('share', 'Unknown share type '.$linkItem['share_type'] - .' for share id '.$linkItem['id'], \OCP\Util::ERROR); - return false; - } - - } - else { - // not authenticated ? - if ( ! \OC::$server->getSession()->exists('public_link_authenticated') - || \OC::$server->getSession()->get('public_link_authenticated') !== $linkItem['id']) { - return false; - } - } - return true; - } - - public static function getSharesFromItem($target) { - $result = array(); - $owner = Filesystem::getOwner($target); - Filesystem::initMountPoints($owner); - $info = Filesystem::getFileInfo($target); - $ownerView = new View('/'.$owner.'/files'); - if ( $owner != User::getUser() ) { - $path = $ownerView->getPath($info['fileid']); - } else { - $path = $target; - } - - - $ids = array(); - while ($path !== dirname($path)) { - $info = $ownerView->getFileInfo($path); - if ($info instanceof \OC\Files\FileInfo) { - $ids[] = $info['fileid']; - } else { - \OCP\Util::writeLog('sharing', 'No fileinfo available for: ' . $path, \OCP\Util::WARN); - } - $path = dirname($path); - } - - if (!empty($ids)) { - - $idList = array_chunk($ids, 99, true); - - foreach ($idList as $subList) { - $statement = "SELECT `share_with`, `share_type`, `file_target` FROM `*PREFIX*share` WHERE `file_source` IN (" . implode(',', $subList) . ") AND `share_type` IN (0, 1, 2)"; - $query = \OCP\DB::prepare($statement); - $r = $query->execute(); - $result = array_merge($result, $r->fetchAll()); - } - } - - return $result; - } - - /** - * get the UID of the owner of the file and the path to the file relative to - * owners files folder - * - * @param $filename - * @return array - * @throws \OC\User\NoUserException - */ - public static function getUidAndFilename($filename) { - $uid = Filesystem::getOwner($filename); - $userManager = \OC::$server->getUserManager(); - // if the user with the UID doesn't exists, e.g. because the UID points - // to a remote user with a federated cloud ID we use the current logged-in - // user. We need a valid local user to create the share - if (!$userManager->userExists($uid)) { - $uid = User::getUser(); - } - Filesystem::initMountPoints($uid); - if ( $uid != User::getUser() ) { - $info = Filesystem::getFileInfo($filename); - $ownerView = new View('/'.$uid.'/files'); - try { - $filename = $ownerView->getPath($info['fileid']); - } catch (NotFoundException $e) { - $filename = null; - } - } - return [$uid, $filename]; - } - - /** - * Format a path to be relative to the /user/files/ directory - * @param string $path the absolute path - * @return string e.g. turns '/admin/files/test.txt' into 'test.txt' - */ - public static function stripUserFilesPath($path) { - $trimmed = ltrim($path, '/'); - $split = explode('/', $trimmed); - - // it is not a file relative to data/user/files - if (count($split) < 3 || $split[1] !== 'files') { - return false; - } - - $sliced = array_slice($split, 2); - $relPath = implode('/', $sliced); - - return $relPath; - } - - /** - * check if file name already exists and generate unique target - * - * @param string $path - * @param array $excludeList - * @param View $view - * @return string $path - */ - public static function generateUniqueTarget($path, $excludeList, $view) { - $pathinfo = pathinfo($path); - $ext = (isset($pathinfo['extension'])) ? '.'.$pathinfo['extension'] : ''; - $name = $pathinfo['filename']; - $dir = $pathinfo['dirname']; - $i = 2; - while ($view->file_exists($path) || in_array($path, $excludeList)) { - $path = Filesystem::normalizePath($dir . '/' . $name . ' ('.$i.')' . $ext); - $i++; - } - - return $path; - } - - /** - * get default share folder - * - * @return string - */ - public static function getShareFolder() { - $shareFolder = \OC::$server->getConfig()->getSystemValue('share_folder', '/'); - $shareFolder = Filesystem::normalizePath($shareFolder); - - if (!Filesystem::file_exists($shareFolder)) { - $dir = ''; - $subdirs = explode('/', $shareFolder); - foreach ($subdirs as $subdir) { - $dir = $dir . '/' . $subdir; - if (!Filesystem::is_dir($dir)) { - Filesystem::mkdir($dir); - } - } - } - - return $shareFolder; - - } - - /** - * set default share folder - * - * @param string $shareFolder - */ - public static function setShareFolder($shareFolder) { - \OC::$server->getConfig()->setSystemValue('share_folder', $shareFolder); - } - -} diff --git a/apps/files_sharing/lib/hooks.php b/apps/files_sharing/lib/hooks.php deleted file mode 100644 index 4882ffcb001..00000000000 --- a/apps/files_sharing/lib/hooks.php +++ /dev/null @@ -1,64 +0,0 @@ - - * @author Joas Schilling - * @author Lukas Reschke - * @author Morris Jobke - * @author Robin Appelman - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing; - -use OC\Files\Filesystem; -use OCA\FederatedFileSharing\DiscoveryManager; - -class Hooks { - - public static function deleteUser($params) { - $discoveryManager = new DiscoveryManager( - \OC::$server->getMemCacheFactory(), - \OC::$server->getHTTPClientService() - ); - $manager = new External\Manager( - \OC::$server->getDatabaseConnection(), - \OC\Files\Filesystem::getMountManager(), - \OC\Files\Filesystem::getLoader(), - \OC::$server->getHTTPHelper(), - \OC::$server->getNotificationManager(), - $discoveryManager, - $params['uid']); - - $manager->removeUserShares($params['uid']); - } - - public static function unshareChildren($params) { - $path = Filesystem::getView()->getAbsolutePath($params['path']); - $view = new \OC\Files\View('/'); - - // find share mount points within $path and unmount them - $mountManager = \OC\Files\Filesystem::getMountManager(); - $mountedShares = $mountManager->findIn($path); - foreach ($mountedShares as $mount) { - if ($mount->getStorage()->instanceOfStorage('OCA\Files_Sharing\ISharedStorage')) { - $mountPoint = $mount->getMountPoint(); - $view->unlink($mountPoint); - } - } - } -} diff --git a/apps/files_sharing/lib/isharedstorage.php b/apps/files_sharing/lib/isharedstorage.php deleted file mode 100644 index bb47b011f48..00000000000 --- a/apps/files_sharing/lib/isharedstorage.php +++ /dev/null @@ -1,27 +0,0 @@ - - * @author Robin Appelman - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing; - -interface ISharedStorage{ - -} diff --git a/apps/files_sharing/lib/maintainer.php b/apps/files_sharing/lib/maintainer.php deleted file mode 100644 index 1d06a34bd0c..00000000000 --- a/apps/files_sharing/lib/maintainer.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @author Robin McCorkell - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing; - -/** - * Maintains stuff around the sharing functionality - * - * for example: on disable of "allow links" it removes all link shares - */ - -class Maintainer { - - /** - * Keeps track of the "allow links" config setting - * and removes all link shares if the config option is set to "no" - * - * @param array $params array with app, key, value as named values - */ - static public function configChangeHook($params) { - if($params['app'] === 'core' && $params['key'] === 'shareapi_allow_links' && $params['value'] === 'no') { - \OCP\Share::removeAllLinkShares(); - } - } - -} diff --git a/apps/files_sharing/lib/middleware/sharingcheckmiddleware.php b/apps/files_sharing/lib/middleware/sharingcheckmiddleware.php deleted file mode 100644 index a4a968b37fa..00000000000 --- a/apps/files_sharing/lib/middleware/sharingcheckmiddleware.php +++ /dev/null @@ -1,161 +0,0 @@ - - * @author Morris Jobke - * @author Roeland Jago Douma - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\Middleware; - -use OCP\App\IAppManager; -use OCP\AppFramework\Http\NotFoundResponse; -use OCP\AppFramework\Middleware; -use OCP\Files\NotFoundException; -use OCP\IConfig; -use OCP\AppFramework\Utility\IControllerMethodReflector; -use OCA\Files_Sharing\Exceptions\S2SException; -use OCP\AppFramework\Http\JSONResponse; - -/** - * Checks whether the "sharing check" is enabled - * - * @package OCA\Files_Sharing\Middleware - */ -class SharingCheckMiddleware extends Middleware { - - /** @var string */ - protected $appName; - /** @var IConfig */ - protected $config; - /** @var IAppManager */ - protected $appManager; - /** @var IControllerMethodReflector */ - protected $reflector; - - /*** - * @param string $appName - * @param IConfig $config - * @param IAppManager $appManager - */ - public function __construct($appName, - IConfig $config, - IAppManager $appManager, - IControllerMethodReflector $reflector - ) { - $this->appName = $appName; - $this->config = $config; - $this->appManager = $appManager; - $this->reflector = $reflector; - } - - /** - * Check if sharing is enabled before the controllers is executed - * - * @param \OCP\AppFramework\Controller $controller - * @param string $methodName - * @throws NotFoundException - */ - public function beforeController($controller, $methodName) { - if(!$this->isSharingEnabled()) { - throw new NotFoundException('Sharing is disabled.'); - } - - if ($controller instanceof \OCA\Files_Sharing\Controllers\ExternalSharesController && - !$this->externalSharesChecks()) { - throw new S2SException('Federated sharing not allowed'); - } else if ($controller instanceof \OCA\Files_Sharing\Controllers\ShareController && - !$this->isLinkSharingEnabled()) { - throw new NotFoundException('Link sharing is disabled'); - } - } - - /** - * Return 404 page in case of a not found exception - * - * @param \OCP\AppFramework\Controller $controller - * @param string $methodName - * @param \Exception $exception - * @return NotFoundResponse - * @throws \Exception - */ - public function afterException($controller, $methodName, \Exception $exception) { - if(is_a($exception, '\OCP\Files\NotFoundException')) { - return new NotFoundResponse(); - } - - if (is_a($exception, '\OCA\Files_Sharing\Exceptions\S2SException')) { - return new JSONResponse($exception->getMessage(), 405); - } - - throw $exception; - } - - /** - * Checks for externalshares controller - * @return bool - */ - private function externalSharesChecks() { - - if (!$this->reflector->hasAnnotation('NoIncomingFederatedSharingRequired') && - $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes') !== 'yes') { - return false; - } - - if (!$this->reflector->hasAnnotation('NoOutgoingFederatedSharingRequired') && - $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') !== 'yes') { - return false; - } - - return true; - } - - /** - * Check whether sharing is enabled - * @return bool - */ - private function isSharingEnabled() { - // FIXME: This check is done here since the route is globally defined and not inside the files_sharing app - // Check whether the sharing application is enabled - if(!$this->appManager->isEnabledForUser($this->appName)) { - return false; - } - - return true; - } - - /** - * Check if link sharing is allowed - * @return bool - */ - private function isLinkSharingEnabled() { - // Check if the shareAPI is enabled - if ($this->config->getAppValue('core', 'shareapi_enabled', 'yes') !== 'yes') { - return false; - } - - // Check whether public sharing is enabled - if($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') !== 'yes') { - return false; - } - - return true; - } - -} diff --git a/apps/files_sharing/lib/migration.php b/apps/files_sharing/lib/migration.php deleted file mode 100644 index 766a7ebd52a..00000000000 --- a/apps/files_sharing/lib/migration.php +++ /dev/null @@ -1,274 +0,0 @@ - - * @author Morris Jobke - * @author Roeland Jago Douma - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing; - -use Doctrine\DBAL\Connection; -use OCP\IDBConnection; -use OC\Cache\CappedMemoryCache; - -/** - * Class Migration - * - * @package OCA\Files_Sharing - * @group DB - */ -class Migration { - - /** @var IDBConnection */ - private $connection; - - /** @var array with all shares we already saw */ - private $shareCache; - - /** @var string */ - private $table = 'share'; - - public function __construct(IDBConnection $connection) { - $this->connection = $connection; - - // We cache up to 10k share items (~20MB) - $this->shareCache = new CappedMemoryCache(10000); - } - - /** - * move all re-shares to the owner in order to have a flat list of shares - * upgrade from oC 8.2 to 9.0 with the new sharing - */ - public function removeReShares() { - - $stmt = $this->getReShares(); - - $owners = []; - while($share = $stmt->fetch()) { - - $this->shareCache[$share['id']] = $share; - - $owners[$share['id']] = [ - 'owner' => $this->findOwner($share), - 'initiator' => $share['uid_owner'], - 'type' => $share['share_type'], - ]; - - if (count($owners) === 1000) { - $this->updateOwners($owners); - $owners = []; - } - } - - $stmt->closeCursor(); - - if (count($owners)) { - $this->updateOwners($owners); - } - } - - /** - * update all owner information so that all shares have an owner - * and an initiator for the upgrade from oC 8.2 to 9.0 with the new sharing - */ - public function updateInitiatorInfo() { - while (true) { - $shares = $this->getMissingInitiator(1000); - - if (empty($shares)) { - break; - } - - $owners = []; - foreach ($shares as $share) { - $owners[$share['id']] = [ - 'owner' => $share['uid_owner'], - 'initiator' => $share['uid_owner'], - 'type' => $share['share_type'], - ]; - } - $this->updateOwners($owners); - } - } - - /** - * find the owner of a re-shared file/folder - * - * @param array $share - * @return array - */ - private function findOwner($share) { - $currentShare = $share; - while(!is_null($currentShare['parent'])) { - if (isset($this->shareCache[$currentShare['parent']])) { - $currentShare = $this->shareCache[$currentShare['parent']]; - } else { - $currentShare = $this->getShare((int)$currentShare['parent']); - $this->shareCache[$currentShare['id']] = $currentShare; - } - } - - return $currentShare['uid_owner']; - } - - /** - * Get $n re-shares from the database - * - * @param int $n The max number of shares to fetch - * @return \Doctrine\DBAL\Driver\Statement - */ - private function getReShares() { - $query = $this->connection->getQueryBuilder(); - $query->select(['id', 'parent', 'uid_owner', 'share_type']) - ->from($this->table) - ->where($query->expr()->in( - 'share_type', - $query->createNamedParameter( - [ - \OCP\Share::SHARE_TYPE_USER, - \OCP\Share::SHARE_TYPE_GROUP, - \OCP\Share::SHARE_TYPE_LINK, - \OCP\Share::SHARE_TYPE_REMOTE, - ], - Connection::PARAM_INT_ARRAY - ) - )) - ->andWhere($query->expr()->in( - 'item_type', - $query->createNamedParameter( - ['file', 'folder'], - Connection::PARAM_STR_ARRAY - ) - )) - ->andWhere($query->expr()->isNotNull('parent')) - ->orderBy('id', 'asc'); - return $query->execute(); - - - $shares = $result->fetchAll(); - $result->closeCursor(); - - $ordered = []; - foreach ($shares as $share) { - $ordered[(int)$share['id']] = $share; - } - - return $ordered; - } - - /** - * Get $n re-shares from the database - * - * @param int $n The max number of shares to fetch - * @return array - */ - private function getMissingInitiator($n = 1000) { - $query = $this->connection->getQueryBuilder(); - $query->select(['id', 'uid_owner', 'share_type']) - ->from($this->table) - ->where($query->expr()->in( - 'share_type', - $query->createNamedParameter( - [ - \OCP\Share::SHARE_TYPE_USER, - \OCP\Share::SHARE_TYPE_GROUP, - \OCP\Share::SHARE_TYPE_LINK, - \OCP\Share::SHARE_TYPE_REMOTE, - ], - Connection::PARAM_INT_ARRAY - ) - )) - ->andWhere($query->expr()->in( - 'item_type', - $query->createNamedParameter( - ['file', 'folder'], - Connection::PARAM_STR_ARRAY - ) - )) - ->andWhere($query->expr()->isNull('uid_initiator')) - ->orderBy('id', 'asc') - ->setMaxResults($n); - $result = $query->execute(); - $shares = $result->fetchAll(); - $result->closeCursor(); - - $ordered = []; - foreach ($shares as $share) { - $ordered[(int)$share['id']] = $share; - } - - return $ordered; - } - - /** - * get a specific share - * - * @param int $id - * @return array - */ - private function getShare($id) { - $query = $this->connection->getQueryBuilder(); - $query->select(['id', 'parent', 'uid_owner']) - ->from($this->table) - ->where($query->expr()->eq('id', $query->createNamedParameter($id))); - $result = $query->execute(); - $share = $result->fetchAll(); - $result->closeCursor(); - - return $share[0]; - } - - /** - * update database with the new owners - * - * @param array $owners - * @throws \Exception - */ - private function updateOwners($owners) { - - $this->connection->beginTransaction(); - - try { - - foreach ($owners as $id => $owner) { - $query = $this->connection->getQueryBuilder(); - $query->update($this->table) - ->set('uid_owner', $query->createNamedParameter($owner['owner'])) - ->set('uid_initiator', $query->createNamedParameter($owner['initiator'])); - - - if ((int)$owner['type'] !== \OCP\Share::SHARE_TYPE_LINK) { - $query->set('parent', $query->createNamedParameter(null)); - } - - $query->where($query->expr()->eq('id', $query->createNamedParameter($id))); - - $query->execute(); - } - - $this->connection->commit(); - - } catch (\Exception $e) { - $this->connection->rollBack(); - throw $e; - } - - } - -} diff --git a/apps/files_sharing/lib/mountprovider.php b/apps/files_sharing/lib/mountprovider.php deleted file mode 100644 index 8e133951293..00000000000 --- a/apps/files_sharing/lib/mountprovider.php +++ /dev/null @@ -1,83 +0,0 @@ - - * @author Robin Appelman - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing; - -use OCP\Files\Config\IMountProvider; -use OCP\Files\Storage\IStorageFactory; -use OCP\IConfig; -use OCP\IUser; -use OCP\Share\IManager; - -class MountProvider implements IMountProvider { - /** - * @var \OCP\IConfig - */ - protected $config; - - /** - * @var IManager - */ - protected $shareManager; - - /** - * @param \OCP\IConfig $config - * @param IManager $shareManager - */ - public function __construct(IConfig $config, IManager $shareManager) { - $this->config = $config; - $this->shareManager = $shareManager; - } - - - /** - * Get all mountpoints applicable for the user and check for shares where we need to update the etags - * - * @param \OCP\IUser $user - * @param \OCP\Files\Storage\IStorageFactory $storageFactory - * @return \OCP\Files\Mount\IMountPoint[] - */ - public function getMountsForUser(IUser $user, IStorageFactory $storageFactory) { - $shares = $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_USER, null, -1); - $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_GROUP, null, -1)); - $shares = array_filter($shares, function (\OCP\Share\IShare $share) { - return $share->getPermissions() > 0; - }); - - $mounts = []; - foreach ($shares as $share) { - - $mounts[] = new SharedMount( - '\OC\Files\Storage\Shared', - $mounts, - [ - 'user' => $user->getUID(), - 'newShare' => $share, - ], - $storageFactory - ); - } - - // array_filter removes the null values from the array - return array_filter($mounts); - } -} diff --git a/apps/files_sharing/lib/scanner.php b/apps/files_sharing/lib/scanner.php deleted file mode 100644 index 215c0a7b6ae..00000000000 --- a/apps/files_sharing/lib/scanner.php +++ /dev/null @@ -1,75 +0,0 @@ - - * @author Robin Appelman - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing; - -use OC\Files\ObjectStore\NoopScanner; - -/** - * Scanner for SharedStorage - */ -class Scanner extends \OC\Files\Cache\Scanner { - private $sourceScanner; - - /** - * Returns metadata from the shared storage, but - * with permissions from the source storage. - * - * @param string $path path of the file for which to retrieve metadata - * - * @return array an array of metadata of the file - */ - public function getData($path) { - $data = parent::getData($path); - if ($data === null) { - return null; - } - list($sourceStorage, $internalPath) = $this->storage->resolvePath($path); - $data['permissions'] = $sourceStorage->getPermissions($internalPath); - return $data; - } - - private function getSourceScanner() { - if ($this->sourceScanner) { - return $this->sourceScanner; - } - if ($this->storage->instanceOfStorage('\OC\Files\Storage\Shared')) { - /** @var \OC\Files\Storage\Storage $storage */ - list($storage) = $this->storage->resolvePath(''); - $this->sourceScanner = $storage->getScanner(); - return $this->sourceScanner; - } else { - return null; - } - } - - public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true) { - $sourceScanner = $this->getSourceScanner(); - if ($sourceScanner instanceof NoopScanner) { - return []; - } else { - return parent::scanFile($file, $reuseExisting, $parentId, $cacheData, $lock); - } - } -} - diff --git a/apps/files_sharing/lib/sharedmount.php b/apps/files_sharing/lib/sharedmount.php deleted file mode 100644 index 4aed80b12b2..00000000000 --- a/apps/files_sharing/lib/sharedmount.php +++ /dev/null @@ -1,226 +0,0 @@ - - * @author Joas Schilling - * @author Morris Jobke - * @author Robin Appelman - * @author Roeland Jago Douma - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing; - -use OC\Files\Filesystem; -use OC\Files\Mount\MountPoint; -use OC\Files\Mount\MoveableMount; -use OC\Files\View; - -/** - * Shared mount points can be moved by the user - */ -class SharedMount extends MountPoint implements MoveableMount { - /** - * @var \OC\Files\Storage\Shared $storage - */ - protected $storage = null; - - /** - * @var \OC\Files\View - */ - private $recipientView; - - /** - * @var string - */ - private $user; - - /** @var \OCP\Share\IShare */ - private $share; - - /** - * @param string $storage - * @param SharedMount[] $mountpoints - * @param array|null $arguments - * @param \OCP\Files\Storage\IStorageFactory $loader - */ - public function __construct($storage, array $mountpoints, $arguments = null, $loader = null) { - $this->user = $arguments['user']; - $this->recipientView = new View('/' . $this->user . '/files'); - $this->share = $arguments['newShare']; - $newMountPoint = $this->verifyMountPoint($this->share, $mountpoints); - $absMountPoint = '/' . $this->user . '/files' . $newMountPoint; - $arguments['ownerView'] = new View('/' . $this->share->getShareOwner() . '/files'); - parent::__construct($storage, $absMountPoint, $arguments, $loader); - } - - /** - * check if the parent folder exists otherwise move the mount point up - * - * @param \OCP\Share\IShare $share - * @param SharedMount[] $mountpoints - * @return string - */ - private function verifyMountPoint(\OCP\Share\IShare $share, array $mountpoints) { - - $mountPoint = basename($share->getTarget()); - $parent = dirname($share->getTarget()); - - if (!$this->recipientView->is_dir($parent)) { - $parent = Helper::getShareFolder(); - } - - $newMountPoint = $this->generateUniqueTarget( - \OC\Files\Filesystem::normalizePath($parent . '/' . $mountPoint), - $this->recipientView, - $mountpoints - ); - - if ($newMountPoint !== $share->getTarget()) { - $this->updateFileTarget($newMountPoint, $share); - } - - return $newMountPoint; - } - - /** - * update fileTarget in the database if the mount point changed - * - * @param string $newPath - * @param \OCP\Share\IShare $share - * @return bool - */ - private function updateFileTarget($newPath, &$share) { - $share->setTarget($newPath); - \OC::$server->getShareManager()->moveShare($share, $this->user); - } - - - /** - * @param string $path - * @param View $view - * @param SharedMount[] $mountpoints - * @return mixed - */ - private function generateUniqueTarget($path, $view, array $mountpoints) { - $pathinfo = pathinfo($path); - $ext = (isset($pathinfo['extension'])) ? '.'.$pathinfo['extension'] : ''; - $name = $pathinfo['filename']; - $dir = $pathinfo['dirname']; - - // Helper function to find existing mount points - $mountpointExists = function($path) use ($mountpoints) { - foreach ($mountpoints as $mountpoint) { - if ($mountpoint->getShare()->getTarget() === $path) { - return true; - } - } - return false; - }; - - $i = 2; - while ($view->file_exists($path) || $mountpointExists($path)) { - $path = Filesystem::normalizePath($dir . '/' . $name . ' ('.$i.')' . $ext); - $i++; - } - - return $path; - } - - /** - * Format a path to be relative to the /user/files/ directory - * - * @param string $path the absolute path - * @return string e.g. turns '/admin/files/test.txt' into '/test.txt' - * @throws \OCA\Files_Sharing\Exceptions\BrokenPath - */ - protected function stripUserFilesPath($path) { - $trimmed = ltrim($path, '/'); - $split = explode('/', $trimmed); - - // it is not a file relative to data/user/files - if (count($split) < 3 || $split[1] !== 'files') { - \OCP\Util::writeLog('file sharing', - 'Can not strip userid and "files/" from path: ' . $path, - \OCP\Util::ERROR); - throw new \OCA\Files_Sharing\Exceptions\BrokenPath('Path does not start with /user/files', 10); - } - - // skip 'user' and 'files' - $sliced = array_slice($split, 2); - $relPath = implode('/', $sliced); - - return '/' . $relPath; - } - - /** - * Move the mount point to $target - * - * @param string $target the target mount point - * @return bool - */ - public function moveMount($target) { - - $relTargetPath = $this->stripUserFilesPath($target); - $share = $this->storage->getShare(); - - $result = true; - - try { - $this->updateFileTarget($relTargetPath, $share); - $this->setMountPoint($target); - $this->storage->setMountPoint($relTargetPath); - } catch (\Exception $e) { - \OCP\Util::writeLog('file sharing', - 'Could not rename mount point for shared folder "' . $this->getMountPoint() . '" to "' . $target . '"', - \OCP\Util::ERROR); - } - - return $result; - } - - /** - * Remove the mount points - * - * @return bool - */ - public function removeMount() { - $mountManager = \OC\Files\Filesystem::getMountManager(); - /** @var $storage \OC\Files\Storage\Shared */ - $storage = $this->getStorage(); - $result = $storage->unshareStorage(); - $mountManager->removeMount($this->mountPoint); - - return $result; - } - - /** - * @return \OCP\Share\IShare - */ - public function getShare() { - return $this->share; - } - - /** - * Get the file id of the root of the storage - * - * @return int - */ - public function getStorageRootId() { - return $this->share->getNodeId(); - } -} diff --git a/apps/files_sharing/lib/sharedpropagator.php b/apps/files_sharing/lib/sharedpropagator.php deleted file mode 100644 index f17cfc3a75b..00000000000 --- a/apps/files_sharing/lib/sharedpropagator.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing; - -use OC\Files\Cache\Propagator; - -class SharedPropagator extends Propagator { - /** - * @var \OC\Files\Storage\Shared - */ - protected $storage; - - /** - * @param string $internalPath - * @param int $time - * @param int $sizeDifference - */ - public function propagateChange($internalPath, $time, $sizeDifference = 0) { - /** @var \OC\Files\Storage\Storage $storage */ - list($storage, $sourceInternalPath) = $this->storage->resolvePath($internalPath); - return $storage->getPropagator()->propagateChange($sourceInternalPath, $time, $sizeDifference); - } -} diff --git a/apps/files_sharing/lib/updater.php b/apps/files_sharing/lib/updater.php deleted file mode 100644 index 02c349e94b6..00000000000 --- a/apps/files_sharing/lib/updater.php +++ /dev/null @@ -1,109 +0,0 @@ - - * @author Joas Schilling - * @author Michael Gapczynski - * @author Morris Jobke - * @author Robin Appelman - * @author Roeland Jago Douma - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing; - -class Updater { - - /** - * @param array $params - */ - static public function renameHook($params) { - self::renameChildren($params['oldpath'], $params['newpath']); - self::moveShareToShare($params['newpath']); - } - - /** - * Fix for https://github.com/owncloud/core/issues/20769 - * - * The owner is allowed to move their files (if they are shared) into a receiving folder - * In this case we need to update the parent of the moved share. Since they are - * effectively handing over ownership of the file the rest of the code needs to know - * they need to build up the reshare tree. - * - * @param string $path - */ - static private function moveShareToShare($path) { - $userFolder = \OC::$server->getUserFolder(); - - // If the user folder can't be constructed (e.g. link share) just return. - if ($userFolder === null) { - return; - } - - $src = $userFolder->get($path); - - $shareManager = \OC::$server->getShareManager(); - - $shares = $shareManager->getSharesBy($userFolder->getOwner()->getUID(), \OCP\Share::SHARE_TYPE_USER, $src, false, -1); - $shares = array_merge($shares, $shareManager->getSharesBy($userFolder->getOwner()->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $src, false, -1)); - - // If the path we move is not a share we don't care - if (empty($shares)) { - return; - } - - // Check if the destination is inside a share - $mountManager = \OC::$server->getMountManager(); - $dstMount = $mountManager->find($src->getPath()); - if (!($dstMount instanceof \OCA\Files_Sharing\SharedMount)) { - return; - } - - $newOwner = $dstMount->getShare()->getShareOwner(); - - //Ownership is moved over - foreach ($shares as $share) { - /** @var \OCP\Share\IShare $share */ - $share->setShareOwner($newOwner); - $shareManager->updateShare($share); - } - } - - /** - * rename mount point from the children if the parent was renamed - * - * @param string $oldPath old path relative to data/user/files - * @param string $newPath new path relative to data/user/files - */ - static private function renameChildren($oldPath, $newPath) { - - $absNewPath = \OC\Files\Filesystem::normalizePath('/' . \OCP\User::getUser() . '/files/' . $newPath); - $absOldPath = \OC\Files\Filesystem::normalizePath('/' . \OCP\User::getUser() . '/files/' . $oldPath); - - $mountManager = \OC\Files\Filesystem::getMountManager(); - $mountedShares = $mountManager->findIn('/' . \OCP\User::getUser() . '/files/' . $oldPath); - foreach ($mountedShares as $mount) { - if ($mount->getStorage()->instanceOfStorage('OCA\Files_Sharing\ISharedStorage')) { - $mountPoint = $mount->getMountPoint(); - $target = str_replace($absOldPath, $absNewPath, $mountPoint); - $mount->moveMount($target); - } - } - } - -} -- cgit v1.2.3 From b72706b450dd483bc25b0fd95266a8ac6c635ae6 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 17 May 2016 10:44:49 +0200 Subject: Move background job to PSR-4 --- apps/files_sharing/appinfo/info.xml | 4 +- apps/files_sharing/lib/DeleteOrphanedSharesJob.php | 64 ++++++++++++++++++++++ apps/files_sharing/lib/deleteorphanedsharesjob.php | 64 ---------------------- lib/private/Repair/DropOldJobs.php | 2 + 4 files changed, 68 insertions(+), 66 deletions(-) create mode 100644 apps/files_sharing/lib/DeleteOrphanedSharesJob.php delete mode 100644 apps/files_sharing/lib/deleteorphanedsharesjob.php diff --git a/apps/files_sharing/appinfo/info.xml b/apps/files_sharing/appinfo/info.xml index f6e3053961f..c1f98aa94ac 100644 --- a/apps/files_sharing/appinfo/info.xml +++ b/apps/files_sharing/appinfo/info.xml @@ -24,7 +24,7 @@ Turning the feature off removes shared files and folders on the server for all s Files_Sharing - OCA\Files_sharing\Lib\DeleteOrphanedSharesJob - OCA\Files_sharing\ExpireSharesJob + OCA\Files_Sharing\DeleteOrphanedSharesJob + OCA\Files_Sharing\ExpireSharesJob diff --git a/apps/files_sharing/lib/DeleteOrphanedSharesJob.php b/apps/files_sharing/lib/DeleteOrphanedSharesJob.php new file mode 100644 index 00000000000..2678d46661d --- /dev/null +++ b/apps/files_sharing/lib/DeleteOrphanedSharesJob.php @@ -0,0 +1,64 @@ + + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing; + +use OC\BackgroundJob\TimedJob; + +/** + * Delete all share entries that have no matching entries in the file cache table. + */ +class DeleteOrphanedSharesJob extends TimedJob { + + /** + * Default interval in minutes + * + * @var int $defaultIntervalMin + **/ + protected $defaultIntervalMin = 15; + + /** + * sets the correct interval for this timed job + */ + public function __construct(){ + $this->interval = $this->defaultIntervalMin * 60; + } + + /** + * Makes the background job do its work + * + * @param array $argument unused argument + */ + public function run($argument) { + $connection = \OC::$server->getDatabaseConnection(); + $logger = \OC::$server->getLogger(); + + $sql = + 'DELETE FROM `*PREFIX*share` ' . + 'WHERE `item_type` in (\'file\', \'folder\') ' . + 'AND NOT EXISTS (SELECT `fileid` FROM `*PREFIX*filecache` WHERE `file_source` = `fileid`)'; + + $deletedEntries = $connection->executeUpdate($sql); + $logger->debug("$deletedEntries orphaned share(s) deleted", ['app' => 'DeleteOrphanedSharesJob']); + } + +} diff --git a/apps/files_sharing/lib/deleteorphanedsharesjob.php b/apps/files_sharing/lib/deleteorphanedsharesjob.php deleted file mode 100644 index 72bf6b222e7..00000000000 --- a/apps/files_sharing/lib/deleteorphanedsharesjob.php +++ /dev/null @@ -1,64 +0,0 @@ - - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_sharing\Lib; - -use OC\BackgroundJob\TimedJob; - -/** - * Delete all share entries that have no matching entries in the file cache table. - */ -class DeleteOrphanedSharesJob extends TimedJob { - - /** - * Default interval in minutes - * - * @var int $defaultIntervalMin - **/ - protected $defaultIntervalMin = 15; - - /** - * sets the correct interval for this timed job - */ - public function __construct(){ - $this->interval = $this->defaultIntervalMin * 60; - } - - /** - * Makes the background job do its work - * - * @param array $argument unused argument - */ - public function run($argument) { - $connection = \OC::$server->getDatabaseConnection(); - $logger = \OC::$server->getLogger(); - - $sql = - 'DELETE FROM `*PREFIX*share` ' . - 'WHERE `item_type` in (\'file\', \'folder\') ' . - 'AND NOT EXISTS (SELECT `fileid` FROM `*PREFIX*filecache` WHERE `file_source` = `fileid`)'; - - $deletedEntries = $connection->executeUpdate($sql); - $logger->debug("$deletedEntries orphaned share(s) deleted", ['app' => 'DeleteOrphanedSharesJob']); - } - -} diff --git a/lib/private/Repair/DropOldJobs.php b/lib/private/Repair/DropOldJobs.php index 489b89d0869..c040aa03961 100644 --- a/lib/private/Repair/DropOldJobs.php +++ b/lib/private/Repair/DropOldJobs.php @@ -73,6 +73,8 @@ class DropOldJobs implements IRepairStep { ['class' => 'OC_Cache_FileGlobalGC', 'arguments' => null], ['class' => 'OC\Cache\FileGlobalGC', 'arguments' => null], ['class' => 'OCA\Files\BackgroundJob\DeleteOrphanedTagsJob', 'arguments' => null], + ['class' => 'OCA\Files_sharing\Lib\DeleteOrphanedSharesJob', 'arguments' => null], + ['class' => 'OCA\Files_sharing\ExpireSharesJob', 'arguments' => null], ]; } -- cgit v1.2.3 From 3f0b2d148d875a2a4961a5b27309d379b9de1329 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 17 May 2016 11:42:03 +0200 Subject: Move tests to PSR-4 --- apps/files_sharing/tests/API/Share20OCSTest.php | 2089 ++++++++++++++++++++ apps/files_sharing/tests/API/ShareesTest.php | 1553 +++++++++++++++ apps/files_sharing/tests/ActivityTest.php | 80 + apps/files_sharing/tests/ApiTest.php | 1598 +++++++++++++++ apps/files_sharing/tests/BackendTest.php | 111 ++ apps/files_sharing/tests/CacheTest.php | 525 +++++ apps/files_sharing/tests/CapabilitiesTest.php | 300 +++ .../Controllers/ExternalShareControllerTest.php | 154 ++ .../tests/Controllers/ShareControllerTest.php | 454 +++++ .../tests/DeleteOrphanedSharesJobTest.php | 171 ++ .../tests/EncryptedSizePropagationTest.php | 41 + apps/files_sharing/tests/EtagPropagationTest.php | 461 +++++ apps/files_sharing/tests/ExpireSharesJobTest.php | 212 ++ apps/files_sharing/tests/External/CacheTest.php | 124 ++ apps/files_sharing/tests/External/ManagerTest.php | 253 +++ apps/files_sharing/tests/External/ScannerTest.php | 82 + apps/files_sharing/tests/ExternalStorageTest.php | 97 + .../tests/GroupEtagPropagationTest.php | 122 ++ apps/files_sharing/tests/HelperTest.php | 50 + apps/files_sharing/tests/LockingTest.php | 113 ++ .../Middleware/SharingCheckMiddlewareTest.php | 287 +++ apps/files_sharing/tests/MigrationTest.php | 352 ++++ apps/files_sharing/tests/PermissionsTest.php | 162 ++ apps/files_sharing/tests/PropagationTestCase.php | 103 + apps/files_sharing/tests/ShareTest.php | 249 +++ apps/files_sharing/tests/SharedMountTest.php | 436 ++++ apps/files_sharing/tests/SharedStorageTest.php | 532 +++++ apps/files_sharing/tests/SizePropagationTest.php | 121 ++ apps/files_sharing/tests/TestCase.php | 232 +++ apps/files_sharing/tests/UnshareChildrenTest.php | 111 ++ apps/files_sharing/tests/UpdaterTest.php | 233 +++ apps/files_sharing/tests/WatcherTest.php | 180 ++ apps/files_sharing/tests/activity.php | 80 - apps/files_sharing/tests/api.php | 1599 --------------- apps/files_sharing/tests/api/share20ocstest.php | 2089 -------------------- apps/files_sharing/tests/api/shareestest.php | 1553 --------------- apps/files_sharing/tests/backend.php | 111 -- apps/files_sharing/tests/cache.php | 525 ----- apps/files_sharing/tests/capabilities.php | 300 --- .../tests/controller/externalsharecontroller.php | 152 -- .../tests/controller/sharecontroller.php | 451 ----- .../tests/deleteorphanedsharesjobtest.php | 171 -- .../tests/encryptedsizepropagation.php | 41 - apps/files_sharing/tests/etagpropagation.php | 461 ----- apps/files_sharing/tests/expiresharesjobtest.php | 212 -- apps/files_sharing/tests/external/cache.php | 124 -- apps/files_sharing/tests/external/managertest.php | 253 --- apps/files_sharing/tests/external/scannertest.php | 82 - apps/files_sharing/tests/externalstorage.php | 95 - apps/files_sharing/tests/groupetagpropagation.php | 122 -- apps/files_sharing/tests/helper.php | 49 - apps/files_sharing/tests/locking.php | 113 -- .../tests/middleware/sharingcheckmiddleware.php | 287 --- apps/files_sharing/tests/migrationtest.php | 351 ---- apps/files_sharing/tests/permissions.php | 158 -- apps/files_sharing/tests/propagationtestcase.php | 103 - apps/files_sharing/tests/share.php | 249 --- apps/files_sharing/tests/sharedmount.php | 434 ---- apps/files_sharing/tests/sharedstorage.php | 532 ----- apps/files_sharing/tests/sizepropagation.php | 121 -- apps/files_sharing/tests/testcase.php | 233 --- apps/files_sharing/tests/unsharechildren.php | 113 -- apps/files_sharing/tests/updater.php | 232 --- apps/files_sharing/tests/watcher.php | 178 -- 64 files changed, 11588 insertions(+), 11574 deletions(-) create mode 100644 apps/files_sharing/tests/API/Share20OCSTest.php create mode 100644 apps/files_sharing/tests/API/ShareesTest.php create mode 100644 apps/files_sharing/tests/ActivityTest.php create mode 100644 apps/files_sharing/tests/ApiTest.php create mode 100644 apps/files_sharing/tests/BackendTest.php create mode 100644 apps/files_sharing/tests/CacheTest.php create mode 100644 apps/files_sharing/tests/CapabilitiesTest.php create mode 100644 apps/files_sharing/tests/Controllers/ExternalShareControllerTest.php create mode 100644 apps/files_sharing/tests/Controllers/ShareControllerTest.php create mode 100644 apps/files_sharing/tests/DeleteOrphanedSharesJobTest.php create mode 100644 apps/files_sharing/tests/EncryptedSizePropagationTest.php create mode 100644 apps/files_sharing/tests/EtagPropagationTest.php create mode 100644 apps/files_sharing/tests/ExpireSharesJobTest.php create mode 100644 apps/files_sharing/tests/External/CacheTest.php create mode 100644 apps/files_sharing/tests/External/ManagerTest.php create mode 100644 apps/files_sharing/tests/External/ScannerTest.php create mode 100644 apps/files_sharing/tests/ExternalStorageTest.php create mode 100644 apps/files_sharing/tests/GroupEtagPropagationTest.php create mode 100644 apps/files_sharing/tests/HelperTest.php create mode 100644 apps/files_sharing/tests/LockingTest.php create mode 100644 apps/files_sharing/tests/Middleware/SharingCheckMiddlewareTest.php create mode 100644 apps/files_sharing/tests/MigrationTest.php create mode 100644 apps/files_sharing/tests/PermissionsTest.php create mode 100644 apps/files_sharing/tests/PropagationTestCase.php create mode 100644 apps/files_sharing/tests/ShareTest.php create mode 100644 apps/files_sharing/tests/SharedMountTest.php create mode 100644 apps/files_sharing/tests/SharedStorageTest.php create mode 100644 apps/files_sharing/tests/SizePropagationTest.php create mode 100644 apps/files_sharing/tests/TestCase.php create mode 100644 apps/files_sharing/tests/UnshareChildrenTest.php create mode 100644 apps/files_sharing/tests/UpdaterTest.php create mode 100644 apps/files_sharing/tests/WatcherTest.php delete mode 100644 apps/files_sharing/tests/activity.php delete mode 100644 apps/files_sharing/tests/api.php delete mode 100644 apps/files_sharing/tests/api/share20ocstest.php delete mode 100644 apps/files_sharing/tests/api/shareestest.php delete mode 100644 apps/files_sharing/tests/backend.php delete mode 100644 apps/files_sharing/tests/cache.php delete mode 100644 apps/files_sharing/tests/capabilities.php delete mode 100644 apps/files_sharing/tests/controller/externalsharecontroller.php delete mode 100644 apps/files_sharing/tests/controller/sharecontroller.php delete mode 100644 apps/files_sharing/tests/deleteorphanedsharesjobtest.php delete mode 100644 apps/files_sharing/tests/encryptedsizepropagation.php delete mode 100644 apps/files_sharing/tests/etagpropagation.php delete mode 100644 apps/files_sharing/tests/expiresharesjobtest.php delete mode 100644 apps/files_sharing/tests/external/cache.php delete mode 100644 apps/files_sharing/tests/external/managertest.php delete mode 100644 apps/files_sharing/tests/external/scannertest.php delete mode 100644 apps/files_sharing/tests/externalstorage.php delete mode 100644 apps/files_sharing/tests/groupetagpropagation.php delete mode 100644 apps/files_sharing/tests/helper.php delete mode 100644 apps/files_sharing/tests/locking.php delete mode 100644 apps/files_sharing/tests/middleware/sharingcheckmiddleware.php delete mode 100644 apps/files_sharing/tests/migrationtest.php delete mode 100644 apps/files_sharing/tests/permissions.php delete mode 100644 apps/files_sharing/tests/propagationtestcase.php delete mode 100644 apps/files_sharing/tests/share.php delete mode 100644 apps/files_sharing/tests/sharedmount.php delete mode 100644 apps/files_sharing/tests/sharedstorage.php delete mode 100644 apps/files_sharing/tests/sizepropagation.php delete mode 100644 apps/files_sharing/tests/testcase.php delete mode 100644 apps/files_sharing/tests/unsharechildren.php delete mode 100644 apps/files_sharing/tests/updater.php delete mode 100644 apps/files_sharing/tests/watcher.php diff --git a/apps/files_sharing/tests/API/Share20OCSTest.php b/apps/files_sharing/tests/API/Share20OCSTest.php new file mode 100644 index 00000000000..96ce34f963c --- /dev/null +++ b/apps/files_sharing/tests/API/Share20OCSTest.php @@ -0,0 +1,2089 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ +namespace OCA\Files_Sharing\Tests\API; + +use OCP\IL10N; +use OCA\Files_Sharing\API\Share20OCS; +use OCP\Files\NotFoundException; +use OCP\IGroupManager; +use OCP\IUserManager; +use OCP\IRequest; +use OCP\IURLGenerator; +use OCP\IUser; +use OCP\Files\IRootFolder; +use OCP\Lock\LockedException; + +/** + * Class Share20OCSTest + * + * @package OCA\Files_Sharing\Tests\API + * @group DB + */ +class Share20OCSTest extends \Test\TestCase { + + /** @var \OC\Share20\Manager | \PHPUnit_Framework_MockObject_MockObject */ + private $shareManager; + + /** @var IGroupManager | \PHPUnit_Framework_MockObject_MockObject */ + private $groupManager; + + /** @var IUserManager | \PHPUnit_Framework_MockObject_MockObject */ + private $userManager; + + /** @var IRequest | \PHPUnit_Framework_MockObject_MockObject */ + private $request; + + /** @var IRootFolder | \PHPUnit_Framework_MockObject_MockObject */ + private $rootFolder; + + /** @var IURLGenerator */ + private $urlGenerator; + + /** @var IUser */ + private $currentUser; + + /** @var Share20OCS */ + private $ocs; + + /** @var IL10N */ + private $l; + + protected function setUp() { + $this->shareManager = $this->getMockBuilder('OCP\Share\IManager') + ->disableOriginalConstructor() + ->getMock(); + $this->shareManager + ->expects($this->any()) + ->method('shareApiEnabled') + ->willReturn(true); + $this->groupManager = $this->getMock('OCP\IGroupManager'); + $this->userManager = $this->getMock('OCP\IUserManager'); + $this->request = $this->getMock('OCP\IRequest'); + $this->rootFolder = $this->getMock('OCP\Files\IRootFolder'); + $this->urlGenerator = $this->getMock('OCP\IURLGenerator'); + $this->currentUser = $this->getMock('OCP\IUser'); + $this->currentUser->method('getUID')->willReturn('currentUser'); + + $this->userManager->expects($this->any())->method('userExists')->willReturn(true); + + $this->l = $this->getMock('\OCP\IL10N'); + $this->l->method('t') + ->will($this->returnCallback(function($text, $parameters = []) { + return vsprintf($text, $parameters); + })); + + $this->ocs = new Share20OCS( + $this->shareManager, + $this->groupManager, + $this->userManager, + $this->request, + $this->rootFolder, + $this->urlGenerator, + $this->currentUser, + $this->l + ); + } + + private function mockFormatShare() { + return $this->getMockBuilder('OCA\Files_Sharing\API\Share20OCS') + ->setConstructorArgs([ + $this->shareManager, + $this->groupManager, + $this->userManager, + $this->request, + $this->rootFolder, + $this->urlGenerator, + $this->currentUser, + $this->l, + ])->setMethods(['formatShare']) + ->getMock(); + } + + private function newShare() { + return \OC::$server->getShareManager()->newShare(); + } + + public function testDeleteShareShareNotFound() { + $this->shareManager + ->expects($this->exactly(2)) + ->method('getShareById') + ->will($this->returnCallback(function($id) { + if ($id === 'ocinternal:42' || $id === 'ocFederatedSharing:42') { + throw new \OCP\Share\Exceptions\ShareNotFound(); + } else { + throw new \Exception(); + } + })); + + $this->shareManager->method('outgoingServer2ServerSharesAllowed')->willReturn(true); + + $expected = new \OC_OCS_Result(null, 404, 'Wrong share ID, share doesn\'t exist'); + $this->assertEquals($expected, $this->ocs->deleteShare(42)); + } + + public function testDeleteShare() { + $node = $this->getMock('\OCP\Files\File'); + + $share = $this->newShare(); + $share->setSharedBy($this->currentUser->getUID()) + ->setNode($node); + $this->shareManager + ->expects($this->once()) + ->method('getShareById') + ->with('ocinternal:42') + ->willReturn($share); + $this->shareManager + ->expects($this->once()) + ->method('deleteShare') + ->with($share); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $node->expects($this->once()) + ->method('unlock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $expected = new \OC_OCS_Result(); + $this->assertEquals($expected, $this->ocs->deleteShare(42)); + } + + public function testDeleteShareLocked() { + $node = $this->getMock('\OCP\Files\File'); + + $share = $this->newShare(); + $share->setSharedBy($this->currentUser->getUID()) + ->setNode($node); + $this->shareManager + ->expects($this->once()) + ->method('getShareById') + ->with('ocinternal:42') + ->willReturn($share); + $this->shareManager + ->expects($this->never()) + ->method('deleteShare') + ->with($share); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED) + ->will($this->throwException(new LockedException('mypath'))); + $node->expects($this->never()) + ->method('unlock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $expected = new \OC_OCS_Result(null, 404, 'could not delete share'); + $this->assertEquals($expected, $this->ocs->deleteShare(42)); + } + + /* + * FIXME: Enable once we have a federated Share Provider + + public function testGetGetShareNotExists() { + $this->shareManager + ->expects($this->once()) + ->method('getShareById') + ->with('ocinternal:42') + ->will($this->throwException(new \OC\Share20\Exception\ShareNotFound())); + + $expected = new \OC_OCS_Result(null, 404, 'wrong share ID, share doesn\'t exist.'); + $this->assertEquals($expected, $this->ocs->getShare(42)); + } + */ + + public function createShare($id, $shareType, $sharedWith, $sharedBy, $shareOwner, $path, $permissions, + $shareTime, $expiration, $parent, $target, $mail_send, $token=null, + $password=null) { + $share = $this->getMock('\OCP\Share\IShare'); + $share->method('getId')->willReturn($id); + $share->method('getShareType')->willReturn($shareType); + $share->method('getSharedWith')->willReturn($sharedWith); + $share->method('getSharedBy')->willReturn($sharedBy); + $share->method('getShareOwner')->willReturn($shareOwner); + $share->method('getNode')->willReturn($path); + $share->method('getPermissions')->willReturn($permissions); + $time = new \DateTime(); + $time->setTimestamp($shareTime); + $share->method('getShareTime')->willReturn($time); + $share->method('getExpirationDate')->willReturn($expiration); + $share->method('getTarget')->willReturn($target); + $share->method('getMailSend')->willReturn($mail_send); + $share->method('getToken')->willReturn($token); + $share->method('getPassword')->willReturn($password); + + if ($shareType === \OCP\Share::SHARE_TYPE_USER || + $shareType === \OCP\Share::SHARE_TYPE_GROUP || + $shareType === \OCP\Share::SHARE_TYPE_LINK) { + $share->method('getFullId')->willReturn('ocinternal:'.$id); + } + + return $share; + } + + public function dataGetShare() { + $data = []; + + $cache = $this->getMockBuilder('OC\Files\Cache\Cache') + ->disableOriginalConstructor() + ->getMock(); + $cache->method('getNumericStorageId')->willReturn(101); + + $storage = $this->getMockBuilder('OC\Files\Storage\Storage') + ->disableOriginalConstructor() + ->getMock(); + $storage->method('getId')->willReturn('STORAGE'); + $storage->method('getCache')->willReturn($cache); + + $parentFolder = $this->getMock('OCP\Files\Folder'); + $parentFolder->method('getId')->willReturn(3); + + $file = $this->getMock('OCP\Files\File'); + $file->method('getId')->willReturn(1); + $file->method('getPath')->willReturn('file'); + $file->method('getStorage')->willReturn($storage); + $file->method('getParent')->willReturn($parentFolder); + $file->method('getMimeType')->willReturn('myMimeType'); + + $folder = $this->getMock('OCP\Files\Folder'); + $folder->method('getId')->willReturn(2); + $folder->method('getPath')->willReturn('folder'); + $folder->method('getStorage')->willReturn($storage); + $folder->method('getParent')->willReturn($parentFolder); + $folder->method('getMimeType')->willReturn('myFolderMimeType'); + + // File shared with user + $share = $this->createShare( + 100, + \OCP\Share::SHARE_TYPE_USER, + 'userId', + 'initiatorId', + 'ownerId', + $file, + 4, + 5, + null, + 6, + 'target', + 0 + ); + $expected = [ + 'id' => 100, + 'share_type' => \OCP\Share::SHARE_TYPE_USER, + 'share_with' => 'userId', + 'share_with_displayname' => 'userDisplay', + 'uid_owner' => 'initiatorId', + 'displayname_owner' => 'initiatorDisplay', + 'item_type' => 'file', + 'item_source' => 1, + 'file_source' => 1, + 'file_target' => 'target', + 'file_parent' => 3, + 'token' => null, + 'expiration' => null, + 'permissions' => 4, + 'stime' => 5, + 'parent' => null, + 'storage_id' => 'STORAGE', + 'path' => 'file', + 'storage' => 101, + 'mail_send' => 0, + 'uid_file_owner' => 'ownerId', + 'displayname_file_owner' => 'ownerDisplay', + 'mimetype' => 'myMimeType', + ]; + $data[] = [$share, $expected]; + + // Folder shared with group + $share = $this->createShare( + 101, + \OCP\Share::SHARE_TYPE_GROUP, + 'groupId', + 'initiatorId', + 'ownerId', + $folder, + 4, + 5, + null, + 6, + 'target', + 0 + ); + $expected = [ + 'id' => 101, + 'share_type' => \OCP\Share::SHARE_TYPE_GROUP, + 'share_with' => 'groupId', + 'share_with_displayname' => 'groupId', + 'uid_owner' => 'initiatorId', + 'displayname_owner' => 'initiatorDisplay', + 'item_type' => 'folder', + 'item_source' => 2, + 'file_source' => 2, + 'file_target' => 'target', + 'file_parent' => 3, + 'token' => null, + 'expiration' => null, + 'permissions' => 4, + 'stime' => 5, + 'parent' => null, + 'storage_id' => 'STORAGE', + 'path' => 'folder', + 'storage' => 101, + 'mail_send' => 0, + 'uid_file_owner' => 'ownerId', + 'displayname_file_owner' => 'ownerDisplay', + 'mimetype' => 'myFolderMimeType', + ]; + $data[] = [$share, $expected]; + + // File shared by link with Expire + $expire = \DateTime::createFromFormat('Y-m-d h:i:s', '2000-01-02 01:02:03'); + $share = $this->createShare( + 101, + \OCP\Share::SHARE_TYPE_LINK, + null, + 'initiatorId', + 'ownerId', + $folder, + 4, + 5, + $expire, + 6, + 'target', + 0, + 'token', + 'password' + ); + $expected = [ + 'id' => 101, + 'share_type' => \OCP\Share::SHARE_TYPE_LINK, + 'share_with' => 'password', + 'share_with_displayname' => 'password', + 'uid_owner' => 'initiatorId', + 'displayname_owner' => 'initiatorDisplay', + 'item_type' => 'folder', + 'item_source' => 2, + 'file_source' => 2, + 'file_target' => 'target', + 'file_parent' => 3, + 'token' => 'token', + 'expiration' => '2000-01-02 00:00:00', + 'permissions' => 4, + 'stime' => 5, + 'parent' => null, + 'storage_id' => 'STORAGE', + 'path' => 'folder', + 'storage' => 101, + 'mail_send' => 0, + 'url' => 'url', + 'uid_file_owner' => 'ownerId', + 'displayname_file_owner' => 'ownerDisplay', + 'mimetype' => 'myFolderMimeType', + ]; + $data[] = [$share, $expected]; + + return $data; + } + + /** + * @dataProvider dataGetShare + */ + public function testGetShare(\OCP\Share\IShare $share, array $result) { + $ocs = $this->getMockBuilder('OCA\Files_Sharing\API\Share20OCS') + ->setConstructorArgs([ + $this->shareManager, + $this->groupManager, + $this->userManager, + $this->request, + $this->rootFolder, + $this->urlGenerator, + $this->currentUser, + $this->l, + ])->setMethods(['canAccessShare']) + ->getMock(); + + $ocs->method('canAccessShare')->willReturn(true); + + $this->shareManager + ->expects($this->once()) + ->method('getShareById') + ->with($share->getFullId()) + ->willReturn($share); + + $userFolder = $this->getMock('OCP\Files\Folder'); + $userFolder + ->method('getRelativePath') + ->will($this->returnArgument(0)); + + $this->rootFolder->method('getUserFolder') + ->with($share->getShareOwner()) + ->willReturn($userFolder); + + $this->urlGenerator + ->method('linkToRouteAbsolute') + ->willReturn('url'); + + $initiator = $this->getMock('OCP\IUser'); + $initiator->method('getUID')->willReturn('initiatorId'); + $initiator->method('getDisplayName')->willReturn('initiatorDisplay'); + + $owner = $this->getMock('OCP\IUser'); + $owner->method('getUID')->willReturn('ownerId'); + $owner->method('getDisplayName')->willReturn('ownerDisplay'); + + $user = $this->getMock('OCP\IUser'); + $user->method('getUID')->willReturn('userId'); + $user->method('getDisplayName')->willReturn('userDisplay'); + + $group = $this->getMock('OCP\IGroup'); + $group->method('getGID')->willReturn('groupId'); + + $this->userManager->method('get')->will($this->returnValueMap([ + ['userId', $user], + ['initiatorId', $initiator], + ['ownerId', $owner], + ])); + $this->groupManager->method('get')->will($this->returnValueMap([ + ['group', $group], + ])); + + $expected = new \OC_OCS_Result([$result]); + $this->assertEquals($expected->getData(), $ocs->getShare($share->getId())->getData()); + } + + public function testGetShareInvalidNode() { + $share = \OC::$server->getShareManager()->newShare(); + $share->setSharedBy('initiator') + ->setSharedWith('recipient') + ->setShareOwner('owner'); + + $this->shareManager + ->expects($this->once()) + ->method('getShareById') + ->with('ocinternal:42') + ->willReturn($share); + + $expected = new \OC_OCS_Result(null, 404, 'Wrong share ID, share doesn\'t exist'); + $this->assertEquals($expected->getMeta(), $this->ocs->getShare(42)->getMeta()); + } + + public function testCanAccessShare() { + $share = $this->getMock('OCP\Share\IShare'); + $share->method('getShareOwner')->willReturn($this->currentUser->getUID()); + $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); + + $share = $this->getMock('OCP\Share\IShare'); + $share->method('getSharedBy')->willReturn($this->currentUser->getUID()); + $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); + + $share = $this->getMock('OCP\Share\IShare'); + $share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_USER); + $share->method('getSharedWith')->willReturn($this->currentUser->getUID()); + $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); + + $share = $this->getMock('OCP\Share\IShare'); + $share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_USER); + $share->method('getSharedWith')->willReturn($this->getMock('OCP\IUser')); + $this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); + + $share = $this->getMock('OCP\Share\IShare'); + $share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_GROUP); + $share->method('getSharedWith')->willReturn('group'); + + $group = $this->getMock('OCP\IGroup'); + $group->method('inGroup')->with($this->currentUser)->willReturn(true); + $group2 = $this->getMock('OCP\IGroup'); + $group2->method('inGroup')->with($this->currentUser)->willReturn(false); + + + $this->groupManager->method('get')->will($this->returnValueMap([ + ['group', $group], + ['group2', $group2], + ])); + $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); + + $share = $this->getMock('OCP\Share\IShare'); + $share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_GROUP); + $share->method('getSharedWith')->willReturn('group2'); + + $this->groupManager->method('get')->with('group2')->willReturn($group); + $this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); + + $share = $this->getMock('OCP\Share\IShare'); + $share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_LINK); + $this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); + } + + public function testCreateShareNoPath() { + $expected = new \OC_OCS_Result(null, 404, 'Please specify a file or folder path'); + + $result = $this->ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testCreateShareInvalidPath() { + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'invalid-path'], + ])); + + $userFolder = $this->getMock('\OCP\Files\Folder'); + $this->rootFolder->expects($this->once()) + ->method('getUserFolder') + ->with('currentUser') + ->willReturn($userFolder); + + $userFolder->expects($this->once()) + ->method('get') + ->with('invalid-path') + ->will($this->throwException(new \OCP\Files\NotFoundException())); + + $expected = new \OC_OCS_Result(null, 404, 'Wrong path, file/folder doesn\'t exist'); + + $result = $this->ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testCreateShareInvalidPermissions() { + $share = $this->newShare(); + $this->shareManager->method('newShare')->willReturn($share); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'valid-path'], + ['permissions', null, 32], + ])); + + $userFolder = $this->getMock('\OCP\Files\Folder'); + $this->rootFolder->expects($this->once()) + ->method('getUserFolder') + ->with('currentUser') + ->willReturn($userFolder); + + $path = $this->getMock('\OCP\Files\File'); + $userFolder->expects($this->once()) + ->method('get') + ->with('valid-path') + ->willReturn($path); + + $path->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $expected = new \OC_OCS_Result(null, 404, 'invalid permissions'); + + $result = $this->ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testCreateShareUserNoShareWith() { + $share = $this->newShare(); + $this->shareManager->method('newShare')->willReturn($share); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'valid-path'], + ['permissions', null, \OCP\Constants::PERMISSION_ALL], + ['shareType', $this->any(), \OCP\Share::SHARE_TYPE_USER], + ])); + + $userFolder = $this->getMock('\OCP\Files\Folder'); + $this->rootFolder->expects($this->once()) + ->method('getUserFolder') + ->with('currentUser') + ->willReturn($userFolder); + + $path = $this->getMock('\OCP\Files\File'); + $storage = $this->getMock('OCP\Files\Storage'); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $userFolder->expects($this->once()) + ->method('get') + ->with('valid-path') + ->willReturn($path); + + $path->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $expected = new \OC_OCS_Result(null, 404, 'Please specify a valid user'); + + $result = $this->ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testCreateShareUserNoValidShareWith() { + $share = $this->newShare(); + $this->shareManager->method('newShare')->willReturn($share); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'valid-path'], + ['permissions', null, \OCP\Constants::PERMISSION_ALL], + ['shareType', $this->any(), \OCP\Share::SHARE_TYPE_USER], + ['shareWith', $this->any(), 'invalidUser'], + ])); + + $userFolder = $this->getMock('\OCP\Files\Folder'); + $this->rootFolder->expects($this->once()) + ->method('getUserFolder') + ->with('currentUser') + ->willReturn($userFolder); + + $path = $this->getMock('\OCP\Files\File'); + $storage = $this->getMock('OCP\Files\Storage'); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $userFolder->expects($this->once()) + ->method('get') + ->with('valid-path') + ->willReturn($path); + + $expected = new \OC_OCS_Result(null, 404, 'Please specify a valid user'); + + $path->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $result = $this->ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testCreateShareUser() { + $share = $this->newShare(); + $this->shareManager->method('newShare')->willReturn($share); + + $ocs = $this->getMockBuilder('OCA\Files_Sharing\API\Share20OCS') + ->setConstructorArgs([ + $this->shareManager, + $this->groupManager, + $this->userManager, + $this->request, + $this->rootFolder, + $this->urlGenerator, + $this->currentUser, + $this->l, + ])->setMethods(['formatShare']) + ->getMock(); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'valid-path'], + ['permissions', null, \OCP\Constants::PERMISSION_ALL], + ['shareType', $this->any(), \OCP\Share::SHARE_TYPE_USER], + ['shareWith', null, 'validUser'], + ])); + + $userFolder = $this->getMock('\OCP\Files\Folder'); + $this->rootFolder->expects($this->once()) + ->method('getUserFolder') + ->with('currentUser') + ->willReturn($userFolder); + + $path = $this->getMock('\OCP\Files\File'); + $storage = $this->getMock('OCP\Files\Storage'); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $userFolder->expects($this->once()) + ->method('get') + ->with('valid-path') + ->willReturn($path); + + $this->userManager->method('userExists')->with('validUser')->willReturn(true); + + $path->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $path->expects($this->once()) + ->method('unlock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->shareManager->method('createShare') + ->with($this->callback(function (\OCP\Share\IShare $share) use ($path) { + return $share->getNode() === $path && + $share->getPermissions() === ( + \OCP\Constants::PERMISSION_ALL & + ~\OCP\Constants::PERMISSION_DELETE & + ~\OCP\Constants::PERMISSION_CREATE + ) && + $share->getShareType() === \OCP\Share::SHARE_TYPE_USER && + $share->getSharedWith() === 'validUser' && + $share->getSharedBy() === 'currentUser'; + })) + ->will($this->returnArgument(0)); + + $expected = new \OC_OCS_Result(); + $result = $ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testCreateShareGroupNoValidShareWith() { + $share = $this->newShare(); + $this->shareManager->method('newShare')->willReturn($share); + $this->shareManager->method('createShare')->will($this->returnArgument(0)); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'valid-path'], + ['permissions', null, \OCP\Constants::PERMISSION_ALL], + ['shareType', $this->any(), \OCP\Share::SHARE_TYPE_GROUP], + ['shareWith', $this->any(), 'invalidGroup'], + ])); + + $userFolder = $this->getMock('\OCP\Files\Folder'); + $this->rootFolder->expects($this->once()) + ->method('getUserFolder') + ->with('currentUser') + ->willReturn($userFolder); + + $path = $this->getMock('\OCP\Files\File'); + $storage = $this->getMock('OCP\Files\Storage'); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $userFolder->expects($this->once()) + ->method('get') + ->with('valid-path') + ->willReturn($path); + + $expected = new \OC_OCS_Result(null, 404, 'Please specify a valid user'); + + $path->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $result = $this->ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testCreateShareGroup() { + $share = $this->newShare(); + $this->shareManager->method('newShare')->willReturn($share); + + $ocs = $this->getMockBuilder('OCA\Files_Sharing\API\Share20OCS') + ->setConstructorArgs([ + $this->shareManager, + $this->groupManager, + $this->userManager, + $this->request, + $this->rootFolder, + $this->urlGenerator, + $this->currentUser, + $this->l, + ])->setMethods(['formatShare']) + ->getMock(); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'valid-path'], + ['permissions', null, \OCP\Constants::PERMISSION_ALL], + ['shareType', '-1', \OCP\Share::SHARE_TYPE_GROUP], + ['shareWith', null, 'validGroup'], + ])); + + $userFolder = $this->getMock('\OCP\Files\Folder'); + $this->rootFolder->expects($this->once()) + ->method('getUserFolder') + ->with('currentUser') + ->willReturn($userFolder); + + $path = $this->getMock('\OCP\Files\Folder'); + $storage = $this->getMock('OCP\Files\Storage'); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $userFolder->expects($this->once()) + ->method('get') + ->with('valid-path') + ->willReturn($path); + + $this->groupManager->method('groupExists')->with('validGroup')->willReturn(true); + + $this->shareManager->expects($this->once()) + ->method('allowGroupSharing') + ->willReturn(true); + + $path->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $path->expects($this->once()) + ->method('unlock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->shareManager->method('createShare') + ->with($this->callback(function (\OCP\Share\IShare $share) use ($path) { + return $share->getNode() === $path && + $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && + $share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP && + $share->getSharedWith() === 'validGroup' && + $share->getSharedBy() === 'currentUser'; + })) + ->will($this->returnArgument(0)); + + $expected = new \OC_OCS_Result(); + $result = $ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testCreateShareGroupNotAllowed() { + $share = $this->newShare(); + $this->shareManager->method('newShare')->willReturn($share); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'valid-path'], + ['permissions', null, \OCP\Constants::PERMISSION_ALL], + ['shareType', '-1', \OCP\Share::SHARE_TYPE_GROUP], + ['shareWith', null, 'validGroup'], + ])); + + $userFolder = $this->getMock('\OCP\Files\Folder'); + $this->rootFolder->expects($this->once()) + ->method('getUserFolder') + ->with('currentUser') + ->willReturn($userFolder); + + $path = $this->getMock('\OCP\Files\Folder'); + $storage = $this->getMock('OCP\Files\Storage'); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $userFolder->expects($this->once()) + ->method('get') + ->with('valid-path') + ->willReturn($path); + + $this->groupManager->method('groupExists')->with('validGroup')->willReturn(true); + + $this->shareManager->expects($this->once()) + ->method('allowGroupSharing') + ->willReturn(false); + + $expected = new \OC_OCS_Result(null, 404, 'Group sharing is disabled by the administrator'); + + $result = $this->ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testCreateShareLinkNoLinksAllowed() { + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'valid-path'], + ['shareType', '-1', \OCP\Share::SHARE_TYPE_LINK], + ])); + + $path = $this->getMock('\OCP\Files\Folder'); + $storage = $this->getMock('OCP\Files\Storage'); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); + $this->rootFolder->method('get')->with('valid-path')->willReturn($path); + + $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); + + $expected = new \OC_OCS_Result(null, 404, 'Public link sharing is disabled by the administrator'); + $result = $this->ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testCreateShareLinkNoPublicUpload() { + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'valid-path'], + ['shareType', '-1', \OCP\Share::SHARE_TYPE_LINK], + ['publicUpload', null, 'true'], + ])); + + $path = $this->getMock('\OCP\Files\Folder'); + $storage = $this->getMock('OCP\Files\Storage'); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); + $this->rootFolder->method('get')->with('valid-path')->willReturn($path); + + $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); + $this->shareManager->method('shareApiAllowLinks')->willReturn(true); + + $expected = new \OC_OCS_Result(null, 403, 'Public upload disabled by the administrator'); + $result = $this->ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testCreateShareLinkPublicUploadFile() { + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'valid-path'], + ['shareType', '-1', \OCP\Share::SHARE_TYPE_LINK], + ['publicUpload', null, 'true'], + ])); + + $path = $this->getMock('\OCP\Files\File'); + $storage = $this->getMock('OCP\Files\Storage'); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); + $this->rootFolder->method('get')->with('valid-path')->willReturn($path); + + $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); + $this->shareManager->method('shareApiAllowLinks')->willReturn(true); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); + + $expected = new \OC_OCS_Result(null, 404, 'Public upload is only possible for publicly shared folders'); + $result = $this->ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testCreateShareLinkPublicUploadFolder() { + $ocs = $this->mockFormatShare(); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'valid-path'], + ['shareType', '-1', \OCP\Share::SHARE_TYPE_LINK], + ['publicUpload', null, 'true'], + ['expireDate', '', ''], + ['password', '', ''], + ])); + + $path = $this->getMock('\OCP\Files\Folder'); + $storage = $this->getMock('OCP\Files\Storage'); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); + $this->rootFolder->method('get')->with('valid-path')->willReturn($path); + + $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); + $this->shareManager->method('shareApiAllowLinks')->willReturn(true); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); + + $this->shareManager->expects($this->once())->method('createShare')->with( + $this->callback(function (\OCP\Share\IShare $share) use ($path) { + return $share->getNode() === $path && + $share->getShareType() === \OCP\Share::SHARE_TYPE_LINK && + $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE && + $share->getSharedBy() === 'currentUser' && + $share->getPassword() === null && + $share->getExpirationDate() === null; + }) + )->will($this->returnArgument(0)); + + $expected = new \OC_OCS_Result(null); + $result = $ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testCreateShareLinkPassword() { + $ocs = $this->mockFormatShare(); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'valid-path'], + ['shareType', '-1', \OCP\Share::SHARE_TYPE_LINK], + ['publicUpload', null, 'false'], + ['expireDate', '', ''], + ['password', '', 'password'], + ])); + + $path = $this->getMock('\OCP\Files\Folder'); + $storage = $this->getMock('OCP\Files\Storage'); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); + $this->rootFolder->method('get')->with('valid-path')->willReturn($path); + + $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); + $this->shareManager->method('shareApiAllowLinks')->willReturn(true); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); + + $this->shareManager->expects($this->once())->method('createShare')->with( + $this->callback(function (\OCP\Share\IShare $share) use ($path) { + return $share->getNode() === $path && + $share->getShareType() === \OCP\Share::SHARE_TYPE_LINK && + $share->getPermissions() === \OCP\Constants::PERMISSION_READ && + $share->getSharedBy() === 'currentUser' && + $share->getPassword() === 'password' && + $share->getExpirationDate() === null; + }) + )->will($this->returnArgument(0)); + + $expected = new \OC_OCS_Result(null); + $result = $ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testCreateShareValidExpireDate() { + $ocs = $this->mockFormatShare(); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'valid-path'], + ['shareType', '-1', \OCP\Share::SHARE_TYPE_LINK], + ['publicUpload', null, 'false'], + ['expireDate', '', '2000-01-01'], + ['password', '', ''], + ])); + + $path = $this->getMock('\OCP\Files\Folder'); + $storage = $this->getMock('OCP\Files\Storage'); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); + $this->rootFolder->method('get')->with('valid-path')->willReturn($path); + + $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); + $this->shareManager->method('shareApiAllowLinks')->willReturn(true); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); + + $this->shareManager->expects($this->once())->method('createShare')->with( + $this->callback(function (\OCP\Share\IShare $share) use ($path) { + $date = new \DateTime('2000-01-01'); + $date->setTime(0,0,0); + + return $share->getNode() === $path && + $share->getShareType() === \OCP\Share::SHARE_TYPE_LINK && + $share->getPermissions() === \OCP\Constants::PERMISSION_READ && + $share->getSharedBy() === 'currentUser' && + $share->getPassword() === null && + $share->getExpirationDate() == $date; + }) + )->will($this->returnArgument(0)); + + $expected = new \OC_OCS_Result(null); + $result = $ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testCreateShareInvalidExpireDate() { + $ocs = $this->mockFormatShare(); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'valid-path'], + ['shareType', '-1', \OCP\Share::SHARE_TYPE_LINK], + ['publicUpload', null, 'false'], + ['expireDate', '', 'a1b2d3'], + ['password', '', ''], + ])); + + $path = $this->getMock('\OCP\Files\Folder'); + $storage = $this->getMock('OCP\Files\Storage'); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $path->method('getStorage')->willReturn($storage); + $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); + $this->rootFolder->method('get')->with('valid-path')->willReturn($path); + + $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); + $this->shareManager->method('shareApiAllowLinks')->willReturn(true); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); + + $expected = new \OC_OCS_Result(null, 404, 'Invalid date, date format must be YYYY-MM-DD'); + $result = $ocs->createShare(); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + /** + * Test for https://github.com/owncloud/core/issues/22587 + * TODO: Remove once proper solution is in place + */ + public function testCreateReshareOfFederatedMountNoDeletePermissions() { + $share = \OC::$server->getShareManager()->newShare(); + $this->shareManager->method('newShare')->willReturn($share); + + $ocs = $this->getMockBuilder('OCA\Files_Sharing\API\Share20OCS') + ->setConstructorArgs([ + $this->shareManager, + $this->groupManager, + $this->userManager, + $this->request, + $this->rootFolder, + $this->urlGenerator, + $this->currentUser, + $this->l, + ])->setMethods(['formatShare']) + ->getMock(); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['path', null, 'valid-path'], + ['permissions', null, \OCP\Constants::PERMISSION_ALL], + ['shareType', $this->any(), \OCP\Share::SHARE_TYPE_USER], + ['shareWith', null, 'validUser'], + ])); + + $userFolder = $this->getMock('\OCP\Files\Folder'); + $this->rootFolder->expects($this->once()) + ->method('getUserFolder') + ->with('currentUser') + ->willReturn($userFolder); + + $path = $this->getMock('\OCP\Files\Folder'); + $storage = $this->getMock('OCP\Files\Storage'); + $storage->method('instanceOfStorage') + ->with('OCA\Files_Sharing\External\Storage') + ->willReturn(true); + $path->method('getStorage')->willReturn($storage); + $path->method('getPermissions')->willReturn(\OCP\Constants::PERMISSION_READ); + $userFolder->expects($this->once()) + ->method('get') + ->with('valid-path') + ->willReturn($path); + + $this->userManager->method('userExists')->with('validUser')->willReturn(true); + + $this->shareManager + ->expects($this->once()) + ->method('createShare') + ->with($this->callback(function (\OCP\Share\IShare $share) { + return $share->getPermissions() === \OCP\Constants::PERMISSION_READ; + })) + ->will($this->returnArgument(0)); + + $ocs->createShare(); + } + + public function testUpdateShareCantAccess() { + $node = $this->getMock('\OCP\Files\Folder'); + $share = $this->newShare(); + $share->setNode($node); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + + $expected = new \OC_OCS_Result(null, 404, 'Wrong share ID, share doesn\'t exist'); + $result = $this->ocs->updateShare(42); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testUpdateNoParametersLink() { + $node = $this->getMock('\OCP\Files\Folder'); + $share = $this->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser->getUID()) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setNode($node); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + + $expected = new \OC_OCS_Result(null, 400, 'Wrong or no update parameter given'); + $result = $this->ocs->updateShare(42); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testUpdateNoParametersOther() { + $node = $this->getMock('\OCP\Files\Folder'); + $share = $this->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser->getUID()) + ->setShareType(\OCP\Share::SHARE_TYPE_GROUP) + ->setNode($node); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + + $expected = new \OC_OCS_Result(null, 400, 'Wrong or no update parameter given'); + $result = $this->ocs->updateShare(42); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testUpdateLinkShareClear() { + $ocs = $this->mockFormatShare(); + + $node = $this->getMock('\OCP\Files\Folder'); + $share = $this->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser->getUID()) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPassword('password') + ->setExpirationDate(new \DateTime()) + ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setNode($node); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $node->expects($this->once()) + ->method('unlock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['publicUpload', null, 'false'], + ['expireDate', null, ''], + ['password', null, ''], + ])); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + + $this->shareManager->expects($this->once())->method('updateShare')->with( + $this->callback(function (\OCP\Share\IShare $share) { + return $share->getPermissions() === \OCP\Constants::PERMISSION_READ && + $share->getPassword() === null && + $share->getExpirationDate() === null; + }) + )->will($this->returnArgument(0)); + + $expected = new \OC_OCS_Result(null); + $result = $ocs->updateShare(42); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testUpdateLinkShareSet() { + $ocs = $this->mockFormatShare(); + + $folder = $this->getMock('\OCP\Files\Folder'); + + $share = \OC::$server->getShareManager()->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser->getUID()) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setNode($folder); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['publicUpload', null, 'true'], + ['expireDate', null, '2000-01-01'], + ['password', null, 'password'], + ])); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); + + $this->shareManager->expects($this->once())->method('updateShare')->with( + $this->callback(function (\OCP\Share\IShare $share) { + $date = new \DateTime('2000-01-01'); + $date->setTime(0,0,0); + + return $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE && \OCP\Constants::PERMISSION_DELETE && + $share->getPassword() === 'password' && + $share->getExpirationDate() == $date; + }) + )->will($this->returnArgument(0)); + + $expected = new \OC_OCS_Result(null); + $result = $ocs->updateShare(42); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testUpdateLinkShareInvalidDate() { + $ocs = $this->mockFormatShare(); + + $folder = $this->getMock('\OCP\Files\Folder'); + + $share = \OC::$server->getShareManager()->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser->getUID()) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setNode($folder); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['publicUpload', null, 'true'], + ['expireDate', null, '2000-01-a'], + ['password', null, 'password'], + ])); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); + + $expected = new \OC_OCS_Result(null, 400, 'Invalid date. Format must be YYYY-MM-DD'); + $result = $ocs->updateShare(42); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testUpdateLinkSharePublicUploadNotAllowed() { + $ocs = $this->mockFormatShare(); + + $folder = $this->getMock('\OCP\Files\Folder'); + + $share = \OC::$server->getShareManager()->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser->getUID()) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setNode($folder); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['publicUpload', null, 'true'], + ['expireDate', '', null], + ['password', '', 'password'], + ])); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(false); + + $expected = new \OC_OCS_Result(null, 403, 'Public upload disabled by the administrator'); + $result = $ocs->updateShare(42); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testUpdateLinkSharePublicUploadOnFile() { + $ocs = $this->mockFormatShare(); + + $file = $this->getMock('\OCP\Files\File'); + + $share = \OC::$server->getShareManager()->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser->getUID()) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setNode($file); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['publicUpload', null, 'true'], + ['expireDate', '', ''], + ['password', '', 'password'], + ])); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); + + $expected = new \OC_OCS_Result(null, 400, 'Public upload is only possible for publicly shared folders'); + $result = $ocs->updateShare(42); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testUpdateLinkSharePasswordDoesNotChangeOther() { + $ocs = $this->mockFormatShare(); + + $date = new \DateTime('2000-01-01'); + $date->setTime(0,0,0); + + $node = $this->getMock('\OCP\Files\File'); + $share = $this->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser->getUID()) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPassword('password') + ->setExpirationDate($date) + ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setNode($node); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $node->expects($this->once()) + ->method('unlock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['password', null, 'newpassword'], + ])); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + + $this->shareManager->expects($this->once())->method('updateShare')->with( + $this->callback(function (\OCP\Share\IShare $share) use ($date) { + return $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && + $share->getPassword() === 'newpassword' && + $share->getExpirationDate() === $date; + }) + )->will($this->returnArgument(0)); + + $expected = new \OC_OCS_Result(null); + $result = $ocs->updateShare(42); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testUpdateLinkShareExpireDateDoesNotChangeOther() { + $ocs = $this->mockFormatShare(); + + $node = $this->getMock('\OCP\Files\File'); + $share = $this->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser->getUID()) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPassword('password') + ->setExpirationDate(new \DateTime()) + ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setNode($node); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['expireDate', null, '2010-12-23'], + ])); + + $node->expects($this->once()) + ->method('lock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + $node->expects($this->once()) + ->method('unlock') + ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + + $this->shareManager->expects($this->once())->method('updateShare')->with( + $this->callback(function (\OCP\Share\IShare $share) { + $date = new \DateTime('2010-12-23'); + $date->setTime(0,0,0); + + return $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && + $share->getPassword() === 'password' && + $share->getExpirationDate() == $date; + }) + )->will($this->returnArgument(0)); + + $expected = new \OC_OCS_Result(null); + $result = $ocs->updateShare(42); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testUpdateLinkSharePublicUploadDoesNotChangeOther() { + $ocs = $this->mockFormatShare(); + + $date = new \DateTime('2000-01-01'); + + $folder = $this->getMock('\OCP\Files\Folder'); + + $share = \OC::$server->getShareManager()->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser->getUID()) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPassword('password') + ->setExpirationDate($date) + ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setNode($folder); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['publicUpload', null, 'true'], + ])); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); + + $this->shareManager->expects($this->once())->method('updateShare')->with( + $this->callback(function (\OCP\Share\IShare $share) use ($date) { + return $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE && + $share->getPassword() === 'password' && + $share->getExpirationDate() === $date; + }) + )->will($this->returnArgument(0)); + + $expected = new \OC_OCS_Result(null); + $result = $ocs->updateShare(42); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testUpdateLinkSharePermissions() { + $ocs = $this->mockFormatShare(); + + $date = new \DateTime('2000-01-01'); + + $folder = $this->getMock('\OCP\Files\Folder'); + + $share = \OC::$server->getShareManager()->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser->getUID()) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPassword('password') + ->setExpirationDate($date) + ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setNode($folder); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['permissions', null, '7'], + ])); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); + + $this->shareManager->expects($this->once())->method('updateShare')->with( + $this->callback(function (\OCP\Share\IShare $share) use ($date) { + return $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE && + $share->getPassword() === 'password' && + $share->getExpirationDate() === $date; + }) + )->will($this->returnArgument(0)); + + $this->shareManager->method('getSharedWith')->willReturn([]); + + $expected = new \OC_OCS_Result(null); + $result = $ocs->updateShare(42); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testUpdateLinkShareInvalidPermissions() { + $ocs = $this->mockFormatShare(); + + $date = new \DateTime('2000-01-01'); + + $folder = $this->getMock('\OCP\Files\Folder'); + + $share = \OC::$server->getShareManager()->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser->getUID()) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPassword('password') + ->setExpirationDate($date) + ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setNode($folder); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['permissions', null, '31'], + ])); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); + + $expected = new \OC_OCS_Result(null, 400, 'Can\'t change permissions for public share links'); + $result = $ocs->updateShare(42); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function testUpdateOtherPermissions() { + $ocs = $this->mockFormatShare(); + + $file = $this->getMock('\OCP\Files\File'); + + $share = \OC::$server->getShareManager()->newShare(); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setSharedBy($this->currentUser->getUID()) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setNode($file); + + $this->request + ->method('getParam') + ->will($this->returnValueMap([ + ['permissions', null, '31'], + ])); + + $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); + $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); + + $this->shareManager->expects($this->once())->method('updateShare')->with( + $this->callback(function (\OCP\Share\IShare $share) { + return $share->getPermissions() === \OCP\Constants::PERMISSION_ALL; + }) + )->will($this->returnArgument(0)); + + $this->shareManager->method('getSharedWith')->willReturn([]); + + $expected = new \OC_OCS_Result(null); + $result = $ocs->updateShare(42); + + $this->assertEquals($expected->getMeta(), $result->getMeta()); + $this->assertEquals($expected->getData(), $result->getData()); + } + + public function dataFormatShare() { + $file = $this->getMock('\OCP\Files\File'); + $folder = $this->getMock('\OCP\Files\Folder'); + $parent = $this->getMock('\OCP\Files\Folder'); + + $file->method('getMimeType')->willReturn('myMimeType'); + $folder->method('getMimeType')->willReturn('myFolderMimeType'); + + $file->method('getPath')->willReturn('file'); + $folder->method('getPath')->willReturn('folder'); + + $parent->method('getId')->willReturn(1); + $folder->method('getId')->willReturn(2); + $file->method('getId')->willReturn(3); + + $file->method('getParent')->willReturn($parent); + $folder->method('getParent')->willReturn($parent); + + $cache = $this->getMock('OCP\Files\Cache\ICache'); + $cache->method('getNumericStorageId')->willReturn(100); + $storage = $this->getMock('\OCP\Files\Storage'); + $storage->method('getId')->willReturn('storageId'); + $storage->method('getCache')->willReturn($cache); + + $file->method('getStorage')->willReturn($storage); + $folder->method('getStorage')->willReturn($storage); + + $owner = $this->getMock('\OCP\IUser'); + $owner->method('getDisplayName')->willReturn('ownerDN'); + $initiator = $this->getMock('\OCP\IUser'); + $initiator->method('getDisplayName')->willReturn('initiatorDN'); + $recipient = $this->getMock('\OCP\IUser'); + $recipient->method('getDisplayName')->willReturn('recipientDN'); + + $result = []; + + $share = \OC::$server->getShareManager()->newShare(); + $share->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith('recipient') + ->setSharedBy('initiator') + ->setShareOwner('owner') + ->setPermissions(\OCP\Constants::PERMISSION_READ) + ->setNode($file) + ->setShareTime(new \DateTime('2000-01-01T00:01:02')) + ->setTarget('myTarget') + ->setId(42); + + /* User backend down */ + $result[] = [ + [ + 'id' => 42, + 'share_type' => \OCP\Share::SHARE_TYPE_USER, + 'uid_owner' => 'initiator', + 'displayname_owner' => 'initiator', + 'permissions' => 1, + 'stime' => 946684862, + 'parent' => null, + 'expiration' => null, + 'token' => null, + 'uid_file_owner' => 'owner', + 'displayname_file_owner' => 'owner', + 'path' => 'file', + 'item_type' => 'file', + 'storage_id' => 'storageId', + 'storage' => 100, + 'item_source' => 3, + 'file_source' => 3, + 'file_parent' => 1, + 'file_target' => 'myTarget', + 'share_with' => 'recipient', + 'share_with_displayname' => 'recipient', + 'mail_send' => 0, + 'mimetype' => 'myMimeType', + ], $share, [], false + ]; + + /* User backend up */ + $result[] = [ + [ + 'id' => 42, + 'share_type' => \OCP\Share::SHARE_TYPE_USER, + 'uid_owner' => 'initiator', + 'displayname_owner' => 'initiatorDN', + 'permissions' => 1, + 'stime' => 946684862, + 'parent' => null, + 'expiration' => null, + 'token' => null, + 'uid_file_owner' => 'owner', + 'displayname_file_owner' => 'ownerDN', + 'path' => 'file', + 'item_type' => 'file', + 'storage_id' => 'storageId', + 'storage' => 100, + 'item_source' => 3, + 'file_source' => 3, + 'file_parent' => 1, + 'file_target' => 'myTarget', + 'share_with' => 'recipient', + 'share_with_displayname' => 'recipientDN', + 'mail_send' => 0, + 'mimetype' => 'myMimeType', + ], $share, [ + ['owner', $owner], + ['initiator', $initiator], + ['recipient', $recipient], + ], false + ]; + + $share = \OC::$server->getShareManager()->newShare(); + $share->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith('recipient') + ->setSharedBy('initiator') + ->setShareOwner('owner') + ->setPermissions(\OCP\Constants::PERMISSION_READ) + ->setNode($file) + ->setShareTime(new \DateTime('2000-01-01T00:01:02')) + ->setTarget('myTarget') + ->setId(42); + + /* User backend down */ + $result[] = [ + [ + 'id' => 42, + 'share_type' => \OCP\Share::SHARE_TYPE_USER, + 'uid_owner' => 'initiator', + 'displayname_owner' => 'initiator', + 'permissions' => 1, + 'stime' => 946684862, + 'parent' => null, + 'expiration' => null, + 'token' => null, + 'uid_file_owner' => 'owner', + 'displayname_file_owner' => 'owner', + 'path' => 'file', + 'item_type' => 'file', + 'storage_id' => 'storageId', + 'storage' => 100, + 'item_source' => 3, + 'file_source' => 3, + 'file_parent' => 1, + 'file_target' => 'myTarget', + 'share_with' => 'recipient', + 'share_with_displayname' => 'recipient', + 'mail_send' => 0, + 'mimetype' => 'myMimeType', + ], $share, [], false + ]; + + $share = \OC::$server->getShareManager()->newShare(); + $share->setShareType(\OCP\Share::SHARE_TYPE_GROUP) + ->setSharedWith('recipient') + ->setSharedBy('initiator') + ->setShareOwner('owner') + ->setPermissions(\OCP\Constants::PERMISSION_READ) + ->setNode($file) + ->setShareTime(new \DateTime('2000-01-01T00:01:02')) + ->setTarget('myTarget') + ->setId(42); + + $result[] = [ + [ + 'id' => 42, + 'share_type' => \OCP\Share::SHARE_TYPE_GROUP, + 'uid_owner' => 'initiator', + 'displayname_owner' => 'initiator', + 'permissions' => 1, + 'stime' => 946684862, + 'parent' => null, + 'expiration' => null, + 'token' => null, + 'uid_file_owner' => 'owner', + 'displayname_file_owner' => 'owner', + 'path' => 'file', + 'item_type' => 'file', + 'storage_id' => 'storageId', + 'storage' => 100, + 'item_source' => 3, + 'file_source' => 3, + 'file_parent' => 1, + 'file_target' => 'myTarget', + 'share_with' => 'recipient', + 'share_with_displayname' => 'recipient', + 'mail_send' => 0, + 'mimetype' => 'myMimeType', + ], $share, [], false + ]; + + $share = \OC::$server->getShareManager()->newShare(); + $share->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setSharedBy('initiator') + ->setShareOwner('owner') + ->setPermissions(\OCP\Constants::PERMISSION_READ) + ->setNode($file) + ->setShareTime(new \DateTime('2000-01-01T00:01:02')) + ->setTarget('myTarget') + ->setPassword('mypassword') + ->setExpirationDate(new \DateTime('2001-01-02T00:00:00')) + ->setToken('myToken') + ->setId(42); + + $result[] = [ + [ + 'id' => 42, + 'share_type' => \OCP\Share::SHARE_TYPE_LINK, + 'uid_owner' => 'initiator', + 'displayname_owner' => 'initiator', + 'permissions' => 1, + 'stime' => 946684862, + 'parent' => null, + 'expiration' => '2001-01-02 00:00:00', + 'token' => 'myToken', + 'uid_file_owner' => 'owner', + 'displayname_file_owner' => 'owner', + 'path' => 'file', + 'item_type' => 'file', + 'storage_id' => 'storageId', + 'storage' => 100, + 'item_source' => 3, + 'file_source' => 3, + 'file_parent' => 1, + 'file_target' => 'myTarget', + 'share_with' => 'mypassword', + 'share_with_displayname' => 'mypassword', + 'mail_send' => 0, + 'url' => 'myLink', + 'mimetype' => 'myMimeType', + ], $share, [], false + ]; + + $share = \OC::$server->getShareManager()->newShare(); + $share->setShareType(\OCP\Share::SHARE_TYPE_REMOTE) + ->setSharedBy('initiator') + ->setSharedWith('user@server.com') + ->setShareOwner('owner') + ->setPermissions(\OCP\Constants::PERMISSION_READ) + ->setNode($folder) + ->setShareTime(new \DateTime('2000-01-01T00:01:02')) + ->setTarget('myTarget') + ->setId(42); + + $result[] = [ + [ + 'id' => 42, + 'share_type' => \OCP\Share::SHARE_TYPE_REMOTE, + 'uid_owner' => 'initiator', + 'displayname_owner' => 'initiator', + 'permissions' => 1, + 'stime' => 946684862, + 'parent' => null, + 'expiration' => null, + 'token' => null, + 'uid_file_owner' => 'owner', + 'displayname_file_owner' => 'owner', + 'path' => 'folder', + 'item_type' => 'folder', + 'storage_id' => 'storageId', + 'storage' => 100, + 'item_source' => 2, + 'file_source' => 2, + 'file_parent' => 1, + 'file_target' => 'myTarget', + 'share_with' => 'user@server.com', + 'share_with_displayname' => 'user@server.com', + 'mail_send' => 0, + 'mimetype' => 'myFolderMimeType', + ], $share, [], false + ]; + + $share = \OC::$server->getShareManager()->newShare(); + $share->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedBy('initiator') + ->setSharedWith('recipient') + ->setShareOwner('owner') + ->setPermissions(\OCP\Constants::PERMISSION_READ) + ->setShareTime(new \DateTime('2000-01-01T00:01:02')) + ->setTarget('myTarget') + ->setId(42); + + $result[] = [ + [], $share, [], true + ]; + + + + return $result; + } + + /** + * @dataProvider dataFormatShare + * + * @param array $expects + * @param \OCP\Share\IShare $share + * @param array $users + * @param $exception + */ + public function testFormatShare(array $expects, \OCP\Share\IShare $share, array $users, $exception) { + $this->userManager->method('get')->will($this->returnValueMap($users)); + $this->urlGenerator->method('linkToRouteAbsolute') + ->with('files_sharing.sharecontroller.showShare', ['token' => 'myToken']) + ->willReturn('myLink'); + + + $this->rootFolder->method('getUserFolder')->with($share->getShareOwner())->will($this->returnSelf()); + $this->rootFolder->method('getRelativePath')->will($this->returnArgument(0)); + + try { + $result = $this->invokePrivate($this->ocs, 'formatShare', [$share]); + $this->assertFalse($exception); + $this->assertEquals($expects, $result); + } catch (NotFoundException $e) { + $this->assertTrue($exception); + } + } + + /** + * @return Share20OCS + */ + public function getOcsDisabledAPI() { + $shareManager = $this->getMockBuilder('OCP\Share\IManager') + ->disableOriginalConstructor() + ->getMock(); + $shareManager + ->expects($this->any()) + ->method('shareApiEnabled') + ->willReturn(false); + + return new Share20OCS( + $shareManager, + $this->groupManager, + $this->userManager, + $this->request, + $this->rootFolder, + $this->urlGenerator, + $this->currentUser, + $this->l + ); + } + + public function testGetShareApiDisabled() { + $ocs = $this->getOcsDisabledAPI(); + + $expected = new \OC_OCS_Result(null, 404, 'Share API is disabled'); + $result = $ocs->getShare('my:id'); + + $this->assertEquals($expected, $result); + } + + public function testDeleteShareApiDisabled() { + $ocs = $this->getOcsDisabledAPI(); + + $expected = new \OC_OCS_Result(null, 404, 'Share API is disabled'); + $result = $ocs->deleteShare('my:id'); + + $this->assertEquals($expected, $result); + } + + + public function testCreateShareApiDisabled() { + $ocs = $this->getOcsDisabledAPI(); + + $expected = new \OC_OCS_Result(null, 404, 'Share API is disabled'); + $result = $ocs->createShare(); + + $this->assertEquals($expected, $result); + } + + public function testGetSharesApiDisabled() { + $ocs = $this->getOcsDisabledAPI(); + + $expected = new \OC_OCS_Result(); + $result = $ocs->getShares(); + + $this->assertEquals($expected, $result); + } + + public function testUpdateShareApiDisabled() { + $ocs = $this->getOcsDisabledAPI(); + + $expected = new \OC_OCS_Result(null, 404, 'Share API is disabled'); + $result = $ocs->updateShare('my:id'); + + $this->assertEquals($expected, $result); + } +} diff --git a/apps/files_sharing/tests/API/ShareesTest.php b/apps/files_sharing/tests/API/ShareesTest.php new file mode 100644 index 00000000000..8a88e7126ee --- /dev/null +++ b/apps/files_sharing/tests/API/ShareesTest.php @@ -0,0 +1,1553 @@ + + * @author Joas Schilling + * @author Roeland Jago Douma + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests\API; + +use OCA\Files_Sharing\API\Sharees; +use OCA\Files_Sharing\Tests\TestCase; +use OCP\AppFramework\Http; +use OCP\Share; + +/** + * Class ShareesTest + * + * @group DB + * + * @package OCA\Files_Sharing\Tests\API + */ +class ShareesTest extends TestCase { + /** @var Sharees */ + 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 */ + protected $request; + + /** @var \OCP\Share\IManager|\PHPUnit_Framework_MockObject_MockObject */ + protected $shareManager; + + protected function setUp() { + parent::setUp(); + + $this->userManager = $this->getMockBuilder('OCP\IUserManager') + ->disableOriginalConstructor() + ->getMock(); + + $this->groupManager = $this->getMockBuilder('OCP\IGroupManager') + ->disableOriginalConstructor() + ->getMock(); + + $this->contactsManager = $this->getMockBuilder('OCP\Contacts\IManager') + ->disableOriginalConstructor() + ->getMock(); + + $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->sharees = new Sharees( + $this->groupManager, + $this->userManager, + $this->contactsManager, + $this->getMockBuilder('OCP\IConfig')->disableOriginalConstructor()->getMock(), + $this->session, + $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(), + $this->request, + $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(), + $this->shareManager + ); + } + + /** + * @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) { + $group = $this->getMockBuilder('OCP\IGroup') + ->disableOriginalConstructor() + ->getMock(); + + $group->expects($this->any()) + ->method('getGID') + ->willReturn($gid); + + 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], + [ + 'test', false, true, + [$this->getGroupMock('test1')], + [], + [], + [['label' => 'test1', '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')); + } + + public function dataGetRemote() { + return [ + ['test', [], true, [], [], true], + ['test', [], false, [], [], true], + [ + 'test@remote', + [], + true, + [ + ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']], + ], + [], + true, + ], + [ + 'test@remote', + [], + false, + [ + ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']], + ], + [], + true, + ], + [ + 'test', + [ + [ + 'FN' => 'User3 @ Localhost', + ], + [ + 'FN' => 'User2 @ Localhost', + 'CLOUD' => [ + ], + ], + [ + 'FN' => 'User @ Localhost', + 'CLOUD' => [ + 'username@localhost', + ], + ], + ], + true, + [], + [ + ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']], + ], + true, + ], + [ + 'test', + [ + [ + 'FN' => 'User3 @ Localhost', + ], + [ + 'FN' => 'User2 @ Localhost', + 'CLOUD' => [ + ], + ], + [ + 'FN' => 'User @ Localhost', + 'CLOUD' => [ + 'username@localhost', + ], + ], + ], + false, + [], + [], + true, + ], + [ + 'test@remote', + [ + [ + 'FN' => 'User3 @ Localhost', + ], + [ + 'FN' => 'User2 @ Localhost', + 'CLOUD' => [ + ], + ], + [ + 'FN' => 'User @ Localhost', + 'CLOUD' => [ + 'username@localhost', + ], + ], + ], + true, + [ + ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']], + ], + [ + ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']], + ], + true, + ], + [ + 'test@remote', + [ + [ + 'FN' => 'User3 @ Localhost', + ], + [ + 'FN' => 'User2 @ Localhost', + 'CLOUD' => [ + ], + ], + [ + 'FN' => 'User @ Localhost', + 'CLOUD' => [ + 'username@localhost', + ], + ], + ], + false, + [ + ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']], + ], + [], + true, + ], + [ + 'username@localhost', + [ + [ + 'FN' => 'User3 @ Localhost', + ], + [ + 'FN' => 'User2 @ Localhost', + 'CLOUD' => [ + ], + ], + [ + 'FN' => 'User @ Localhost', + 'CLOUD' => [ + 'username@localhost', + ], + ], + ], + true, + [ + ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']], + ], + [], + true, + ], + [ + 'username@localhost', + [ + [ + 'FN' => 'User3 @ Localhost', + ], + [ + 'FN' => 'User2 @ Localhost', + 'CLOUD' => [ + ], + ], + [ + 'FN' => 'User @ Localhost', + 'CLOUD' => [ + 'username@localhost', + ], + ], + ], + false, + [ + ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']], + ], + [], + true, + ], + ]; + } + + /** + * @dataProvider dataGetRemote + * + * @param string $searchTerm + * @param array $contacts + * @param bool $shareeEnumeration + * @param array $exactExpected + * @param array $expected + * @param bool $reachedEnd + */ + public function testGetRemote($searchTerm, $contacts, $shareeEnumeration, $exactExpected, $expected, $reachedEnd) { + $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]); + $this->contactsManager->expects($this->any()) + ->method('search') + ->with($searchTerm, ['CLOUD', 'FN']) + ->willReturn($contacts); + + $this->invokePrivate($this->sharees, 'getRemote', [$searchTerm]); + $result = $this->invokePrivate($this->sharees, 'result'); + + $this->assertEquals($exactExpected, $result['exact']['remotes']); + $this->assertEquals($expected, $result['remotes']); + $this->assertCount((int) $reachedEnd, $this->invokePrivate($this->sharees, 'reachedEndFor')); + } + + public function dataSearch() { + $allTypes = [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE]; + + return [ + [[], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], + + // Test itemType + [[ + 'search' => '', + ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], + [[ + 'search' => 'foobar', + ], '', 'yes', true, 'foobar', null, $allTypes, 1, 200, false, true, true], + [[ + 'search' => 0, + ], '', 'yes', true, '0', null, $allTypes, 1, 200, false, true, true], + + // Test itemType + [[ + 'itemType' => '', + ], '', 'yes', true, '', '', $allTypes, 1, 200, false, true, true], + [[ + 'itemType' => 'folder', + ], '', 'yes', true, '', 'folder', $allTypes, 1, 200, false, true, true], + [[ + 'itemType' => 0, + ], '', 'yes', true, '', '0', $allTypes, 1, 200, false, true, true], + + // Test shareType + [[ + ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], + [[ + 'shareType' => 0, + ], '', 'yes', true, '', null, [0], 1, 200, false, true, true], + [[ + 'shareType' => '0', + ], '', 'yes', true, '', null, [0], 1, 200, false, true, true], + [[ + 'shareType' => 1, + ], '', 'yes', true, '', null, [1], 1, 200, false, true, true], + [[ + 'shareType' => 12, + ], '', 'yes', true, '', null, [], 1, 200, false, true, true], + [[ + 'shareType' => 'foobar', + ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], + [[ + 'shareType' => [0, 1, 2], + ], '', 'yes', true, '', null, [0, 1], 1, 200, false, true, true], + [[ + 'shareType' => [0, 1], + ], '', 'yes', true, '', null, [0, 1], 1, 200, false, true, true], + [[ + 'shareType' => $allTypes, + ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], + [[ + 'shareType' => $allTypes, + ], '', 'yes', false, '', null, [0, 1], 1, 200, false, true, true], + [[ + 'shareType' => $allTypes, + ], '', 'yes', true, '', null, [0, 6], 1, 200, false, true, false], + [[ + 'shareType' => $allTypes, + ], '', 'yes', false, '', null, [0], 1, 200, false, true, false], + + // Test pagination + [[ + 'page' => 1, + ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], + [[ + 'page' => 10, + ], '', 'yes', true, '', null, $allTypes, 10, 200, false, true, true], + + // Test perPage + [[ + 'perPage' => 1, + ], '', 'yes', true, '', null, $allTypes, 1, 1, false, true, true], + [[ + 'perPage' => 10, + ], '', 'yes', true, '', null, $allTypes, 1, 10, false, true, true], + + // Test $shareWithGroupOnly setting + [[], 'no', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], + [[], 'yes', 'yes', true, '', null, $allTypes, 1, 200, true, true, true], + + // Test $shareeEnumeration setting + [[], 'no', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], + [[], 'no', 'no', true, '', null, $allTypes, 1, 200, false, false, true], + + // Test keep case for search + [[ + 'search' => 'foo@example.com/ownCloud', + ], '', 'yes', true, 'foo@example.com/ownCloud', null, $allTypes, 1, 200, false, true, true], + ]; + } + + /** + * @dataProvider dataSearch + * + * @param array $getData + * @param string $apiSetting + * @param string $enumSetting + * @param bool $remoteSharingEnabled + * @param string $search + * @param string $itemType + * @param array $shareTypes + * @param int $page + * @param int $perPage + * @param bool $shareWithGroupOnly + * @param bool $shareeEnumeration + * @param bool $allowGroupSharing + */ + public function testSearch($getData, $apiSetting, $enumSetting, $remoteSharingEnabled, $search, $itemType, $shareTypes, $page, $perPage, $shareWithGroupOnly, $shareeEnumeration, $allowGroupSharing) { + $oldGet = $_GET; + $_GET = $getData; + + $config = $this->getMockBuilder('OCP\IConfig') + ->disableOriginalConstructor() + ->getMock(); + $config->expects($this->exactly(2)) + ->method('getAppValue') + ->with('core', $this->anything(), $this->anything()) + ->willReturnMap([ + ['core', 'shareapi_only_share_with_group_members', 'no', $apiSetting], + ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', $enumSetting], + ]); + + $this->shareManager->expects($this->once()) + ->method('allowGroupSharing') + ->willReturn($allowGroupSharing); + + $sharees = $this->getMockBuilder('\OCA\Files_Sharing\API\Sharees') + ->setConstructorArgs([ + $this->groupManager, + $this->userManager, + $this->contactsManager, + $config, + $this->session, + $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(), + $this->getMockBuilder('OCP\IRequest')->disableOriginalConstructor()->getMock(), + $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(), + $this->shareManager + ]) + ->setMethods(array('searchSharees', 'isRemoteSharingAllowed')) + ->getMock(); + $sharees->expects($this->once()) + ->method('searchSharees') + ->with($search, $itemType, $shareTypes, $page, $perPage) + ->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($shareTypes, $ishareTypes); + $this->assertSame($page, $ipage); + $this->assertSame($perPage, $iperPage); + return new \OC_OCS_Result([]); + }); + $sharees->expects($this->any()) + ->method('isRemoteSharingAllowed') + ->with($itemType) + ->willReturn($remoteSharingEnabled); + + /** @var \PHPUnit_Framework_MockObject_MockObject|\OCA\Files_Sharing\API\Sharees $sharees */ + $this->assertInstanceOf('\OC_OCS_Result', $sharees->search()); + + $this->assertSame($shareWithGroupOnly, $this->invokePrivate($sharees, 'shareWithGroupOnly')); + $this->assertSame($shareeEnumeration, $this->invokePrivate($sharees, 'shareeEnumeration')); + + $_GET = $oldGet; + } + + public function dataSearchInvalid() { + return [ + // Test invalid pagination + [[ + 'page' => 0, + ], 'Invalid page'], + [[ + 'page' => '0', + ], 'Invalid page'], + [[ + 'page' => -1, + ], 'Invalid page'], + + // Test invalid perPage + [[ + 'perPage' => 0, + ], 'Invalid perPage argument'], + [[ + 'perPage' => '0', + ], 'Invalid perPage argument'], + [[ + 'perPage' => -1, + ], 'Invalid perPage argument'], + ]; + } + + /** + * @dataProvider dataSearchInvalid + * + * @param array $getData + * @param string $message + */ + public function testSearchInvalid($getData, $message) { + $oldGet = $_GET; + $_GET = $getData; + + $config = $this->getMockBuilder('OCP\IConfig') + ->disableOriginalConstructor() + ->getMock(); + $config->expects($this->never()) + ->method('getAppValue'); + + $sharees = $this->getMockBuilder('\OCA\Files_Sharing\API\Sharees') + ->setConstructorArgs([ + $this->groupManager, + $this->userManager, + $this->contactsManager, + $config, + $this->session, + $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(), + $this->getMockBuilder('OCP\IRequest')->disableOriginalConstructor()->getMock(), + $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(), + $this->shareManager + ]) + ->setMethods(array('searchSharees', 'isRemoteSharingAllowed')) + ->getMock(); + $sharees->expects($this->never()) + ->method('searchSharees'); + $sharees->expects($this->never()) + ->method('isRemoteSharingAllowed'); + + /** @var \PHPUnit_Framework_MockObject_MockObject|\OCA\Files_Sharing\API\Sharees $sharees */ + $ocs = $sharees->search(); + $this->assertInstanceOf('\OC_OCS_Result', $ocs); + + $this->assertOCSError($ocs, $message); + + $_GET = $oldGet; + } + + public function dataIsRemoteSharingAllowed() { + return [ + ['file', true], + ['folder', true], + ['', false], + ['contacts', false], + ]; + } + + /** + * @dataProvider dataIsRemoteSharingAllowed + * + * @param string $itemType + * @param bool $expected + */ + public function testIsRemoteSharingAllowed($itemType, $expected) { + $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, [], [], [], + [ + 'exact' => ['users' => [], 'groups' => [], 'remotes' => []], + 'users' => [], + 'groups' => [], + 'remotes' => [], + ], false], + ['test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE], 1, 2, false, [], [], [], + [ + 'exact' => ['users' => [], 'groups' => [], 'remotes' => []], + 'users' => [], + 'groups' => [], + 'remotes' => [], + ], 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']], + ], [ + ['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']], + ], + [ + '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', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_REMOTE], 1, 2, false, [ + ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']], + ], null, [ + ['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']], + ], + [ + 'exact' => ['users' => [], 'groups' => [], 'remotes' => []], + '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']], + ], + ], 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' => []], + 'users' => [ + ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']], + ], + 'groups' => [], + 'remotes' => [], + ], 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' => []], + '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' => [], + ], 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\API\Sharees $sharees */ + $sharees = $this->getMockBuilder('\OCA\Files_Sharing\API\Sharees') + ->setConstructorArgs([ + $this->groupManager, + $this->userManager, + $this->contactsManager, + $this->getMockBuilder('OCP\IConfig')->disableOriginalConstructor()->getMock(), + $this->session, + $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(), + $this->getMockBuilder('OCP\IRequest')->disableOriginalConstructor()->getMock(), + $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(), + $this->shareManager + ]) + ->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) + ->willReturnCallback(function() use ($sharees, $mockedRemotesResult) { + $result = $this->invokePrivate($sharees, 'result'); + $result['remotes'] = $mockedRemotesResult; + $this->invokePrivate($sharees, 'result', [$result]); + }); + + /** @var \OC_OCS_Result $ocs */ + $ocs = $this->invokePrivate($sharees, 'searchSharees', [$searchTerm, $itemType, $shareTypes, $page, $perPage, $shareWithGroupOnly]); + $this->assertInstanceOf('\OC_OCS_Result', $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']); + } + } + + public function testSearchShareesNoItemType() { + /** @var \OC_OCS_Result $ocs */ + $ocs = $this->invokePrivate($this->sharees, 'searchSharees', ['', null, [], [], 0, 0, false]); + $this->assertInstanceOf('\OC_OCS_Result', $ocs); + + $this->assertOCSError($ocs, 'Missing itemType'); + } + + public function dataGetPaginationLink() { + return [ + [1, '/ocs/v1.php', ['perPage' => 2], '; rel="next"'], + [10, '/ocs/v2.php', ['perPage' => 2], '; rel="next"'], + ]; + } + + /** + * @dataProvider dataGetPaginationLink + * + * @param int $page + * @param string $scriptName + * @param array $params + * @param array $expected + */ + public function testGetPaginationLink($page, $scriptName, $params, $expected) { + $this->request->expects($this->once()) + ->method('getScriptName') + ->willReturn($scriptName); + + $this->assertEquals($expected, $this->invokePrivate($this->sharees, 'getPaginationLink', [$page, $params])); + } + + public function dataIsV2() { + return [ + ['/ocs/v1.php', false], + ['/ocs/v2.php', true], + ]; + } + + /** + * @dataProvider dataIsV2 + * + * @param string $scriptName + * @param bool $expected + */ + public function testIsV2($scriptName, $expected) { + $this->request->expects($this->once()) + ->method('getScriptName') + ->willReturn($scriptName); + + $this->assertEquals($expected, $this->invokePrivate($this->sharees, 'isV2')); + } + + /** + * @param \OC_OCS_Result $ocs + * @param string $message + */ + protected function assertOCSError(\OC_OCS_Result $ocs, $message) { + $this->assertSame(Http::STATUS_BAD_REQUEST, $ocs->getStatusCode(), 'Expected status code 400'); + $this->assertSame([], $ocs->getData(), 'Expected that no data is send'); + + $meta = $ocs->getMeta(); + $this->assertNotEmpty($meta); + $this->assertArrayHasKey('message', $meta); + $this->assertSame($message, $meta['message']); + } + + /** + * @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/apps/files_sharing/tests/ActivityTest.php b/apps/files_sharing/tests/ActivityTest.php new file mode 100644 index 00000000000..2894d485aca --- /dev/null +++ b/apps/files_sharing/tests/ActivityTest.php @@ -0,0 +1,80 @@ + + * @author Joas Schilling + * @author Morris Jobke + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +/** + * Class ActivityTest + * + * @group DB + * + * @package OCA\Files_Sharing\Tests + */ +class ActivityTest extends TestCase { + + /** + * @var \OCA\Files_Sharing\Activity + */ + private $activity; + + protected function setUp() { + parent::setUp(); + $this->activity = new \OCA\Files_Sharing\Activity( + $this->getMockBuilder('OCP\L10N\IFactory') + ->disableOriginalConstructor() + ->getMock(), + $this->getMockBuilder('OCP\IURLGenerator') + ->disableOriginalConstructor() + ->getMock(), + $this->getMockBuilder('OCP\Activity\IManager') + ->disableOriginalConstructor() + ->getMock() + ); + } + + /** + * @dataProvider dataTestGetDefaultType + */ + public function testGetDefaultTypes($method, $expectedResult) { + $result = $this->activity->getDefaultTypes($method); + + if (is_array($expectedResult)) { + $this->assertSame(count($expectedResult), count($result)); + foreach ($expectedResult as $key => $expected) { + $this->assertSame($expected, $result[$key]); + } + } else { + $this->assertSame($expectedResult, $result); + } + + } + + public function dataTestGetDefaultType() { + return array( + array('email', array(\OCA\Files_Sharing\Activity::TYPE_SHARED, \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE)), + array('stream', array(\OCA\Files_Sharing\Activity::TYPE_SHARED, \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::TYPE_PUBLIC_LINKS)), + ); + } + +} diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php new file mode 100644 index 00000000000..3a2d42a646f --- /dev/null +++ b/apps/files_sharing/tests/ApiTest.php @@ -0,0 +1,1598 @@ + + * @author Joas Schilling + * @author Morris Jobke + * @author Robin Appelman + * @author Robin McCorkell + * @author Roeland Jago Douma + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +/** + * Class ApiTest + * + * @group DB + */ +class ApiTest extends TestCase { + + const TEST_FOLDER_NAME = '/folder_share_api_test'; + + private static $tempStorage; + + /** @var \OCP\Files\Folder */ + private $userFolder; + + protected function setUp() { + parent::setUp(); + + \OC::$server->getAppConfig()->setValue('core', 'shareapi_exclude_groups', 'no'); + \OC::$server->getAppConfig()->setValue('core', 'shareapi_expire_after_n_days', '7'); + + $this->folder = self::TEST_FOLDER_NAME; + $this->subfolder = '/subfolder_share_api_test'; + $this->subsubfolder = '/subsubfolder_share_api_test'; + + $this->filename = '/share-api-test.txt'; + + // save file with content + $this->view->file_put_contents($this->filename, $this->data); + $this->view->mkdir($this->folder); + $this->view->mkdir($this->folder . $this->subfolder); + $this->view->mkdir($this->folder . $this->subfolder . $this->subsubfolder); + $this->view->file_put_contents($this->folder.$this->filename, $this->data); + $this->view->file_put_contents($this->folder . $this->subfolder . $this->filename, $this->data); + + $this->userFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1); + } + + protected function tearDown() { + if($this->view instanceof \OC\Files\View) { + $this->view->unlink($this->filename); + $this->view->deleteAll($this->folder); + } + + self::$tempStorage = null; + + parent::tearDown(); + } + + /** + * @param array $data + * @return \OCP\IRequest + */ + private function createRequest(array $data) { + $request = $this->getMock('\OCP\IRequest'); + $request->method('getParam') + ->will($this->returnCallback(function($param, $default = null) use ($data) { + if (isset($data[$param])) { + return $data[$param]; + } + return $default; + })); + return $request; + } + + /** + * @param \OCP\IRequest $request + * @param string $userId The userId of the caller + * @return \OCA\Files_Sharing\API\Share20OCS + */ + private function createOCS($request, $userId) { + $currentUser = \OC::$server->getUserManager()->get($userId); + + $l = $this->getMock('\OCP\IL10N'); + $l->method('t') + ->will($this->returnCallback(function($text, $parameters = []) { + return vsprintf($text, $parameters); + })); + + return new \OCA\Files_Sharing\API\Share20OCS( + $this->shareManager, + \OC::$server->getGroupManager(), + \OC::$server->getUserManager(), + $request, + \OC::$server->getRootFolder(), + \OC::$server->getURLGenerator(), + $currentUser, + $l + ); + } + + /** + * @medium + */ + function testCreateShareUserFile() { + // simulate a post request + $data['path'] = $this->filename; + $data['shareWith'] = self::TEST_FILES_SHARING_API_USER2; + $data['shareType'] = \OCP\Share::SHARE_TYPE_USER; + + $request = $this->createRequest($data); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + + $this->assertTrue($result->succeeded()); + $data = $result->getData(); + $this->assertEquals(19, $data['permissions']); + $this->assertEmpty($data['expiration']); + + $this->shareManager->getShareById('ocinternal:'.$data['id']); + + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->deleteShare($data['id']); + $this->assertTrue($result->succeeded()); + } + + function testCreateShareUserFolder() { + // simulate a post request + $data['path'] = $this->folder; + $data['shareWith'] = self::TEST_FILES_SHARING_API_USER2; + $data['shareType'] = \OCP\Share::SHARE_TYPE_USER; + + $request = $this->createRequest($data); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + + $this->assertTrue($result->succeeded()); + $data = $result->getData(); + $this->assertEquals(31, $data['permissions']); + $this->assertEmpty($data['expiration']); + + $this->shareManager->getShareById('ocinternal:'.$data['id']); + + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->deleteShare($data['id']); + $this->assertTrue($result->succeeded()); + } + + + function testCreateShareGroupFile() { + // simulate a post request + $data['path'] = $this->filename; + $data['shareWith'] = self::TEST_FILES_SHARING_API_GROUP1; + $data['shareType'] = \OCP\Share::SHARE_TYPE_GROUP; + + $request = $this->createRequest($data); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + + $this->assertTrue($result->succeeded()); + $data = $result->getData(); + $this->assertEquals(19, $data['permissions']); + $this->assertEmpty($data['expiration']); + + $this->shareManager->getShareById('ocinternal:'.$data['id']); + + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->deleteShare($data['id']); + $this->assertTrue($result->succeeded()); + } + + function testCreateShareGroupFolder() { + // simulate a post request + $data['path'] = $this->folder; + $data['shareWith'] = self::TEST_FILES_SHARING_API_GROUP1; + $data['shareType'] = \OCP\Share::SHARE_TYPE_GROUP; + + $request = $this->createRequest($data); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + + $this->assertTrue($result->succeeded()); + $data = $result->getData(); + $this->assertEquals(31, $data['permissions']); + $this->assertEmpty($data['expiration']); + + $this->shareManager->getShareById('ocinternal:'.$data['id']); + + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->deleteShare($data['id']); + $this->assertTrue($result->succeeded()); + } + + public function testCreateShareLink() { + // simulate a post request + $data['path'] = $this->folder; + $data['shareType'] = \OCP\Share::SHARE_TYPE_LINK; + + $request = $this->createRequest($data); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + + // check if API call was successful + $this->assertTrue($result->succeeded()); + + $data = $result->getData(); + $this->assertEquals(1, $data['permissions']); + $this->assertEmpty($data['expiration']); + $this->assertTrue(is_string($data['token'])); + + // check for correct link + $url = \OC::$server->getURLGenerator()->getAbsoluteURL('/index.php/s/' . $data['token']); + $this->assertEquals($url, $data['url']); + + $this->shareManager->getShareById('ocinternal:'.$data['id']); + + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->deleteShare($data['id']); + $this->assertTrue($result->succeeded()); + } + + public function testCreateShareLinkPublicUpload() { + // simulate a post request + $data['path'] = $this->folder; + $data['shareType'] = \OCP\Share::SHARE_TYPE_LINK; + $data['publicUpload'] = 'true'; + + $request = $this->createRequest($data); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + + // check if API call was successful + $this->assertTrue($result->succeeded()); + + $data = $result->getData(); + $this->assertEquals(7, $data['permissions']); + $this->assertEmpty($data['expiration']); + $this->assertTrue(is_string($data['token'])); + + // check for correct link + $url = \OC::$server->getURLGenerator()->getAbsoluteURL('/index.php/s/' . $data['token']); + $this->assertEquals($url, $data['url']); + + $this->shareManager->getShareById('ocinternal:'.$data['id']); + + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->deleteShare($data['id']); + $this->assertTrue($result->succeeded()); + } + + function testEnfoceLinkPassword() { + + $appConfig = \OC::$server->getAppConfig(); + $appConfig->setValue('core', 'shareapi_enforce_links_password', 'yes'); + + // don't allow to share link without a password + $data['path'] = $this->folder; + $data['shareType'] = \OCP\Share::SHARE_TYPE_LINK; + + $request = $this->createRequest($data); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + $this->assertFalse($result->succeeded()); + + // don't allow to share link without a empty password + $data = []; + $data['path'] = $this->folder; + $data['shareType'] = \OCP\Share::SHARE_TYPE_LINK; + $data['password'] = ''; + + $request = $this->createRequest($data); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + $this->assertFalse($result->succeeded()); + + // share with password should succeed + $data = []; + $data['path'] = $this->folder; + $data['shareType'] = \OCP\Share::SHARE_TYPE_LINK; + $data['password'] = 'foo'; + + $request = $this->createRequest($data); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + $this->assertTrue($result->succeeded()); + + $data = $result->getData(); + + // setting new password should succeed + $data2 = [ + 'password' => 'bar', + ]; + $request = $this->createRequest($data2); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->updateShare($data['id']); + $this->assertTrue($result->succeeded()); + + // removing password should fail + $data2 = [ + 'password' => '', + ]; + $request = $this->createRequest($data2); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->updateShare($data['id']); + $this->assertFalse($result->succeeded()); + + // cleanup + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->deleteShare($data['id']); + $this->assertTrue($result->succeeded()); + + $appConfig->setValue('core', 'shareapi_enforce_links_password', 'no'); + } + + /** + * @medium + */ + function testSharePermissions() { + // sharing file to a user should work if shareapi_exclude_groups is set + // to no + \OC::$server->getAppConfig()->setValue('core', 'shareapi_exclude_groups', 'no'); + $post['path'] = $this->filename; + $post['shareWith'] = self::TEST_FILES_SHARING_API_USER2; + $post['shareType'] = \OCP\Share::SHARE_TYPE_USER; + + $request = $this->createRequest($post); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + + $this->assertTrue($result->succeeded()); + $data = $result->getData(); + + $this->shareManager->getShareById('ocinternal:'.$data['id']); + + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->deleteShare($data['id']); + $this->assertTrue($result->succeeded()); + + // exclude groups, but not the group the user belongs to. Sharing should still work + \OC::$server->getAppConfig()->setValue('core', 'shareapi_exclude_groups', 'yes'); + \OC::$server->getAppConfig()->setValue('core', 'shareapi_exclude_groups_list', 'admin,group1,group2'); + + $post = []; + $post['path'] = $this->filename; + $post['shareWith'] = self::TEST_FILES_SHARING_API_USER2; + $post['shareType'] = \OCP\Share::SHARE_TYPE_USER; + + $request = $this->createRequest($post); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + + $this->assertTrue($result->succeeded()); + $data = $result->getData(); + + $this->shareManager->getShareById('ocinternal:' . $data['id']); + + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->deleteShare($data['id']); + $this->assertTrue($result->succeeded()); + + // now we exclude the group the user belongs to ('group'), sharing should fail now + \OC::$server->getAppConfig()->setValue('core', 'shareapi_exclude_groups_list', 'admin,group'); + + $post = []; + $post['path'] = $this->filename; + $post['shareWith'] = self::TEST_FILES_SHARING_API_USER2; + $post['shareType'] = \OCP\Share::SHARE_TYPE_USER; + + $request = $this->createRequest($post); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + + // cleanup + \OC::$server->getAppConfig()->setValue('core', 'shareapi_exclude_groups', 'no'); + \OC::$server->getAppConfig()->setValue('core', 'shareapi_exclude_groups_list', ''); + } + + + /** + * @medium + */ + function testGetAllShares() { + $node = $this->userFolder->get($this->filename); + + $share = $this->shareManager->newShare(); + $share->setNode($node) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(19); + + $share = $this->shareManager->createShare($share); + + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->getShares(); + + $this->assertTrue($result->succeeded()); + $this->assertTrue(count($result->getData()) === 1); + + $this->shareManager->deleteShare($share); + } + + function testGetAllSharesWithMe() { + $node1 = $this->userFolder->get($this->filename); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(19); + $share1 = $this->shareManager->createShare($share1); + + $node2 = $this->userFolder->get($this->folder); + $share2 = $this->shareManager->newShare(); + $share2->setNode($node2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(31); + $share2 = $this->shareManager->createShare($share2); + + $request = $this->createRequest(['shared_with_me' => 'true']); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); + $result = $ocs->getShares(); + + $this->assertTrue($result->succeeded()); + $this->assertTrue(count($result->getData()) === 2); + + $this->shareManager->deleteShare($share1); + $this->shareManager->deleteShare($share2); + } + + /** + * @medium + */ + function testPublicLinkUrl() { + // simulate a post request + $post['path'] = $this->folder; + $post['shareType'] = \OCP\Share::SHARE_TYPE_LINK; + + $request = $this->createRequest($post); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + $this->assertTrue($result->succeeded()); + + $data = $result->getData(); + + // check if we have a token + $this->assertTrue(is_string($data['token'])); + $id = $data['id']; + + // check for correct link + $url = \OC::$server->getURLGenerator()->getAbsoluteURL('/index.php/s/' . $data['token']); + $this->assertEquals($url, $data['url']); + + // check for link in getall shares + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->getShares(); + $this->assertTrue($result->succeeded()); + + $data = $result->getData(); + $this->assertEquals($url, current($data)['url']); + + // check for path + $request = $this->createRequest(['path' => $this->folder]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->getShares(); + $this->assertTrue($result->succeeded()); + + $data = $result->getData(); + $this->assertEquals($url, current($data)['url']); + + // check in share id + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->getShare($id); + $this->assertTrue($result->succeeded()); + + $data = $result->getData(); + $this->assertEquals($url, current($data)['url']); + + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->deleteShare($id); + $this->assertTrue($result->succeeded()); + } + + /** + * @medium + * @depends testCreateShareUserFile + * @depends testCreateShareLink + */ + function testGetShareFromSource() { + $node = $this->userFolder->get($this->filename); + $share = $this->shareManager->newShare(); + $share->setNode($node) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(19); + $share1 = $this->shareManager->createShare($share); + + $share = $this->shareManager->newShare(); + $share->setNode($node) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPermissions(1); + $share2 = $this->shareManager->createShare($share); + + $request = $this->createRequest(['path' => $this->filename]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->getShares(); + $this->assertTrue($result->succeeded()); + + // test should return one share created from testCreateShare() + $this->assertTrue(count($result->getData()) === 2); + + $this->shareManager->deleteShare($share1); + $this->shareManager->deleteShare($share2); + } + + /** + * @medium + * @depends testCreateShareUserFile + * @depends testCreateShareLink + */ + function testGetShareFromSourceWithReshares() { + $node = $this->userFolder->get($this->filename); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(19); + $share1 = $this->shareManager->createShare($share1); + + $share2 = $this->shareManager->newShare(); + $share2->setNode($node) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER3) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(19); + $share2 = $this->shareManager->createShare($share2); + + $request = $this->createRequest(['path' => $this->filename]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->getShares(); + $this->assertTrue($result->succeeded()); + + // test should return one share + $this->assertTrue(count($result->getData()) === 1); + + // now also ask for the reshares + $request = $this->createRequest(['path' => $this->filename, 'reshares' => 'true']); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->getShares(); + $this->assertTrue($result->succeeded()); + + $this->assertTrue($result->succeeded()); + + // now we should get two shares, the initial share and the reshare + $this->assertCount(2, $result->getData()); + + $this->shareManager->deleteShare($share1); + $this->shareManager->deleteShare($share2); + } + + /** + * @medium + * @depends testCreateShareUserFile + */ + function testGetShareFromId() { + $node = $this->userFolder->get($this->filename); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(19); + $share1 = $this->shareManager->createShare($share1); + + // call getShare() with share ID + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->getShare($share1->getId()); + $this->assertTrue($result->succeeded()); + + // test should return one share created from testCreateShare() + $this->assertEquals(1, count($result->getData())); + + $this->shareManager->deleteShare($share1); + } + + /** + * @medium + */ + function testGetShareFromFolder() { + $node1 = $this->userFolder->get($this->filename); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(19); + $share1 = $this->shareManager->createShare($share1); + + $node2 = $this->userFolder->get($this->folder.'/'.$this->filename); + $share2 = $this->shareManager->newShare(); + $share2->setNode($node2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPermissions(1); + $share2 = $this->shareManager->createShare($share2); + + + $request = $this->createRequest(['path' => $this->folder, 'subfiles' => 'true']); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->getShares(); + $this->assertTrue($result->succeeded()); + + // test should return one share within $this->folder + $this->assertTrue(count($result->getData()) === 1); + + $this->shareManager->deleteShare($share1); + $this->shareManager->deleteShare($share2); + } + + function testGetShareFromFolderWithFile() { + $node1 = $this->userFolder->get($this->filename); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(19); + $share1 = $this->shareManager->createShare($share1); + + $request = $this->createRequest(['path' => $this->filename, 'subfiles' => 'true']); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->getShares(); + + $this->assertFalse($result->succeeded()); + $this->assertEquals(400, $result->getStatusCode()); + $this->assertEquals('Not a directory', $result->getMeta()['message']); + + $this->shareManager->deleteShare($share1); + } + + /** + * share a folder, than reshare a file within the shared folder and check if we construct the correct path + * @medium + */ + function testGetShareFromFolderReshares() { + $node1 = $this->userFolder->get($this->folder); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(31); + $share1 = $this->shareManager->createShare($share1); + + $node2 = $this->userFolder->get($this->folder.'/'.$this->filename); + $share2 = $this->shareManager->newShare(); + $share2->setNode($node2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPermissions(1); + $share2 = $this->shareManager->createShare($share2); + + $node3 = $this->userFolder->get($this->folder.'/'.$this->subfolder.'/'.$this->filename); + $share3 = $this->shareManager->newShare(); + $share3->setNode($node3) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPermissions(1); + $share3 = $this->shareManager->createShare($share3); + + $testValues=array( + array('query' => $this->folder, + 'expectedResult' => $this->folder . $this->filename), + array('query' => $this->folder . $this->subfolder, + 'expectedResult' => $this->folder . $this->subfolder . $this->filename), + ); + foreach ($testValues as $value) { + + $request = $this->createRequest(['path' => $value['query'], 'subfiles' => 'true']); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); + $result = $ocs->getShares(); + $this->assertTrue($result->succeeded()); + + // test should return one share within $this->folder + $data = $result->getData(); + + $this->assertEquals($value['expectedResult'], $data[0]['path']); + } + + // cleanup + $this->shareManager->deleteShare($share1); + $this->shareManager->deleteShare($share2); + $this->shareManager->deleteShare($share3); + } + + /** + * reshare a sub folder and check if we get the correct path + * @medium + */ + function testGetShareFromSubFolderReShares() { + $node1 = $this->userFolder->get($this->folder . $this->subfolder); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(31); + $share1 = $this->shareManager->createShare($share1); + + $node2 = \OC::$server->getRootFolder()->getUserFolder(self::TEST_FILES_SHARING_API_USER2)->get($this->subfolder); + $share2 = $this->shareManager->newShare(); + $share2->setNode($node2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPermissions(1); + $share2 = $this->shareManager->createShare($share2); + + $request = $this->createRequest(['path' => '/', 'subfiles' => 'true']); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); + $result = $ocs->getShares(); + $this->assertTrue($result->succeeded()); + + // test should return one share within $this->folder + $data = $result->getData(); + + // we should get exactly one result + $this->assertCount(1, $data); + + $expectedPath = $this->folder . $this->subfolder; + $this->assertEquals($expectedPath, $data[0]['path']); + + $this->shareManager->deleteShare($share2); + $this->shareManager->deleteShare($share1); + } + + /** + * test re-re-share of folder if the path gets constructed correctly + * @medium + */ + function testGetShareFromFolderReReShares() { + $node1 = $this->userFolder->get($this->folder . $this->subfolder); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(31); + $share1 = $this->shareManager->createShare($share1); + + $node2 = $this->userFolder->get($this->folder . $this->subfolder . $this->subsubfolder); + $share2 = $this->shareManager->newShare(); + $share2->setNode($node2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER3) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(31); + $share2 = $this->shareManager->createShare($share2); + + $share3 = $this->shareManager->newShare(); + $share3->setNode($node2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER3) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPermissions(1); + $share3 = $this->shareManager->createShare($share3); + + $request = $this->createRequest(['path' => '/', 'subfiles' => 'true']); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER3); + $result = $ocs->getShares(); + $this->assertTrue($result->succeeded()); + + // test should return one share within $this->folder + $data = $result->getData(); + + // we should get exactly one result + $this->assertCount(1, $data); + + $expectedPath = $this->folder . $this->subfolder . $this->subsubfolder; + $this->assertEquals($expectedPath, $data[0]['path']); + + $this->shareManager->deleteShare($share1); + $this->shareManager->deleteShare($share2); + $this->shareManager->deleteShare($share3); + } + + /** + * test multiple shared folder if the path gets constructed correctly + * @medium + */ + function testGetShareMultipleSharedFolder() { + $node1 = $this->userFolder->get($this->folder . $this->subfolder); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(31); + $share1 = $this->shareManager->createShare($share1); + + $node2 = $this->userFolder->get($this->folder); + $share2 = $this->shareManager->newShare(); + $share2->setNode($node2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(31); + $share2 = $this->shareManager->createShare($share2); + + $share3 = $this->shareManager->newShare(); + $share3->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPermissions(1); + $share3 = $this->shareManager->createShare($share3); + + $request = $this->createRequest(['path' => $this->subfolder]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); + $result1 = $ocs->getShares(); + $this->assertTrue($result1->succeeded()); + + // test should return one share within $this->folder + $data1 = $result1->getData(); + $this->assertCount(1, $data1); + $s1 = reset($data1); + + $request = $this->createRequest(['path' => $this->folder.$this->subfolder]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); + $result2 = $ocs->getShares(); + $this->assertTrue($result2->succeeded()); + + // test should return one share within $this->folder + $data2 = $result2->getData(); + $this->assertCount(1, $data2); + $s2 = reset($data2); + + $this->assertEquals($this->folder.$this->subfolder, $s1['path']); + $this->assertEquals($this->folder.$this->subfolder, $s2['path']); + + $this->shareManager->deleteShare($share1); + $this->shareManager->deleteShare($share2); + $this->shareManager->deleteShare($share3); + } + + /** + * test re-re-share of folder if the path gets constructed correctly + * @medium + */ + function testGetShareFromFileReReShares() { + $node1 = $this->userFolder->get($this->folder . $this->subfolder); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(31); + $share1 = $this->shareManager->createShare($share1); + + $user2Folder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER2); + $node2 = $user2Folder->get($this->subfolder . $this->filename); + $share2 = $this->shareManager->newShare(); + $share2->setNode($node2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER3) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(19); + $share2 = $this->shareManager->createShare($share2); + + $user3Folder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER3); + $node3 = $user3Folder->get($this->filename); + $share3 = $this->shareManager->newShare(); + $share3->setNode($node3) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER3) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPermissions(1); + $share3 = $this->shareManager->createShare($share3); + + $request = $this->createRequest(['path' => '/', 'subfiles' => 'true']); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER3); + $result = $ocs->getShares(); + $this->assertTrue($result->succeeded()); + + // test should return one share within $this->folder + $data = $result->getData(); + + // we should get exactly one result + $this->assertCount(1, $data); + + $expectedPath = $this->folder.$this->subfolder.$this->filename; + $this->assertEquals($expectedPath, $data[0]['path']); + + $this->shareManager->deleteShare($share1); + $this->shareManager->deleteShare($share2); + $this->shareManager->deleteShare($share3); + } + + /** + * @medium + */ + function testGetShareFromUnknownId() { + $request = $this->createRequest(['path' => '/', 'subfiles' => 'true']); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER3); + $result = $ocs->getShare(0); + $this->assertFalse($result->succeeded()); + + $this->assertEquals(404, $result->getStatusCode()); + $meta = $result->getMeta(); + $this->assertEquals('Wrong share ID, share doesn\'t exist', $meta['message']); + } + + /** + * @medium + * @depends testCreateShareUserFile + * @depends testCreateShareLink + */ + function testUpdateShare() { + $node1 = $this->userFolder->get($this->filename); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(19); + $share1 = $this->shareManager->createShare($share1); + + $share2 = $this->shareManager->newShare(); + $share2->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPermissions(1); + $share2 = $this->shareManager->createShare($share2); + + // update permissions + $params = array(); + $params['permissions'] = 1; + + $request = $this->createRequest(['permissions' => 1]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->updateShare($share1->getId()); + $this->assertTrue($result->succeeded()); + + $meta = $result->getMeta(); + $this->assertTrue($result->succeeded(), $meta['message']); + + $share1 = $this->shareManager->getShareById('ocinternal:' . $share1->getId()); + $this->assertEquals(1, $share1->getPermissions()); + + // update password for link share + $this->assertNull($share2->getPassword()); + + $request = $this->createRequest(['password' => 'foo']); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->updateShare($share2->getId()); + $this->assertTrue($result->succeeded()); + + $share2 = $this->shareManager->getShareById('ocinternal:' . $share2->getId()); + $this->assertNotNull($share2->getPassword()); + + $request = $this->createRequest(['password' => '']); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->updateShare($share2->getId()); + $this->assertTrue($result->succeeded()); + + $share2 = $this->shareManager->getShareById('ocinternal:' . $share2->getId()); + $this->assertNull($share2->getPassword()); + + $this->shareManager->deleteShare($share1); + $this->shareManager->deleteShare($share2); + } + + /** + * @medium + * @depends testCreateShareUserFile + */ + public function testUpdateShareInvalidPermissions() { + $node1 = $this->userFolder->get($this->filename); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(19); + $share1 = $this->shareManager->createShare($share1); + + $request = $this->createRequest(['permissions' => \OCP\Constants::PERMISSION_ALL]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->updateShare($share1->getId()); + + //Updating should fail with 400 + $this->assertFalse($result->succeeded()); + $this->assertEquals(400, $result->getStatusCode()); + + //Permissions should not have changed! + $share1 = $this->shareManager->getShareById('ocinternal:' . $share1->getId()); + $this->assertEquals(19, $share1->getPermissions()); + + $this->shareManager->deleteShare($share1); + } + + /** + * @medium + */ + function testUpdateShareUpload() { + $node1 = $this->userFolder->get($this->folder); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPermissions(1); + $share1 = $this->shareManager->createShare($share1); + + // update public upload + $request = $this->createRequest(['publicUpload' => 'true']); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->updateShare($share1->getId()); + $this->assertTrue($result->succeeded()); + + $share1 = $this->shareManager->getShareById($share1->getFullId()); + $this->assertEquals(7, $share1->getPermissions()); + + // cleanup + $this->shareManager->deleteShare($share1); + } + + /** + * @medium + */ + function testUpdateShareExpireDate() { + $node1 = $this->userFolder->get($this->folder); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPermissions(1); + $share1 = $this->shareManager->createShare($share1); + + $config = \OC::$server->getConfig(); + + // enforce expire date, by default 7 days after the file was shared + $config->setAppValue('core', 'shareapi_default_expire_date', 'yes'); + $config->setAppValue('core', 'shareapi_enforce_expire_date', 'yes'); + + $dateWithinRange = new \DateTime(); + $dateWithinRange->setTime(0,0,0); + $dateWithinRange->add(new \DateInterval('P5D')); + $dateOutOfRange = new \DateTime(); + $dateOutOfRange->setTime(0,0,0); + $dateOutOfRange->add(new \DateInterval('P8D')); + + // update expire date to a valid value + $request = $this->createRequest(['expireDate' => $dateWithinRange->format('Y-m-d')]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->updateShare($share1->getId()); + $this->assertTrue($result->succeeded()); + + $share1 = $this->shareManager->getShareById($share1->getFullId()); + + // date should be changed + $this->assertEquals($dateWithinRange, $share1->getExpirationDate()); + + // update expire date to a value out of range + $request = $this->createRequest(['expireDate' => $dateOutOfRange->format('Y-m-d')]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->updateShare($share1->getId()); + $this->assertFalse($result->succeeded()); + + $share1 = $this->shareManager->getShareById($share1->getFullId()); + + // date shouldn't be changed + $this->assertEquals($dateWithinRange, $share1->getExpirationDate()); + + // Try to remove expire date + $request = $this->createRequest(['expireDate' => '']); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->updateShare($share1->getId()); + $this->assertFalse($result->succeeded()); + + $share1 = $this->shareManager->getShareById($share1->getFullId()); + + + // date shouldn't be changed + $this->assertEquals($dateWithinRange, $share1->getExpirationDate()); + // cleanup + $config->setAppValue('core', 'shareapi_default_expire_date', 'no'); + $config->setAppValue('core', 'shareapi_enforce_expire_date', 'no'); + $this->shareManager->deleteShare($share1); + } + + /** + * @medium + * @depends testCreateShareUserFile + */ + function testDeleteShare() { + $node1 = $this->userFolder->get($this->filename); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(19); + $share1 = $this->shareManager->createShare($share1); + + $share2 = $this->shareManager->newShare(); + $share2->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPermissions(1); + $share2 = $this->shareManager->createShare($share1); + + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->deleteShare($share1->getId()); + $this->assertTrue($result->succeeded()); + + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->deleteShare($share2->getId()); + $this->assertTrue($result->succeeded()); + + $this->assertEmpty($this->shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER2, \OCP\Share::SHARE_TYPE_USER)); + $this->assertEmpty($this->shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER2, \OCP\Share::SHARE_TYPE_LINK)); + } + + /** + * test unshare of a reshared file + */ + function testDeleteReshare() { + $node1 = $this->userFolder->get($this->folder); + $share1 = $this->shareManager->newShare(); + $share1->setNode($node1) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setPermissions(31); + $share1 = $this->shareManager->createShare($share1); + + $user2folder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER2); + $node2 = $user2folder->get($this->folder.'/'.$this->filename); + $share2 = $this->shareManager->newShare(); + $share2->setNode($node2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) + ->setShareType(\OCP\Share::SHARE_TYPE_LINK) + ->setPermissions(1); + $share2 = $this->shareManager->createShare($share2); + + // test if we can unshare the link again + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); + $result = $ocs->deleteShare($share2->getId()); + $this->assertTrue($result->succeeded()); + + $this->shareManager->deleteShare($share1); + } + + /** + * share a folder which contains a share mount point, should be forbidden + */ + public function testShareFolderWithAMountPoint() { + // user 1 shares a folder with user2 + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $fileInfo = $this->view->getFileInfo($this->folder); + + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL + ); + + // user2 shares a file from the folder as link + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + $view = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); + $view->mkdir("localDir"); + + // move mount point to the folder "localDir" + $result = $view->rename($this->folder, 'localDir/'.$this->folder); + $this->assertTrue($result !== false); + + // try to share "localDir" + $fileInfo2 = $view->getFileInfo('localDir'); + + $this->assertTrue($fileInfo2 instanceof \OC\Files\FileInfo); + + $pass = true; + try { + $this->share( + \OCP\Share::SHARE_TYPE_USER, + 'localDir', + self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3, + \OCP\Constants::PERMISSION_ALL + ); + } catch (\Exception $e) { + $pass = false; + } + + $this->assertFalse($pass); + + //cleanup + + $result = $view->rename('localDir/' . $this->folder, $this->folder); + $this->assertTrue($result !== false); + $view->unlink('localDir'); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $this->shareManager->deleteShare($share); + } + + /** + * Post init mount points hook for mounting simulated ext storage + */ + public static function initTestMountPointsHook($data) { + if ($data['user'] === self::TEST_FILES_SHARING_API_USER1) { + \OC\Files\Filesystem::mount(self::$tempStorage, array(), '/' . self::TEST_FILES_SHARING_API_USER1 . '/files' . self::TEST_FOLDER_NAME); + } + } + + /** + * Tests mounting a folder that is an external storage mount point. + */ + public function testShareStorageMountPoint() { + self::$tempStorage = new \OC\Files\Storage\Temporary(array()); + self::$tempStorage->file_put_contents('test.txt', 'abcdef'); + self::$tempStorage->getScanner()->scan(''); + + // needed because the sharing code sometimes switches the user internally and mounts the user's + // storages. In our case the temp storage isn't mounted automatically, so doing it in the post hook + // (similar to how ext storage works) + \OCP\Util::connectHook('OC_Filesystem', 'post_initMountPoints', '\OCA\Files_Sharing\Tests\ApiTest', 'initTestMountPointsHook'); + + // logging in will auto-mount the temp storage for user1 as well + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $fileInfo = $this->view->getFileInfo($this->folder); + + // user 1 shares the mount point folder with user2 + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL + ); + + // user2: check that mount point name appears correctly + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + $view = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); + + $this->assertTrue($view->file_exists($this->folder)); + $this->assertTrue($view->file_exists($this->folder . '/test.txt')); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $this->shareManager->deleteShare($share); + + \OC_Hook::clear('OC_Filesystem', 'post_initMountPoints', '\OCA\Files_Sharing\Tests\ApiTest', 'initTestMountPointsHook'); + } + /** + * @expectedException \Exception + */ + public function testShareNonExisting() { + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $id = PHP_INT_MAX - 1; + \OCP\Share::shareItem('file', $id, \OCP\Share::SHARE_TYPE_LINK, self::TEST_FILES_SHARING_API_USER2, 31); + } + + /** + * @expectedException \Exception + */ + public function testShareNotOwner() { + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + \OC\Files\Filesystem::file_put_contents('foo.txt', 'bar'); + $info = \OC\Files\Filesystem::getFileInfo('foo.txt'); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + \OCP\Share::shareItem('file', $info->getId(), \OCP\Share::SHARE_TYPE_LINK, self::TEST_FILES_SHARING_API_USER2, 31); + } + + public function testDefaultExpireDate() { + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + // TODO drop this once all code paths use the DI version - otherwise + // the cache inside this config object is out of date because + // OC_Appconfig is used and bypasses this cache which lead to integrity + // constraint violations + $config = \OC::$server->getConfig(); + $config->deleteAppValue('core', 'shareapi_default_expire_date'); + $config->deleteAppValue('core', 'shareapi_enforce_expire_date'); + $config->deleteAppValue('core', 'shareapi_expire_after_n_days'); + + $config->setAppValue('core', 'shareapi_default_expire_date', 'yes'); + $config->setAppValue('core', 'shareapi_enforce_expire_date', 'yes'); + $config->setAppValue('core', 'shareapi_expire_after_n_days', '2'); + + // default expire date is set to 2 days + // the time when the share was created is set to 3 days in the past + // user defined expire date is set to +2 days from now on + // -> link should be already expired by the default expire date but the user + // share should still exists. + $now = time(); + $dateFormat = 'Y-m-d H:i:s'; + $shareCreated = $now - 3 * 24 * 60 * 60; + $expireDate = date($dateFormat, $now + 2 * 24 * 60 * 60); + + $info = \OC\Files\Filesystem::getFileInfo($this->filename); + $this->assertTrue($info instanceof \OC\Files\FileInfo); + + $result = \OCP\Share::shareItem('file', $info->getId(), \OCP\Share::SHARE_TYPE_LINK, null, \OCP\Constants::PERMISSION_READ); + $this->assertTrue(is_string($result)); + + $result = \OCP\Share::shareItem('file', $info->getId(), \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER2, 31); + $this->assertTrue($result); + + $result = \OCP\Share::setExpirationDate('file', $info->getId() , $expireDate, $now); + $this->assertTrue($result); + + //manipulate stime so that both shares are older then the default expire date + $statement = "UPDATE `*PREFIX*share` SET `stime` = ? WHERE `share_type` = ?"; + $query = \OCP\DB::prepare($statement); + $result = $query->execute(array($shareCreated, \OCP\Share::SHARE_TYPE_LINK)); + $this->assertSame(1, $result); + $query = \OCP\DB::prepare($statement); + $result = $query->execute(array($shareCreated, \OCP\Share::SHARE_TYPE_USER)); + $this->assertSame(1, $result); + + // now the link share should expire because of enforced default expire date + // the user share should still exist + $result = \OCP\Share::getItemShared('file', $info->getId()); + $this->assertTrue(is_array($result)); + $this->assertSame(1, count($result)); + $share = reset($result); + $this->assertSame(\OCP\Share::SHARE_TYPE_USER, $share['share_type']); + + //cleanup + $result = \OCP\Share::unshare('file', $info->getId(), \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER2); + $this->assertTrue($result); + $config->setAppValue('core', 'shareapi_default_expire_date', 'no'); + $config->setAppValue('core', 'shareapi_enforce_expire_date', 'no'); + + } + + public function datesProvider() { + $date = new \DateTime(); + $date->add(new \DateInterval('P5D')); + + return [ + [$date->format('Y-m-d'), true], + ['abc', false], + [$date->format('Y-m-d') . 'xyz', false], + ]; + } + + /** + * Make sure only ISO 8601 dates are accepted + * + * @dataProvider datesProvider + */ + public function testPublicLinkExpireDate($date, $valid) { + $request = $this->createRequest([ + 'path' => $this->folder, + 'shareType' => \OCP\Share::SHARE_TYPE_LINK, + 'expireDate' => $date, + ]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + + if ($valid === false) { + $this->assertFalse($result->succeeded()); + $this->assertEquals(404, $result->getStatusCode()); + $this->assertEquals('Invalid date, date format must be YYYY-MM-DD', $result->getMeta()['message']); + return; + } + + $this->assertTrue($result->succeeded()); + + $data = $result->getData(); + $this->assertTrue(is_string($data['token'])); + $this->assertEquals($date, substr($data['expiration'], 0, 10)); + + // check for correct link + $url = \OC::$server->getURLGenerator()->getAbsoluteURL('/index.php/s/' . $data['token']); + $this->assertEquals($url, $data['url']); + + $share = $this->shareManager->getShareById('ocinternal:'.$data['id']); + + $this->assertEquals($date, $share->getExpirationDate()->format('Y-m-d')); + + $this->shareManager->deleteShare($share); + } + + public function testCreatePublicLinkExpireDateValid() { + $config = \OC::$server->getConfig(); + + // enforce expire date, by default 7 days after the file was shared + $config->setAppValue('core', 'shareapi_default_expire_date', 'yes'); + $config->setAppValue('core', 'shareapi_enforce_expire_date', 'yes'); + + $date = new \DateTime(); + $date->add(new \DateInterval('P5D')); + + $request = $this->createRequest([ + 'path' => $this->folder, + 'shareType' => \OCP\Share::SHARE_TYPE_LINK, + 'expireDate' => $date->format('Y-m-d'), + ]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + $this->assertTrue($result->succeeded()); + + $data = $result->getData(); + $this->assertTrue(is_string($data['token'])); + $this->assertEquals($date->format('Y-m-d') . ' 00:00:00', $data['expiration']); + + // check for correct link + $url = \OC::$server->getURLGenerator()->getAbsoluteURL('/index.php/s/' . $data['token']); + $this->assertEquals($url, $data['url']); + + $share = $this->shareManager->getShareById('ocinternal:'.$data['id']); + $date->setTime(0,0,0); + $this->assertEquals($date, $share->getExpirationDate()); + + $this->shareManager->deleteShare($share); + + $config->setAppValue('core', 'shareapi_default_expire_date', 'no'); + $config->setAppValue('core', 'shareapi_enforce_expire_date', 'no'); + } + + public function testCreatePublicLinkExpireDateInvalidFuture() { + $config = \OC::$server->getConfig(); + + // enforce expire date, by default 7 days after the file was shared + $config->setAppValue('core', 'shareapi_default_expire_date', 'yes'); + $config->setAppValue('core', 'shareapi_enforce_expire_date', 'yes'); + + $date = new \DateTime(); + $date->add(new \DateInterval('P8D')); + + $request = $this->createRequest([ + 'path' => $this->folder, + 'shareType' => \OCP\Share::SHARE_TYPE_LINK, + 'expireDate' => $date->format('Y-m-d'), + ]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + $this->assertFalse($result->succeeded()); + $this->assertEquals(404, $result->getStatusCode()); + $this->assertEquals('Cannot set expiration date more than 7 days in the future', $result->getMeta()['message']); + + $config->setAppValue('core', 'shareapi_default_expire_date', 'no'); + $config->setAppValue('core', 'shareapi_enforce_expire_date', 'no'); + } + + public function testCreatePublicLinkExpireDateInvalidPast() { + $config = \OC::$server->getConfig(); + + $date = new \DateTime(); + $date->sub(new \DateInterval('P8D')); + + $request = $this->createRequest([ + 'path' => $this->folder, + 'shareType' => \OCP\Share::SHARE_TYPE_LINK, + 'expireDate' => $date->format('Y-m-d'), + ]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + $this->assertFalse($result->succeeded()); + $this->assertEquals(404, $result->getStatusCode()); + $this->assertEquals('Expiration date is in the past', $result->getMeta()['message']); + + $config->setAppValue('core', 'shareapi_default_expire_date', 'no'); + $config->setAppValue('core', 'shareapi_enforce_expire_date', 'no'); + } + + /** + * test for no invisible shares + * See: https://github.com/owncloud/core/issues/22295 + */ + public function testInvisibleSharesUser() { + // simulate a post request + $request = $this->createRequest([ + 'path' => $this->folder, + 'shareWith' => self::TEST_FILES_SHARING_API_USER2, + 'shareType' => \OCP\Share::SHARE_TYPE_USER + ]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + $this->assertTrue($result->succeeded()); + $data = $result->getData(); + + $topId = $data['id']; + + $request = $this->createRequest([ + 'path' => $this->folder . $this->subfolder, + 'shareType' => \OCP\Share::SHARE_TYPE_LINK, + ]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); + $result = $ocs->createShare(); + $this->assertTrue($result->succeeded()); + + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->deleteShare($topId); + $this->assertTrue($result->succeeded()); + + $request = $this->createRequest([ + 'reshares' => 'true', + ]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->getShares(); + $this->assertTrue($result->succeeded()); + + $this->assertEmpty($result->getData()); + } + + /** + * test for no invisible shares + * See: https://github.com/owncloud/core/issues/22295 + */ + public function testInvisibleSharesGroup() { + // simulate a post request + $request = $this->createRequest([ + 'path' => $this->folder, + 'shareWith' => self::TEST_FILES_SHARING_API_GROUP1, + 'shareType' => \OCP\Share::SHARE_TYPE_GROUP + ]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->createShare(); + $this->assertTrue($result->succeeded()); + $data = $result->getData(); + + $topId = $data['id']; + + $request = $this->createRequest([ + 'path' => $this->folder . $this->subfolder, + 'shareType' => \OCP\Share::SHARE_TYPE_LINK, + ]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); + $result = $ocs->createShare(); + $this->assertTrue($result->succeeded()); + + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->deleteShare($topId); + $this->assertTrue($result->succeeded()); + + $request = $this->createRequest([ + 'reshares' => 'true', + ]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->getShares(); + $this->assertTrue($result->succeeded()); + + $this->assertEmpty($result->getData()); + } +} diff --git a/apps/files_sharing/tests/BackendTest.php b/apps/files_sharing/tests/BackendTest.php new file mode 100644 index 00000000000..81037115f7c --- /dev/null +++ b/apps/files_sharing/tests/BackendTest.php @@ -0,0 +1,111 @@ + + * @author Joas Schilling + * @author Morris Jobke + * @author Robin Appelman + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + + +/** + * Class BackendTest + * + * @group DB + */ +class BackendTest extends TestCase { + + const TEST_FOLDER_NAME = '/folder_share_api_test'; + + public $folder; + public $subfolder; + public $subsubfolder; + + protected function setUp() { + parent::setUp(); + + $this->folder = self::TEST_FOLDER_NAME; + $this->subfolder = '/subfolder_share_backend_test'; + $this->subsubfolder = '/subsubfolder_share_backend_test'; + + $this->filename = '/share-backend-test.txt'; + + // save file with content + $this->view->file_put_contents($this->filename, $this->data); + $this->view->mkdir($this->folder); + $this->view->mkdir($this->folder . $this->subfolder); + $this->view->mkdir($this->folder . $this->subfolder . $this->subsubfolder); + $this->view->file_put_contents($this->folder.$this->filename, $this->data); + $this->view->file_put_contents($this->folder . $this->subfolder . $this->filename, $this->data); + $this->view->file_put_contents($this->folder . $this->subfolder . $this->subsubfolder . $this->filename, $this->data); + } + + protected function tearDown() { + if ($this->view) { + $this->view->unlink($this->filename); + $this->view->deleteAll($this->folder); + } + + parent::tearDown(); + } + + function testGetParents() { + + $fileinfo1 = $this->view->getFileInfo($this->folder); + $fileinfo2 = $this->view->getFileInfo($this->folder . $this->subfolder . $this->subsubfolder); + $fileinfo3 = $this->view->getFileInfo($this->folder . $this->subfolder . $this->subsubfolder . $this->filename); + + $this->assertTrue(\OCP\Share::shareItem('folder', $fileinfo1['fileid'], \OCP\Share::SHARE_TYPE_USER, + self::TEST_FILES_SHARING_API_USER2, 31)); + $this->assertTrue(\OCP\Share::shareItem('folder', $fileinfo2['fileid'], \OCP\Share::SHARE_TYPE_USER, + self::TEST_FILES_SHARING_API_USER3, 31)); + + $backend = new \OC_Share_Backend_Folder(); + + $result = $backend->getParents($fileinfo3['fileid']); + $this->assertSame(2, count($result)); + + $count1 = 0; + $count2 = 0; + foreach($result as $r) { + if ($r['path'] === 'files' . $this->folder) { + $this->assertSame(ltrim($this->folder, '/'), $r['collection']['path']); + $count1++; + } elseif ($r['path'] === 'files' . $this->folder . $this->subfolder . $this->subsubfolder) { + $this->assertSame(ltrim($this->subsubfolder, '/'), $r['collection']['path']); + $count2++; + } else { + $this->assertTrue(false, 'unexpected result'); + } + } + + $this->assertSame(1, $count1); + $this->assertSame(1, $count2); + + $result1 = $backend->getParents($fileinfo3['fileid'], self::TEST_FILES_SHARING_API_USER3); + $this->assertSame(1, count($result1)); + $elemet = reset($result1); + $this->assertSame('files' . $this->folder . $this->subfolder . $this->subsubfolder ,$elemet['path']); + $this->assertSame(ltrim($this->subsubfolder, '/') ,$elemet['collection']['path']); + + } + +} diff --git a/apps/files_sharing/tests/CacheTest.php b/apps/files_sharing/tests/CacheTest.php new file mode 100644 index 00000000000..f34301c9618 --- /dev/null +++ b/apps/files_sharing/tests/CacheTest.php @@ -0,0 +1,525 @@ + + * @author Joas Schilling + * @author Jörn Friedrich Dreyer + * @author Morris Jobke + * @author Robin Appelman + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +/** + * Class CacheTest + * + * @group DB + */ +class CacheTest extends TestCase { + + /** + * @var \OC\Files\View + */ + public $user2View; + + /** @var \OC\Files\Cache\Cache */ + protected $ownerCache; + + /** @var \OC\Files\Cache\Cache */ + protected $sharedCache; + + /** @var \OC\Files\Storage\Storage */ + protected $ownerStorage; + + /** @var \OC\Files\Storage\Storage */ + protected $sharedStorage; + + /** @var \OCP\Share\IManager */ + protected $shareManager; + + protected function setUp() { + parent::setUp(); + + $this->shareManager = \OC::$server->getShareManager(); + + \OC_User::setDisplayName(self::TEST_FILES_SHARING_API_USER1, 'User One'); + \OC_User::setDisplayName(self::TEST_FILES_SHARING_API_USER2, 'User Two'); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $this->user2View = new \OC\Files\View('/'. self::TEST_FILES_SHARING_API_USER2 . '/files'); + + // prepare user1's dir structure + $this->view->mkdir('container'); + $this->view->mkdir('container/shareddir'); + $this->view->mkdir('container/shareddir/subdir'); + $this->view->mkdir('container/shareddir/emptydir'); + + $textData = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $this->view->file_put_contents('container/not shared.txt', $textData); + $this->view->file_put_contents('container/shared single file.txt', $textData); + $this->view->file_put_contents('container/shareddir/bar.txt', $textData); + $this->view->file_put_contents('container/shareddir/subdir/another.txt', $textData); + $this->view->file_put_contents('container/shareddir/subdir/another too.txt', $textData); + $this->view->file_put_contents('container/shareddir/subdir/not a text file.xml', ''); + + list($this->ownerStorage,) = $this->view->resolvePath(''); + $this->ownerCache = $this->ownerStorage->getCache(); + $this->ownerStorage->getScanner()->scan(''); + + // share "shareddir" with user2 + $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1); + + $node = $rootFolder->get('container/shareddir'); + $share = $this->shareManager->newShare(); + $share->setNode($node) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setPermissions(\OCP\Constants::PERMISSION_ALL); + $this->shareManager->createShare($share); + + $node = $rootFolder->get('container/shared single file.txt'); + $share = $this->shareManager->newShare(); + $share->setNode($node) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setPermissions(\OCP\Constants::PERMISSION_ALL & ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE)); + $this->shareManager->createShare($share); + + // login as user2 + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + // retrieve the shared storage + $secondView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2); + list($this->sharedStorage,) = $secondView->resolvePath('files/shareddir'); + $this->sharedCache = $this->sharedStorage->getCache(); + } + + protected function tearDown() { + if($this->sharedCache) { + $this->sharedCache->clear(); + } + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $shares = $this->shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER1, \OCP\Share::SHARE_TYPE_USER); + foreach ($shares as $share) { + $this->shareManager->deleteShare($share); + } + + $this->view->deleteAll('container'); + + $this->ownerCache->clear(); + + parent::tearDown(); + } + + function searchDataProvider() { + return array( + array('%another%', + array( + array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'), + array('name' => 'another.txt', 'path' => 'subdir/another.txt'), + ) + ), + array('%Another%', + array( + array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'), + array('name' => 'another.txt', 'path' => 'subdir/another.txt'), + ) + ), + array('%dir%', + array( + array('name' => 'emptydir', 'path' => 'emptydir'), + array('name' => 'subdir', 'path' => 'subdir'), + array('name' => 'shareddir', 'path' => ''), + ) + ), + array('%Dir%', + array( + array('name' => 'emptydir', 'path' => 'emptydir'), + array('name' => 'subdir', 'path' => 'subdir'), + array('name' => 'shareddir', 'path' => ''), + ) + ), + array('%txt%', + array( + array('name' => 'bar.txt', 'path' => 'bar.txt'), + array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'), + array('name' => 'another.txt', 'path' => 'subdir/another.txt'), + ) + ), + array('%Txt%', + array( + array('name' => 'bar.txt', 'path' => 'bar.txt'), + array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'), + array('name' => 'another.txt', 'path' => 'subdir/another.txt'), + ) + ), + array('%', + array( + array('name' => 'bar.txt', 'path' => 'bar.txt'), + array('name' => 'emptydir', 'path' => 'emptydir'), + array('name' => 'subdir', 'path' => 'subdir'), + array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'), + array('name' => 'another.txt', 'path' => 'subdir/another.txt'), + array('name' => 'not a text file.xml', 'path' => 'subdir/not a text file.xml'), + array('name' => 'shareddir', 'path' => ''), + ) + ), + array('%nonexistent%', + array( + ) + ), + ); + } + + /** + * we cannot use a dataProvider because that would cause the stray hook detection to remove the hooks + * that were added in setUpBeforeClass. + */ + function testSearch() { + foreach ($this->searchDataProvider() as $data) { + list($pattern, $expectedFiles) = $data; + + $results = $this->sharedStorage->getCache()->search($pattern); + + $this->verifyFiles($expectedFiles, $results); + } + + } + /** + * Test searching by mime type + */ + function testSearchByMime() { + $results = $this->sharedStorage->getCache()->searchByMime('text'); + $check = array( + array( + 'name' => 'bar.txt', + 'path' => 'bar.txt' + ), + array( + 'name' => 'another too.txt', + 'path' => 'subdir/another too.txt' + ), + array( + 'name' => 'another.txt', + 'path' => 'subdir/another.txt' + ), + ); + $this->verifyFiles($check, $results); + } + + /** + * Test searching by tag + */ + function testSearchByTag() { + $userId = \OC::$server->getUserSession()->getUser()->getUId(); + $id1 = $this->sharedCache->get('bar.txt')['fileid']; + $id2 = $this->sharedCache->get('subdir/another too.txt')['fileid']; + $id3 = $this->sharedCache->get('subdir/not a text file.xml')['fileid']; + $id4 = $this->sharedCache->get('subdir/another.txt')['fileid']; + $tagManager = \OC::$server->getTagManager()->load('files', null, null, $userId); + $tagManager->tagAs($id1, 'tag1'); + $tagManager->tagAs($id1, 'tag2'); + $tagManager->tagAs($id2, 'tag1'); + $tagManager->tagAs($id3, 'tag1'); + $tagManager->tagAs($id4, 'tag2'); + $results = $this->sharedStorage->getCache()->searchByTag('tag1', $userId); + $check = array( + array( + 'name' => 'bar.txt', + 'path' => 'bar.txt' + ), + array( + 'name' => 'another too.txt', + 'path' => 'subdir/another too.txt' + ), + array( + 'name' => 'not a text file.xml', + 'path' => 'subdir/not a text file.xml' + ), + ); + $this->verifyFiles($check, $results); + $tagManager->delete(array('tag1', 'tag2')); + } + + /** + * Test searching by tag for multiple sections of the tree + */ + function testSearchByTagTree() { + $userId = \OC::$server->getUserSession()->getUser()->getUId(); + $this->sharedStorage->mkdir('subdir/emptydir'); + $this->sharedStorage->mkdir('subdir/emptydir2'); + $this->ownerStorage->getScanner()->scan(''); + $allIds = array( + $this->sharedCache->get('')['fileid'], + $this->sharedCache->get('bar.txt')['fileid'], + $this->sharedCache->get('subdir/another too.txt')['fileid'], + $this->sharedCache->get('subdir/not a text file.xml')['fileid'], + $this->sharedCache->get('subdir/another.txt')['fileid'], + $this->sharedCache->get('subdir/emptydir')['fileid'], + $this->sharedCache->get('subdir/emptydir2')['fileid'], + ); + $tagManager = \OC::$server->getTagManager()->load('files', null, null, $userId); + foreach ($allIds as $id) { + $tagManager->tagAs($id, 'tag1'); + } + $results = $this->sharedStorage->getCache()->searchByTag('tag1', $userId); + $check = array( + array( + 'name' => 'shareddir', + 'path' => '' + ), + array( + 'name' => 'bar.txt', + 'path' => 'bar.txt' + ), + array( + 'name' => 'another.txt', + 'path' => 'subdir/another.txt' + ), + array( + 'name' => 'another too.txt', + 'path' => 'subdir/another too.txt' + ), + array( + 'name' => 'emptydir', + 'path' => 'subdir/emptydir' + ), + array( + 'name' => 'emptydir2', + 'path' => 'subdir/emptydir2' + ), + array( + 'name' => 'not a text file.xml', + 'path' => 'subdir/not a text file.xml' + ), + ); + $this->verifyFiles($check, $results); + $tagManager->delete(array('tag1')); + } + + function testGetFolderContentsInRoot() { + $results = $this->user2View->getDirectoryContent('/'); + + // we should get the shared items "shareddir" and "shared single file.txt" + // additional root will always contain the example file "welcome.txt", + // so this will be part of the result + $this->verifyFiles( + array( + array( + 'name' => 'welcome.txt', + 'path' => 'files/welcome.txt', + 'mimetype' => 'text/plain', + ), + array( + 'name' => 'shareddir', + 'path' => 'files/shareddir', + 'mimetype' => 'httpd/unix-directory', + 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, + 'displayname_owner' => 'User One', + ), + array( + 'name' => 'shared single file.txt', + 'path' => 'files/shared single file.txt', + 'mimetype' => 'text/plain', + 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, + 'displayname_owner' => 'User One', + ), + ), + $results + ); + } + + function testGetFolderContentsInSubdir() { + $results = $this->user2View->getDirectoryContent('/shareddir'); + + $this->verifyFiles( + array( + array( + 'name' => 'bar.txt', + 'path' => 'bar.txt', + 'mimetype' => 'text/plain', + 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, + 'displayname_owner' => 'User One', + ), + array( + 'name' => 'emptydir', + 'path' => 'emptydir', + 'mimetype' => 'httpd/unix-directory', + 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, + 'displayname_owner' => 'User One', + ), + array( + 'name' => 'subdir', + 'path' => 'subdir', + 'mimetype' => 'httpd/unix-directory', + 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, + 'displayname_owner' => 'User One', + ), + ), + $results + ); + } + + function testGetFolderContentsWhenSubSubdirShared() { + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1); + $node = $rootFolder->get('container/shareddir/subdir'); + $share = $this->shareManager->newShare(); + $share->setNode($node) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER3) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setPermissions(\OCP\Constants::PERMISSION_ALL); + $share = $this->shareManager->createShare($share); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER3); + + $thirdView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER3 . '/files'); + $results = $thirdView->getDirectoryContent('/subdir'); + + $this->verifyFiles( + array( + array( + 'name' => 'another too.txt', + 'path' => 'another too.txt', + 'mimetype' => 'text/plain', + 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, + 'displayname_owner' => 'User One', + ), + array( + 'name' => 'another.txt', + 'path' => 'another.txt', + 'mimetype' => 'text/plain', + 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, + 'displayname_owner' => 'User One', + ), + array( + 'name' => 'not a text file.xml', + 'path' => 'not a text file.xml', + 'mimetype' => 'application/xml', + 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, + 'displayname_owner' => 'User One', + ), + ), + $results + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $this->shareManager->deleteShare($share); + } + + /** + * Check if 'results' contains the expected 'examples' only. + * + * @param array $examples array of example files + * @param array $results array of files + */ + private function verifyFiles($examples, $results) { + $this->assertEquals(count($examples), count($results)); + + foreach ($examples as $example) { + foreach ($results as $key => $result) { + if ($result['name'] === $example['name']) { + $this->verifyKeys($example, $result); + unset($results[$key]); + break; + } + } + } + $this->assertEquals(array(), $results); + } + + /** + * verify if each value from the result matches the expected result + * @param array $example array with the expected results + * @param array $result array with the results + */ + private function verifyKeys($example, $result) { + foreach ($example as $key => $value) { + $this->assertEquals($value, $result[$key]); + } + } + + public function testGetPathByIdDirectShare() { + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + \OC\Files\Filesystem::file_put_contents('test.txt', 'foo'); + $info = \OC\Files\Filesystem::getFileInfo('test.txt'); + + $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1); + $node = $rootFolder->get('test.txt'); + $share = $this->shareManager->newShare(); + $share->setNode($node) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setPermissions(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE); + $this->shareManager->createShare($share); + + \OC_Util::tearDownFS(); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $this->assertTrue(\OC\Files\Filesystem::file_exists('/test.txt')); + list($sharedStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/test.txt'); + /** + * @var \OC\Files\Storage\Shared $sharedStorage + */ + + $sharedCache = $sharedStorage->getCache(); + $this->assertEquals('', $sharedCache->getPathById($info->getId())); + } + + public function testGetPathByIdShareSubFolder() { + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + \OC\Files\Filesystem::mkdir('foo'); + \OC\Files\Filesystem::mkdir('foo/bar'); + \OC\Files\Filesystem::touch('foo/bar/test.txt'); + $folderInfo = \OC\Files\Filesystem::getFileInfo('foo'); + $fileInfo = \OC\Files\Filesystem::getFileInfo('foo/bar/test.txt'); + + $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1); + $node = $rootFolder->get('foo'); + $share = $this->shareManager->newShare(); + $share->setNode($node) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setPermissions(\OCP\Constants::PERMISSION_ALL); + $this->shareManager->createShare($share); + \OC_Util::tearDownFS(); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $this->assertTrue(\OC\Files\Filesystem::file_exists('/foo')); + list($sharedStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/foo'); + /** + * @var \OC\Files\Storage\Shared $sharedStorage + */ + + $sharedCache = $sharedStorage->getCache(); + $this->assertEquals('', $sharedCache->getPathById($folderInfo->getId())); + $this->assertEquals('bar/test.txt', $sharedCache->getPathById($fileInfo->getId())); + } +} diff --git a/apps/files_sharing/tests/CapabilitiesTest.php b/apps/files_sharing/tests/CapabilitiesTest.php new file mode 100644 index 00000000000..08797b26810 --- /dev/null +++ b/apps/files_sharing/tests/CapabilitiesTest.php @@ -0,0 +1,300 @@ + + * @author Roeland Jago Douma + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ +namespace OCA\Files_Sharing\Tests; + +use OCA\Files_Sharing\Capabilities; +use OCA\Files_Sharing\Tests\TestCase; + +/** + * Class CapabilitiesTest + * + * @group DB + */ +class CapabilitiesTest extends \Test\TestCase { + + /** + * Test for the general part in each return statement and assert. + * Strip of the general part on the way. + * + * @param string[] $data Capabilities + * @return string[] + */ + private function getFilesSharingPart(array $data) { + $this->assertArrayHasKey('files_sharing', $data); + return $data['files_sharing']; + } + + /** + * Create a mock config object and insert the values in $map tot the getAppValue + * function. Then obtain the capabilities and extract the first few + * levels in the array + * + * @param (string[])[] $map Map of arguments to return types for the getAppValue function in the mock + * @return string[] + */ + private function getResults(array $map) { + $stub = $this->getMockBuilder('\OCP\IConfig')->disableOriginalConstructor()->getMock(); + $stub->method('getAppValue')->will($this->returnValueMap($map)); + $cap = new Capabilities($stub); + $result = $this->getFilesSharingPart($cap->getCapabilities()); + return $result; + } + + public function testEnabledSharingAPI() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ]; + $result = $this->getResults($map); + $this->assertTrue($result['api_enabled']); + $this->assertContains('public', $result); + $this->assertContains('user', $result); + $this->assertContains('resharing', $result); + } + + public function testDisabledSharingAPI() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'no'], + ]; + $result = $this->getResults($map); + $this->assertFalse($result['api_enabled']); + $this->assertNotContains('public', $result); + $this->assertNotContains('user', $result); + $this->assertNotContains('resharing', $result); + } + + public function testNoLinkSharing() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_links', 'yes', 'no'], + ]; + $result = $this->getResults($map); + $this->assertInternalType('array', $result['public']); + $this->assertFalse($result['public']['enabled']); + } + + public function testOnlyLinkSharing() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ]; + $result = $this->getResults($map); + $this->assertInternalType('array', $result['public']); + $this->assertTrue($result['public']['enabled']); + } + + public function testLinkPassword() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['core', 'shareapi_enforce_links_password', 'no', 'yes'], + ]; + $result = $this->getResults($map); + $this->assertArrayHasKey('password', $result['public']); + $this->assertArrayHasKey('enforced', $result['public']['password']); + $this->assertTrue($result['public']['password']['enforced']); + } + + public function testLinkNoPassword() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['core', 'shareapi_enforce_links_password', 'no', 'no'], + ]; + $result = $this->getResults($map); + $this->assertArrayHasKey('password', $result['public']); + $this->assertArrayHasKey('enforced', $result['public']['password']); + $this->assertFalse($result['public']['password']['enforced']); + } + + public function testLinkNoExpireDate() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['core', 'shareapi_default_expire_date', 'no', 'no'], + ]; + $result = $this->getResults($map); + $this->assertArrayHasKey('expire_date', $result['public']); + $this->assertInternalType('array', $result['public']['expire_date']); + $this->assertFalse($result['public']['expire_date']['enabled']); + } + + public function testLinkExpireDate() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['core', 'shareapi_default_expire_date', 'no', 'yes'], + ['core', 'shareapi_expire_after_n_days', '7', '7'], + ['core', 'shareapi_enforce_expire_date', 'no', 'no'], + ]; + $result = $this->getResults($map); + $this->assertArrayHasKey('expire_date', $result['public']); + $this->assertInternalType('array', $result['public']['expire_date']); + $this->assertTrue($result['public']['expire_date']['enabled']); + $this->assertArrayHasKey('days', $result['public']['expire_date']); + $this->assertFalse($result['public']['expire_date']['enforced']); + } + + public function testLinkExpireDateEnforced() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['core', 'shareapi_default_expire_date', 'no', 'yes'], + ['core', 'shareapi_enforce_expire_date', 'no', 'yes'], + ]; + $result = $this->getResults($map); + $this->assertArrayHasKey('expire_date', $result['public']); + $this->assertInternalType('array', $result['public']['expire_date']); + $this->assertTrue($result['public']['expire_date']['enforced']); + } + + public function testLinkSendMail() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['core', 'shareapi_allow_public_notification', 'no', 'yes'], + ]; + $result = $this->getResults($map); + $this->assertTrue($result['public']['send_mail']); + } + + public function testLinkNoSendMail() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['core', 'shareapi_allow_public_notification', 'no', 'no'], + ]; + $result = $this->getResults($map); + $this->assertFalse($result['public']['send_mail']); + } + + public function testUserSendMail() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_mail_notification', 'no', 'yes'], + ]; + $result = $this->getResults($map); + $this->assertTrue($result['user']['send_mail']); + } + + public function testUserNoSendMail() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_mail_notification', 'no', 'no'], + ]; + $result = $this->getResults($map); + $this->assertFalse($result['user']['send_mail']); + } + + public function testResharing() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_resharing', 'yes', 'yes'], + ]; + $result = $this->getResults($map); + $this->assertTrue($result['resharing']); + } + + public function testNoResharing() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_resharing', 'yes', 'no'], + ]; + $result = $this->getResults($map); + $this->assertFalse($result['resharing']); + } + + public function testLinkPublicUpload() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['core', 'shareapi_allow_public_upload', 'yes', 'yes'], + ]; + $result = $this->getResults($map); + $this->assertTrue($result['public']['upload']); + } + + public function testLinkNoPublicUpload() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['core', 'shareapi_allow_public_upload', 'yes', 'no'], + ]; + $result = $this->getResults($map); + $this->assertFalse($result['public']['upload']); + } + + public function testNoGroupSharing() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_group_sharing', 'yes', 'no'], + ]; + $result = $this->getResults($map); + $this->assertFalse($result['group_sharing']); + } + + public function testGroupSharing() { + $map = [ + ['core', 'shareapi_enabled', 'yes', 'yes'], + ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'], + ]; + $result = $this->getResults($map); + $this->assertTrue($result['group_sharing']); + } + + public function testFederatedSharingIncomming() { + $map = [ + ['files_sharing', 'incoming_server2server_share_enabled', 'yes', 'yes'], + ]; + $result = $this->getResults($map); + $this->assertArrayHasKey('federation', $result); + $this->assertTrue($result['federation']['incoming']); + } + + public function testFederatedSharingNoIncomming() { + $map = [ + ['files_sharing', 'incoming_server2server_share_enabled', 'yes', 'no'], + ]; + $result = $this->getResults($map); + $this->assertArrayHasKey('federation', $result); + $this->assertFalse($result['federation']['incoming']); + } + + public function testFederatedSharingOutgoing() { + $map = [ + ['files_sharing', 'outgoing_server2server_share_enabled', 'yes', 'yes'], + ]; + $result = $this->getResults($map); + $this->assertArrayHasKey('federation', $result); + $this->assertTrue($result['federation']['outgoing']); + } + + public function testFederatedSharingNoOutgoing() { + $map = [ + ['files_sharing', 'outgoing_server2server_share_enabled', 'yes', 'no'], + ]; + $result = $this->getResults($map); + $this->assertArrayHasKey('federation', $result); + $this->assertFalse($result['federation']['outgoing']); + } + +} diff --git a/apps/files_sharing/tests/Controllers/ExternalShareControllerTest.php b/apps/files_sharing/tests/Controllers/ExternalShareControllerTest.php new file mode 100644 index 00000000000..add6d2f08a3 --- /dev/null +++ b/apps/files_sharing/tests/Controllers/ExternalShareControllerTest.php @@ -0,0 +1,154 @@ + + * @author Roeland Jago Douma + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests\Controllers; + +use OCA\Files_Sharing\Controllers\ExternalSharesController; +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http\JSONResponse; +use OCP\Http\Client\IClientService; +use OCP\IRequest; + +/** + * Class ExternalShareControllerTest + * + * @package OCA\Files_Sharing\Controllers + */ +class ExternalShareControllerTest extends \Test\TestCase { + /** @var IRequest */ + private $request; + /** @var \OCA\Files_Sharing\External\Manager */ + private $externalManager; + /** @var IClientService */ + private $clientService; + + public function setUp() { + parent::setUp(); + $this->request = $this->getMockBuilder('\\OCP\\IRequest') + ->disableOriginalConstructor()->getMock(); + $this->externalManager = $this->getMockBuilder('\\OCA\\Files_Sharing\\External\\Manager') + ->disableOriginalConstructor()->getMock(); + $this->clientService = $this->getMockBuilder('\\OCP\Http\\Client\\IClientService') + ->disableOriginalConstructor()->getMock(); + } + + /** + * @return ExternalSharesController + */ + public function getExternalShareController() { + return new ExternalSharesController( + 'files_sharing', + $this->request, + $this->externalManager, + $this->clientService + ); + } + + public function testIndex() { + $this->externalManager + ->expects($this->once()) + ->method('getOpenShares') + ->will($this->returnValue(['MyDummyArray'])); + + $this->assertEquals(new JSONResponse(['MyDummyArray']), $this->getExternalShareController()->index()); + } + + public function testCreate() { + $this->externalManager + ->expects($this->once()) + ->method('acceptShare') + ->with(4); + + $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->create(4)); + } + + public function testDestroy() { + $this->externalManager + ->expects($this->once()) + ->method('declineShare') + ->with(4); + + $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->destroy(4)); + } + + public function testRemoteWithValidHttps() { + $client = $this->getMockBuilder('\\OCP\\Http\\Client\\IClient') + ->disableOriginalConstructor()->getMock(); + $response = $this->getMockBuilder('\\OCP\\Http\\Client\\IResponse') + ->disableOriginalConstructor()->getMock(); + $response + ->expects($this->exactly(2)) + ->method('getBody') + ->will($this->onConsecutiveCalls('Certainly not a JSON string', '{"installed":true,"maintenance":false,"version":"8.1.0.8","versionstring":"8.1.0","edition":""}')); + $client + ->expects($this->any()) + ->method('get') + ->will($this->returnValue($response)); + + $this->clientService + ->expects($this->exactly(2)) + ->method('newClient') + ->will($this->returnValue($client)); + + $this->assertEquals(new DataResponse('https'), $this->getExternalShareController()->testRemote('owncloud.org')); + } + + public function testRemoteWithWorkingHttp() { + $client = $this->getMockBuilder('\\OCP\\Http\\Client\\IClient') + ->disableOriginalConstructor()->getMock(); + $response = $this->getMockBuilder('\\OCP\\Http\\Client\\IResponse') + ->disableOriginalConstructor()->getMock(); + $client + ->method('get') + ->will($this->returnValue($response)); + $response + ->expects($this->exactly(5)) + ->method('getBody') + ->will($this->onConsecutiveCalls('Certainly not a JSON string', 'Certainly not a JSON string', 'Certainly not a JSON string', 'Certainly not a JSON string', '{"installed":true,"maintenance":false,"version":"8.1.0.8","versionstring":"8.1.0","edition":""}')); + $this->clientService + ->expects($this->exactly(5)) + ->method('newClient') + ->will($this->returnValue($client)); + + $this->assertEquals(new DataResponse('http'), $this->getExternalShareController()->testRemote('owncloud.org')); + } + + public function testRemoteWithInvalidRemote() { + $client = $this->getMockBuilder('\\OCP\\Http\\Client\\IClient') + ->disableOriginalConstructor()->getMock(); + $response = $this->getMockBuilder('\\OCP\\Http\\Client\\IResponse') + ->disableOriginalConstructor()->getMock(); + $client + ->method('get') + ->will($this->returnValue($response)); + $response + ->expects($this->exactly(6)) + ->method('getBody') + ->will($this->returnValue('Certainly not a JSON string')); + $this->clientService + ->expects($this->exactly(6)) + ->method('newClient') + ->will($this->returnValue($client)); + + $this->assertEquals(new DataResponse(false), $this->getExternalShareController()->testRemote('owncloud.org')); + } +} diff --git a/apps/files_sharing/tests/Controllers/ShareControllerTest.php b/apps/files_sharing/tests/Controllers/ShareControllerTest.php new file mode 100644 index 00000000000..74e19aa29b4 --- /dev/null +++ b/apps/files_sharing/tests/Controllers/ShareControllerTest.php @@ -0,0 +1,454 @@ + + * @author Joas Schilling + * @author Lukas Reschke + * @author Morris Jobke + * @author Robin Appelman + * @author Roeland Jago Douma + * @author Thomas Müller + * @author Vincent Cloutier + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests\Controllers; + +use OC\Files\Filesystem; +use OCA\FederatedFileSharing\FederatedShareProvider; +use OCA\Files_Sharing\Controllers\ShareController; +use OCP\Share\Exceptions\ShareNotFound; +use OCP\AppFramework\Http\NotFoundResponse; +use OCP\AppFramework\Http\RedirectResponse; +use OCP\AppFramework\Http\TemplateResponse; +use OCP\ISession; +use OCP\IUserManager; +use OCP\Security\ISecureRandom; +use OCP\IURLGenerator; + +/** + * @group DB + * + * @package OCA\Files_Sharing\Controllers + */ +class ShareControllerTest extends \Test\TestCase { + + /** @var string */ + private $user; + /** @var string */ + private $oldUser; + + /** @var string */ + private $appName = 'files_sharing'; + /** @var ShareController */ + private $shareController; + /** @var IURLGenerator | \PHPUnit_Framework_MockObject_MockObject */ + private $urlGenerator; + /** @var ISession | \PHPUnit_Framework_MockObject_MockObject */ + private $session; + /** @var \OCP\IPreview | \PHPUnit_Framework_MockObject_MockObject */ + private $previewManager; + /** @var \OCP\IConfig | \PHPUnit_Framework_MockObject_MockObject */ + private $config; + /** @var \OC\Share20\Manager | \PHPUnit_Framework_MockObject_MockObject */ + private $shareManager; + /** @var IUserManager | \PHPUnit_Framework_MockObject_MockObject */ + private $userManager; + /** @var FederatedShareProvider | \PHPUnit_Framework_MockObject_MockObject */ + private $federatedShareProvider; + + protected function setUp() { + parent::setUp(); + $this->appName = 'files_sharing'; + + $this->shareManager = $this->getMockBuilder('\OC\Share20\Manager')->disableOriginalConstructor()->getMock(); + $this->urlGenerator = $this->getMock('\OCP\IURLGenerator'); + $this->session = $this->getMock('\OCP\ISession'); + $this->previewManager = $this->getMock('\OCP\IPreview'); + $this->config = $this->getMock('\OCP\IConfig'); + $this->userManager = $this->getMock('\OCP\IUserManager'); + $this->federatedShareProvider = $this->getMockBuilder('OCA\FederatedFileSharing\FederatedShareProvider') + ->disableOriginalConstructor()->getMock(); + $this->federatedShareProvider->expects($this->any()) + ->method('isOutgoingServer2serverShareEnabled')->willReturn(true); + $this->federatedShareProvider->expects($this->any()) + ->method('isIncomingServer2serverShareEnabled')->willReturn(true); + + $this->shareController = new \OCA\Files_Sharing\Controllers\ShareController( + $this->appName, + $this->getMock('\OCP\IRequest'), + $this->config, + $this->urlGenerator, + $this->userManager, + $this->getMock('\OCP\ILogger'), + $this->getMock('\OCP\Activity\IManager'), + $this->shareManager, + $this->session, + $this->previewManager, + $this->getMock('\OCP\Files\IRootFolder'), + $this->federatedShareProvider + ); + + + // Store current user + $this->oldUser = \OC_User::getUser(); + + // Create a dummy user + $this->user = \OC::$server->getSecureRandom()->generate(12, ISecureRandom::CHAR_LOWER); + + \OC::$server->getUserManager()->createUser($this->user, $this->user); + \OC_Util::tearDownFS(); + $this->loginAsUser($this->user); + } + + protected function tearDown() { + \OC_Util::tearDownFS(); + \OC_User::setUserId(''); + Filesystem::tearDown(); + $user = \OC::$server->getUserManager()->get($this->user); + if ($user !== null) { $user->delete(); } + \OC_User::setIncognitoMode(false); + + \OC::$server->getSession()->set('public_link_authenticated', ''); + + // Set old user + \OC_User::setUserId($this->oldUser); + \OC_Util::setupFS($this->oldUser); + parent::tearDown(); + } + + public function testShowAuthenticateNotAuthenticated() { + $share = \OC::$server->getShareManager()->newShare(); + + $this->shareManager + ->expects($this->once()) + ->method('getShareByToken') + ->with('token') + ->willReturn($share); + + $response = $this->shareController->showAuthenticate('token'); + $expectedResponse = new TemplateResponse($this->appName, 'authenticate', [], 'guest'); + $this->assertEquals($expectedResponse, $response); + } + + public function testShowAuthenticateAuthenticatedForDifferentShare() { + $share = \OC::$server->getShareManager()->newShare(); + $share->setId(1); + + $this->shareManager + ->expects($this->once()) + ->method('getShareByToken') + ->with('token') + ->willReturn($share); + + $this->session->method('exists')->with('public_link_authenticated')->willReturn(true); + $this->session->method('get')->with('public_link_authenticated')->willReturn('2'); + + $response = $this->shareController->showAuthenticate('token'); + $expectedResponse = new TemplateResponse($this->appName, 'authenticate', [], 'guest'); + $this->assertEquals($expectedResponse, $response); + } + + public function testShowAuthenticateCorrectShare() { + $share = \OC::$server->getShareManager()->newShare(); + $share->setId(1); + + $this->shareManager + ->expects($this->once()) + ->method('getShareByToken') + ->with('token') + ->willReturn($share); + + $this->session->method('exists')->with('public_link_authenticated')->willReturn(true); + $this->session->method('get')->with('public_link_authenticated')->willReturn('1'); + + $this->urlGenerator->expects($this->once()) + ->method('linkToRoute') + ->with('files_sharing.sharecontroller.showShare', ['token' => 'token']) + ->willReturn('redirect'); + + $response = $this->shareController->showAuthenticate('token'); + $expectedResponse = new RedirectResponse('redirect'); + $this->assertEquals($expectedResponse, $response); + } + + public function testAuthenticateInvalidToken() { + $this->shareManager + ->expects($this->once()) + ->method('getShareByToken') + ->with('token') + ->will($this->throwException(new \OCP\Share\Exceptions\ShareNotFound())); + + $response = $this->shareController->authenticate('token'); + $expectedResponse = new NotFoundResponse(); + $this->assertEquals($expectedResponse, $response); + } + + public function testAuthenticateValidPassword() { + $share = \OC::$server->getShareManager()->newShare(); + $share->setId(42); + + $this->shareManager + ->expects($this->once()) + ->method('getShareByToken') + ->with('token') + ->willReturn($share); + + $this->shareManager + ->expects($this->once()) + ->method('checkPassword') + ->with($share, 'validpassword') + ->willReturn(true); + + $this->session + ->expects($this->once()) + ->method('set') + ->with('public_link_authenticated', '42'); + + $this->urlGenerator->expects($this->once()) + ->method('linkToRoute') + ->with('files_sharing.sharecontroller.showShare', ['token'=>'token']) + ->willReturn('redirect'); + + $response = $this->shareController->authenticate('token', 'validpassword'); + $expectedResponse = new RedirectResponse('redirect'); + $this->assertEquals($expectedResponse, $response); + } + + public function testAuthenticateInvalidPassword() { + $share = \OC::$server->getShareManager()->newShare(); + $share->setNodeId(100) + ->setNodeType('file') + ->setToken('token') + ->setSharedBy('initiator') + ->setId(42); + + $this->shareManager + ->expects($this->once()) + ->method('getShareByToken') + ->with('token') + ->willReturn($share); + + $this->shareManager + ->expects($this->once()) + ->method('checkPassword') + ->with($share, 'invalidpassword') + ->willReturn(false); + + $this->session + ->expects($this->never()) + ->method('set'); + + $hookListner = $this->getMockBuilder('Dummy')->setMethods(['access'])->getMock(); + \OCP\Util::connectHook('OCP\Share', 'share_link_access', $hookListner, 'access'); + + $hookListner->expects($this->once()) + ->method('access') + ->with($this->callback(function(array $data) { + return $data['itemType'] === 'file' && + $data['itemSource'] === 100 && + $data['uidOwner'] === 'initiator' && + $data['token'] === 'token' && + $data['errorCode'] === 403 && + $data['errorMessage'] === 'Wrong password'; + })); + + $response = $this->shareController->authenticate('token', 'invalidpassword'); + $expectedResponse = new TemplateResponse($this->appName, 'authenticate', array('wrongpw' => true), 'guest'); + $this->assertEquals($expectedResponse, $response); + } + + public function testShowShareInvalidToken() { + $this->shareManager + ->expects($this->once()) + ->method('getShareByToken') + ->with('invalidtoken') + ->will($this->throwException(new ShareNotFound())); + + // Test without a not existing token + $response = $this->shareController->showShare('invalidtoken'); + $expectedResponse = new NotFoundResponse(); + $this->assertEquals($expectedResponse, $response); + } + + public function testShowShareNotAuthenticated() { + $share = \OC::$server->getShareManager()->newShare(); + $share->setPassword('password'); + + $this->shareManager + ->expects($this->once()) + ->method('getShareByToken') + ->with('validtoken') + ->willReturn($share); + + $this->urlGenerator->expects($this->once()) + ->method('linkToRoute') + ->with('files_sharing.sharecontroller.authenticate', ['token' => 'validtoken']) + ->willReturn('redirect'); + + // Test without a not existing token + $response = $this->shareController->showShare('validtoken'); + $expectedResponse = new RedirectResponse('redirect'); + $this->assertEquals($expectedResponse, $response); + } + + + public function testShowShare() { + $owner = $this->getMock('OCP\IUser'); + $owner->method('getDisplayName')->willReturn('ownerDisplay'); + $owner->method('getUID')->willReturn('ownerUID'); + + $file = $this->getMock('OCP\Files\File'); + $file->method('getName')->willReturn('file1.txt'); + $file->method('getMimetype')->willReturn('text/plain'); + $file->method('getSize')->willReturn(33); + $file->method('isReadable')->willReturn(true); + $file->method('isShareable')->willReturn(true); + + $share = \OC::$server->getShareManager()->newShare(); + $share->setId(42); + $share->setPassword('password') + ->setShareOwner('ownerUID') + ->setNode($file) + ->setTarget('/file1.txt'); + + $this->session->method('exists')->with('public_link_authenticated')->willReturn(true); + $this->session->method('get')->with('public_link_authenticated')->willReturn('42'); + + $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true); + + $this->config->method('getSystemValue') + ->willReturnMap( + [ + ['max_filesize_animated_gifs_public_sharing', 10, 10], + ['enable_previews', true, true], + ['preview_max_x', 1024, 1024], + ['preview_max_y', 1024, 1024], + ] + ); + $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10); + $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true); + + $this->shareManager + ->expects($this->once()) + ->method('getShareByToken') + ->with('token') + ->willReturn($share); + + $this->userManager->method('get')->with('ownerUID')->willReturn($owner); + + $response = $this->shareController->showShare('token'); + $sharedTmplParams = array( + 'displayName' => 'ownerDisplay', + 'owner' => 'ownerUID', + 'filename' => 'file1.txt', + 'directory_path' => '/file1.txt', + 'mimetype' => 'text/plain', + 'dirToken' => 'token', + 'sharingToken' => 'token', + 'server2serversharing' => true, + 'protected' => 'true', + 'dir' => '', + 'downloadURL' => null, + 'fileSize' => '33 B', + 'nonHumanFileSize' => 33, + 'maxSizeAnimateGif' => 10, + 'previewSupported' => true, + 'previewEnabled' => true, + 'previewMaxX' => 1024, + 'previewMaxY' => 1024, + ); + + $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy(); + $csp->addAllowedFrameDomain('\'self\''); + $expectedResponse = new TemplateResponse($this->appName, 'public', $sharedTmplParams, 'base'); + $expectedResponse->setContentSecurityPolicy($csp); + + $this->assertEquals($expectedResponse, $response); + } + + /** + * @expectedException \OCP\Files\NotFoundException + */ + public function testShowShareInvalid() { + $owner = $this->getMock('OCP\IUser'); + $owner->method('getDisplayName')->willReturn('ownerDisplay'); + $owner->method('getUID')->willReturn('ownerUID'); + + $file = $this->getMock('OCP\Files\File'); + $file->method('getName')->willReturn('file1.txt'); + $file->method('getMimetype')->willReturn('text/plain'); + $file->method('getSize')->willReturn(33); + $file->method('isShareable')->willReturn(false); + $file->method('isReadable')->willReturn(true); + + $share = \OC::$server->getShareManager()->newShare(); + $share->setId(42); + $share->setPassword('password') + ->setShareOwner('ownerUID') + ->setNode($file) + ->setTarget('/file1.txt'); + + $this->session->method('exists')->with('public_link_authenticated')->willReturn(true); + $this->session->method('get')->with('public_link_authenticated')->willReturn('42'); + + $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true); + + $this->config->method('getSystemValue') + ->willReturnMap( + [ + ['max_filesize_animated_gifs_public_sharing', 10, 10], + ['enable_previews', true, true], + ] + ); + $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10); + $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true); + + $this->shareManager + ->expects($this->once()) + ->method('getShareByToken') + ->with('token') + ->willReturn($share); + + $this->userManager->method('get')->with('ownerUID')->willReturn($owner); + + $this->shareController->showShare('token'); + } + + + public function testDownloadShare() { + $share = $this->getMock('\OCP\Share\IShare'); + $share->method('getPassword')->willReturn('password'); + + $this->shareManager + ->expects($this->once()) + ->method('getShareByToken') + ->with('validtoken') + ->willReturn($share); + + $this->urlGenerator->expects($this->once()) + ->method('linkToRoute') + ->with('files_sharing.sharecontroller.authenticate', ['token' => 'validtoken']) + ->willReturn('redirect'); + + // Test with a password protected share and no authentication + $response = $this->shareController->downloadShare('validtoken'); + $expectedResponse = new RedirectResponse('redirect'); + $this->assertEquals($expectedResponse, $response); + } + +} diff --git a/apps/files_sharing/tests/DeleteOrphanedSharesJobTest.php b/apps/files_sharing/tests/DeleteOrphanedSharesJobTest.php new file mode 100644 index 00000000000..69d9ab228f2 --- /dev/null +++ b/apps/files_sharing/tests/DeleteOrphanedSharesJobTest.php @@ -0,0 +1,171 @@ + + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +use OCA\Files_Sharing\DeleteOrphanedSharesJob; + +/** + * Class DeleteOrphanedSharesJobTest + * + * @group DB + * + * @package OCA\Files_Sharing\Tests + */ +class DeleteOrphanedSharesJobTest extends \Test\TestCase { + + /** + * @var bool + */ + private static $trashBinStatus; + + /** + * @var DeleteOrphanedSharesJob + */ + private $job; + + /** + * @var \OCP\IDBConnection + */ + private $connection; + + /** + * @var string + */ + private $user1; + + /** + * @var string + */ + private $user2; + + public static function setUpBeforeClass() { + $appManager = \OC::$server->getAppManager(); + self::$trashBinStatus = $appManager->isEnabledForUser('files_trashbin'); + $appManager->disableApp('files_trashbin'); + + // just in case... + \OC\Files\Filesystem::getLoader()->removeStorageWrapper('oc_trashbin'); + } + + public static function tearDownAfterClass() { + if (self::$trashBinStatus) { + \OC::$server->getAppManager()->enableApp('files_trashbin'); + } + } + + protected function setup() { + parent::setUp(); + + $this->connection = \OC::$server->getDatabaseConnection(); + // clear occasional leftover shares from other tests + $this->connection->executeUpdate('DELETE FROM `*PREFIX*share`'); + + $this->user1 = $this->getUniqueID('user1_'); + $this->user2 = $this->getUniqueID('user2_'); + + $userManager = \OC::$server->getUserManager(); + $userManager->createUser($this->user1, 'pass'); + $userManager->createUser($this->user2, 'pass'); + + \OC::registerShareHooks(); + + $this->job = new DeleteOrphanedSharesJob(); + } + + protected function tearDown() { + $this->connection->executeUpdate('DELETE FROM `*PREFIX*share`'); + + $userManager = \OC::$server->getUserManager(); + $user1 = $userManager->get($this->user1); + if($user1) { + $user1->delete(); + } + $user2 = $userManager->get($this->user2); + if($user2) { + $user2->delete(); + } + + $this->logout(); + + parent::tearDown(); + } + + private function getShares() { + $shares = []; + $result = $this->connection->executeQuery('SELECT * FROM `*PREFIX*share`'); + while ($row = $result->fetch()) { + $shares[] = $row; + } + $result->closeCursor(); + return $shares; + } + + /** + * Test clearing orphaned shares + */ + public function testClearShares() { + $this->loginAsUser($this->user1); + + $view = new \OC\Files\View('/' . $this->user1 . '/'); + $view->mkdir('files/test'); + $view->mkdir('files/test/sub'); + + $fileInfo = $view->getFileInfo('files/test/sub'); + $fileId = $fileInfo->getId(); + + $this->assertTrue( + \OCP\Share::shareItem('folder', $fileId, \OCP\Share::SHARE_TYPE_USER, $this->user2, \OCP\Constants::PERMISSION_READ), + 'Failed asserting that user 1 successfully shared "test/sub" with user 2.' + ); + + $this->assertCount(1, $this->getShares()); + + $this->job->run([]); + + $this->assertCount(1, $this->getShares(), 'Linked shares not deleted'); + + $view->unlink('files/test'); + + $this->job->run([]); + + $this->assertCount(0, $this->getShares(), 'Orphaned shares deleted'); + } + + public function testKeepNonFileShares() { + $this->loginAsUser($this->user1); + + \OCP\Share::registerBackend('test', 'Test\Share\Backend'); + + $this->assertTrue( + \OCP\Share::shareItem('test', 'test.txt', \OCP\Share::SHARE_TYPE_USER, $this->user2, \OCP\Constants::PERMISSION_READ), + 'Failed asserting that user 1 successfully shared something with user 2.' + ); + + $this->assertCount(1, $this->getShares()); + + $this->job->run([]); + + $this->assertCount(1, $this->getShares(), 'Non-file shares kept'); + } +} + diff --git a/apps/files_sharing/tests/EncryptedSizePropagationTest.php b/apps/files_sharing/tests/EncryptedSizePropagationTest.php new file mode 100644 index 00000000000..0abd9c39c99 --- /dev/null +++ b/apps/files_sharing/tests/EncryptedSizePropagationTest.php @@ -0,0 +1,41 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +use OC\Files\View; +use Test\Traits\EncryptionTrait; + +/** + * @group DB + */ +class EncryptedSizePropagationTest extends SizePropagationTest { + use EncryptionTrait; + + protected function setupUser($name, $password = '') { + $this->createUser($name, $password); + $tmpFolder = \OC::$server->getTempManager()->getTemporaryFolder(); + $this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]); + $this->setupForUser($name, $password); + $this->loginWithEncryption($name); + return new View('/' . $name . '/files'); + } +} diff --git a/apps/files_sharing/tests/EtagPropagationTest.php b/apps/files_sharing/tests/EtagPropagationTest.php new file mode 100644 index 00000000000..bf53beccab1 --- /dev/null +++ b/apps/files_sharing/tests/EtagPropagationTest.php @@ -0,0 +1,461 @@ + + * @author Lukas Reschke + * @author Robin Appelman + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +use OC\Files\Filesystem; +use OC\Files\View; + +/** + * Class EtagPropagationTest + * + * @group DB + * + * @package OCA\Files_Sharing\Tests + */ +class EtagPropagationTest extends PropagationTestCase { + + /** + * "user1" is the admin who shares a folder "sub1/sub2/folder" with "user2" and "user3" + * "user2" receives the folder and puts it in "sub1/sub2/folder" + * "user3" receives the folder and puts it in "sub1/sub2/folder" + * "user2" reshares the subdir "sub1/sub2/folder/inside" with "user4" + * "user4" puts the received "inside" folder into "sub1/sub2/inside" (this is to check if it propagates across multiple subfolders) + */ + protected function setUpShares() { + $this->fileIds[self::TEST_FILES_SHARING_API_USER1] = []; + $this->fileIds[self::TEST_FILES_SHARING_API_USER2] = []; + $this->fileIds[self::TEST_FILES_SHARING_API_USER3] = []; + $this->fileIds[self::TEST_FILES_SHARING_API_USER4] = []; + + $rootFolder = \OC::$server->getRootFolder(); + $shareManager = \OC::$server->getShareManager(); + + $this->rootView = new View(''); + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + $view1 = new View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files'); + $view1->mkdir('/sub1/sub2/folder/inside'); + $view1->mkdir('/directReshare'); + $view1->mkdir('/sub1/sub2/folder/other'); + $view1->file_put_contents('/foo.txt', 'foobar'); + $view1->file_put_contents('/sub1/sub2/folder/file.txt', 'foobar'); + $view1->file_put_contents('/sub1/sub2/folder/inside/file.txt', 'foobar'); + $folderInfo = $view1->getFileInfo('/sub1/sub2/folder'); + $this->assertInstanceOf('\OC\Files\FileInfo', $folderInfo); + $fileInfo = $view1->getFileInfo('/foo.txt'); + $this->assertInstanceOf('\OC\Files\FileInfo', $fileInfo); + + $node = $rootFolder->getUserFolder(self::TEST_FILES_SHARING_API_USER1) + ->get('/foo.txt'); + $share = $shareManager->newShare(); + $share->setNode($node) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setPermissions(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE); + $shareManager->createShare($share); + $node = $rootFolder->getUserFolder(self::TEST_FILES_SHARING_API_USER1) + ->get('/sub1/sub2/folder'); + $share = $shareManager->newShare(); + $share->setNode($node) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setPermissions(\OCP\Constants::PERMISSION_ALL); + $shareManager->createShare($share); + $share = $shareManager->newShare(); + $share->setNode($node) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER3) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setPermissions(\OCP\Constants::PERMISSION_ALL); + $shareManager->createShare($share); + + $folderInfo = $view1->getFileInfo('/directReshare'); + $this->assertInstanceOf('\OC\Files\FileInfo', $folderInfo); + + $node = $rootFolder->getUserFolder(self::TEST_FILES_SHARING_API_USER1) + ->get('/directReshare'); + $share = $shareManager->newShare(); + $share->setNode($node) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setPermissions(\OCP\Constants::PERMISSION_ALL); + $shareManager->createShare($share); + + $this->fileIds[self::TEST_FILES_SHARING_API_USER1][''] = $view1->getFileInfo('')->getId(); + $this->fileIds[self::TEST_FILES_SHARING_API_USER1]['sub1'] = $view1->getFileInfo('sub1')->getId(); + $this->fileIds[self::TEST_FILES_SHARING_API_USER1]['sub1/sub2'] = $view1->getFileInfo('sub1/sub2')->getId(); + + /* + * User 2 + */ + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); + $view2 = new View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); + $view2->mkdir('/sub1/sub2'); + $view2->rename('/folder', '/sub1/sub2/folder'); + $insideInfo = $view2->getFileInfo('/sub1/sub2/folder/inside'); + $this->assertInstanceOf('\OC\Files\FileInfo', $insideInfo); + + $node = $rootFolder->getUserFolder(self::TEST_FILES_SHARING_API_USER2) + ->get('/sub1/sub2/folder/inside'); + $share = $shareManager->newShare(); + $share->setNode($node) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER4) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) + ->setPermissions(\OCP\Constants::PERMISSION_ALL); + $shareManager->createShare($share); + + $folderInfo = $view2->getFileInfo('/directReshare'); + $this->assertInstanceOf('\OC\Files\FileInfo', $folderInfo); + + $node = $rootFolder->getUserFolder(self::TEST_FILES_SHARING_API_USER2) + ->get('/directReshare'); + $share = $shareManager->newShare(); + $share->setNode($node) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER4) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) + ->setPermissions(\OCP\Constants::PERMISSION_ALL); + $shareManager->createShare($share); + + $this->fileIds[self::TEST_FILES_SHARING_API_USER2][''] = $view2->getFileInfo('')->getId(); + $this->fileIds[self::TEST_FILES_SHARING_API_USER2]['sub1'] = $view2->getFileInfo('sub1')->getId(); + $this->fileIds[self::TEST_FILES_SHARING_API_USER2]['sub1/sub2'] = $view2->getFileInfo('sub1/sub2')->getId(); + + /* + * User 3 + */ + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER3); + $view3 = new View('/' . self::TEST_FILES_SHARING_API_USER3 . '/files'); + $view3->mkdir('/sub1/sub2'); + $view3->rename('/folder', '/sub1/sub2/folder'); + $this->fileIds[self::TEST_FILES_SHARING_API_USER3][''] = $view3->getFileInfo('')->getId(); + $this->fileIds[self::TEST_FILES_SHARING_API_USER3]['sub1'] = $view3->getFileInfo('sub1')->getId(); + $this->fileIds[self::TEST_FILES_SHARING_API_USER3]['sub1/sub2'] = $view3->getFileInfo('sub1/sub2')->getId(); + + /* + * User 4 + */ + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER4); + $view4 = new View('/' . self::TEST_FILES_SHARING_API_USER4 . '/files'); + $view4->mkdir('/sub1/sub2'); + $view4->rename('/inside', '/sub1/sub2/inside'); + $this->fileIds[self::TEST_FILES_SHARING_API_USER4][''] = $view4->getFileInfo('')->getId(); + $this->fileIds[self::TEST_FILES_SHARING_API_USER4]['sub1'] = $view4->getFileInfo('sub1')->getId(); + $this->fileIds[self::TEST_FILES_SHARING_API_USER4]['sub1/sub2'] = $view4->getFileInfo('sub1/sub2')->getId(); + + foreach ($this->fileIds as $user => $ids) { + $this->loginAsUser($user); + foreach ($ids as $id) { + $path = $this->rootView->getPath($id); + $ls = $this->rootView->getDirectoryContent($path); + $this->fileEtags[$id] = $this->rootView->getFileInfo($path)->getEtag(); + } + } + } + + public function testOwnerWritesToShare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + Filesystem::file_put_contents('/sub1/sub2/folder/asd.txt', 'bar'); + $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER4]); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3]); + + $this->assertAllUnchanged(); + } + + public function testOwnerWritesToSingleFileShare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + Filesystem::file_put_contents('/foo.txt', 'longer_bar'); + $t = (int)Filesystem::filemtime('/foo.txt') - 1; + Filesystem::touch('/foo.txt', $t); + $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER4, self::TEST_FILES_SHARING_API_USER3]); + $this->assertEtagsChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2]); + + $this->assertAllUnchanged(); + } + + public function testOwnerWritesToShareWithReshare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + Filesystem::file_put_contents('/sub1/sub2/folder/inside/bar.txt', 'bar'); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); + + $this->assertAllUnchanged(); + } + + public function testOwnerRenameInShare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER4]); + Filesystem::rename('/sub1/sub2/folder/file.txt', '/sub1/sub2/folder/renamed.txt'); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3]); + + $this->assertAllUnchanged(); + } + + public function testOwnerRenameInReShare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + Filesystem::rename('/sub1/sub2/folder/inside/file.txt', '/sub1/sub2/folder/inside/renamed.txt'); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); + + $this->assertAllUnchanged(); + } + + public function testOwnerRenameIntoReShare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + Filesystem::rename('/sub1/sub2/folder/file.txt', '/sub1/sub2/folder/inside/renamed.txt'); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); + + $this->assertAllUnchanged(); + } + + public function testOwnerRenameOutOfReShare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + Filesystem::rename('/sub1/sub2/folder/inside/file.txt', '/sub1/sub2/folder/renamed.txt'); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); + + $this->assertAllUnchanged(); + } + + public function testOwnerDeleteInShare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + Filesystem::unlink('/sub1/sub2/folder/file.txt'); + $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER4]); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3]); + + $this->assertAllUnchanged(); + } + + public function testOwnerDeleteInReShare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + Filesystem::unlink('/sub1/sub2/folder/inside/file.txt'); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); + + $this->assertAllUnchanged(); + } + + public function testOwnerUnshares() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + $folderInfo = $this->rootView->getFileInfo('/' . self::TEST_FILES_SHARING_API_USER1 . '/files/sub1/sub2/folder'); + $this->assertInstanceOf('\OC\Files\FileInfo', $folderInfo); + + $node = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1)->get('/sub1/sub2/folder'); + $shareManager = \OC::$server->getShareManager(); + $shares = $shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER1, \OCP\Share::SHARE_TYPE_USER, $node, true); + + foreach ($shares as $share) { + if ($share->getSharedWith() === self::TEST_FILES_SHARING_API_USER2) { + $shareManager->deleteShare($share); + } + } + + $this->assertEtagsForFoldersChanged([ + // direct recipient affected + self::TEST_FILES_SHARING_API_USER2, + ]); + + $this->assertAllUnchanged(); + } + + public function testOwnerUnsharesFlatReshares() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + $folderInfo = $this->rootView->getFileInfo('/' . self::TEST_FILES_SHARING_API_USER1 . '/files/sub1/sub2/folder/inside'); + $this->assertInstanceOf('\OC\Files\FileInfo', $folderInfo); + + $node = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1)->get('/sub1/sub2/folder/inside'); + $shareManager = \OC::$server->getShareManager(); + $shares = $shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER1, \OCP\Share::SHARE_TYPE_USER, $node, true); + + foreach ($shares as $share) { + $shareManager->deleteShare($share); + } + + $this->assertEtagsForFoldersChanged([ + // direct recipient affected + self::TEST_FILES_SHARING_API_USER4, + ]); + + $this->assertAllUnchanged(); + } + + public function testRecipientUnsharesFromSelf() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); + $ls = $this->rootView->getDirectoryContent('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/sub1/sub2/'); + $this->assertTrue( + $this->rootView->unlink('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/sub1/sub2/folder') + ); + $this->assertEtagsForFoldersChanged([ + // direct recipient affected + self::TEST_FILES_SHARING_API_USER2, + ]); + + $this->assertAllUnchanged(); + } + + public function testRecipientWritesToShare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); + Filesystem::file_put_contents('/sub1/sub2/folder/asd.txt', 'bar'); + $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER4]); + $this->assertEtagsForFoldersChanged([ + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3 + ]); + + $this->assertAllUnchanged(); + } + + public function testRecipientWritesToReshare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); + Filesystem::file_put_contents('/sub1/sub2/folder/inside/asd.txt', 'bar'); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); + + $this->assertAllUnchanged(); + } + + public function testRecipientWritesToOtherRecipientsReshare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER3); + Filesystem::file_put_contents('/sub1/sub2/folder/inside/asd.txt', 'bar'); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); + + $this->assertAllUnchanged(); + } + + public function testRecipientRenameInShare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); + Filesystem::rename('/sub1/sub2/folder/file.txt', '/sub1/sub2/folder/renamed.txt'); + $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER4]); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3]); + + $this->assertAllUnchanged(); + } + + public function testRecipientRenameInReShare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); + Filesystem::rename('/sub1/sub2/folder/inside/file.txt', '/sub1/sub2/folder/inside/renamed.txt'); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); + + $this->assertAllUnchanged(); + } + + public function testRecipientRenameResharedFolder() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); + Filesystem::rename('/directReshare', '/sub1/directReshare'); + $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); + $this->assertEtagsChanged([self::TEST_FILES_SHARING_API_USER2]); + + $this->assertEtagsChanged([self::TEST_FILES_SHARING_API_USER2], 'sub1'); + + $this->assertAllUnchanged(); + } + + public function testRecipientDeleteInShare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); + Filesystem::unlink('/sub1/sub2/folder/file.txt'); + $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER4]); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3]); + + $this->assertAllUnchanged(); + } + + public function testRecipientDeleteInReShare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); + Filesystem::unlink('/sub1/sub2/folder/inside/file.txt'); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); + + $this->assertAllUnchanged(); + } + + public function testReshareRecipientWritesToReshare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER4); + Filesystem::file_put_contents('/sub1/sub2/inside/asd.txt', 'bar'); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); + + $this->assertAllUnchanged(); + } + + public function testReshareRecipientRenameInReShare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER4); + Filesystem::rename('/sub1/sub2/inside/file.txt', '/sub1/sub2/inside/renamed.txt'); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); + + $this->assertAllUnchanged(); + } + + public function testReshareRecipientDeleteInReShare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER4); + Filesystem::unlink('/sub1/sub2/inside/file.txt'); + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); + + $this->assertAllUnchanged(); + } + + public function testRecipientUploadInDirectReshare() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); + Filesystem::file_put_contents('/directReshare/test.txt', 'sad'); + $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER3]); + $this->assertEtagsChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER4]); + + $this->assertAllUnchanged(); + } + + public function testEtagChangeOnPermissionsChange() { + $userFolder = $this->rootFolder->getUserFolder(self::TEST_FILES_SHARING_API_USER1); + $node = $userFolder->get('/sub1/sub2/folder'); + + $shares = $this->shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER1, \OCP\Share::SHARE_TYPE_USER, $node); + /** @var \OCP\Share\IShare[] $shares */ + $shares = array_filter($shares, function(\OCP\Share\IShare $share) { + return $share->getSharedWith() === self::TEST_FILES_SHARING_API_USER2; + }); + $this->assertCount(1, $shares); + + $share = $shares[0]; + $share->setPermissions(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_SHARE); + $this->shareManager->updateShare($share); + + $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER2]); + + $this->assertAllUnchanged(); + } +} diff --git a/apps/files_sharing/tests/ExpireSharesJobTest.php b/apps/files_sharing/tests/ExpireSharesJobTest.php new file mode 100644 index 00000000000..bb4f756e6c7 --- /dev/null +++ b/apps/files_sharing/tests/ExpireSharesJobTest.php @@ -0,0 +1,212 @@ + + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +use OCA\Files_Sharing\ExpireSharesJob; + +/** + * Class ExpireSharesJobTest + * + * @group DB + * + * @package OCA\Files_Sharing\Tests + */ +class ExpireSharesJobTest extends \Test\TestCase { + + /** + * @var ExpireSharesJob + */ + private $job; + + /** + * @var \OCP\IDBConnection + */ + private $connection; + + /** + * @var string + */ + private $user1; + + /** + * @var string + */ + private $user2; + + protected function setup() { + parent::setUp(); + + $this->connection = \OC::$server->getDatabaseConnection(); + // clear occasional leftover shares from other tests + $this->connection->executeUpdate('DELETE FROM `*PREFIX*share`'); + + $this->user1 = $this->getUniqueID('user1_'); + $this->user2 = $this->getUniqueID('user2_'); + + $userManager = \OC::$server->getUserManager(); + $userManager->createUser($this->user1, 'pass'); + $userManager->createUser($this->user2, 'pass'); + + \OC::registerShareHooks(); + + $this->job = new ExpireSharesJob(); + } + + protected function tearDown() { + $this->connection->executeUpdate('DELETE FROM `*PREFIX*share`'); + + $userManager = \OC::$server->getUserManager(); + $user1 = $userManager->get($this->user1); + if($user1) { + $user1->delete(); + } + $user2 = $userManager->get($this->user2); + if($user2) { + $user2->delete(); + } + + $this->logout(); + + parent::tearDown(); + } + + private function getShares() { + $shares = []; + $qb = $this->connection->getQueryBuilder(); + + $result = $qb->select('*') + ->from('share') + ->execute(); + + while ($row = $result->fetch()) { + $shares[] = $row; + } + $result->closeCursor(); + return $shares; + } + + public function dataExpireLinkShare() { + return [ + [false, '', false, false], + [false, '', true, false], + [true, 'P1D', false, true], + [true, 'P1D', true, false], + [true, 'P1W', false, true], + [true, 'P1W', true, false], + [true, 'P1M', false, true], + [true, 'P1M', true, false], + [true, 'P1Y', false, true], + [true, 'P1Y', true, false], + ]; + } + + /** + * @dataProvider dataExpireLinkShare + * + * @param bool addExpiration Should we add an expire date + * @param string $interval The dateInterval + * @param bool $addInterval If true add to the current time if false subtract + * @param bool $shouldExpire Should this share be expired + */ + public function testExpireLinkShare($addExpiration, $interval, $addInterval, $shouldExpire) { + $this->loginAsUser($this->user1); + + $view = new \OC\Files\View('/' . $this->user1 . '/'); + $view->mkdir('files/test'); + + $fileInfo = $view->getFileInfo('files/test'); + + $this->assertNotNull( + \OCP\Share::shareItem('folder', $fileInfo->getId(), \OCP\Share::SHARE_TYPE_LINK, null, \OCP\Constants::PERMISSION_READ), + 'Failed asserting that user 1 successfully shared "test" by link.' + ); + + $shares = $this->getShares(); + $this->assertCount(1, $shares); + reset($shares); + $share = current($shares); + + if ($addExpiration) { + $expire = new \DateTime(); + $expire->setTime(0, 0, 0); + if ($addInterval) { + $expire->add(new \DateInterval($interval)); + } else { + $expire->sub(new \DateInterval($interval)); + } + $expire = $expire->format('Y-m-d 00:00:00'); + + // Set expiration date to yesterday + $qb = $this->connection->getQueryBuilder(); + $qb->update('share') + ->set('expiration', $qb->createParameter('expiration')) + ->where($qb->expr()->eq('id', $qb->createParameter('id'))) + ->setParameter('id', $share['id']) + ->setParameter('expiration', $expire) + ->execute(); + + $shares = $this->getShares(); + $this->assertCount(1, $shares); + } + + $this->logout(); + + $this->job->run([]); + + $shares = $this->getShares(); + + if ($shouldExpire) { + $this->assertCount(0, $shares); + } else { + $this->assertCount(1, $shares); + } + } + + public function testDoNotExpireOtherShares() { + $this->loginAsUser($this->user1); + + $view = new \OC\Files\View('/' . $this->user1 . '/'); + $view->mkdir('files/test'); + + $fileInfo = $view->getFileInfo('files/test'); + + $this->assertNotNull( + \OCP\Share::shareItem('folder', $fileInfo->getId(), \OCP\Share::SHARE_TYPE_USER, $this->user2, \OCP\Constants::PERMISSION_READ), + 'Failed asserting that user 1 successfully shared "test" by link with user2.' + ); + + $shares = $this->getShares(); + $this->assertCount(1, $shares); + reset($shares); + $share = current($shares); + + $this->logout(); + + $this->job->run([]); + + $shares = $this->getShares(); + $this->assertCount(1, $shares); + } + +} + diff --git a/apps/files_sharing/tests/External/CacheTest.php b/apps/files_sharing/tests/External/CacheTest.php new file mode 100644 index 00000000000..6f207e1e4ab --- /dev/null +++ b/apps/files_sharing/tests/External/CacheTest.php @@ -0,0 +1,124 @@ + + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ +namespace OCA\Files_Sharing\Tests\External; + +use OCA\Files_Sharing\Tests\TestCase; + +/** + * Class Cache + * + * @group DB + * + * @package OCA\Files_Sharing\Tests\External + */ +class CacheTest extends TestCase { + + /** + * @var \OC\Files\Storage\Storage + **/ + private $storage; + + /** + * @var \OCA\Files_Sharing\External\Cache + */ + private $cache; + + /** + * @var string + */ + private $remoteUser; + + protected function setUp() { + parent::setUp(); + + $this->remoteUser = $this->getUniqueID('remoteuser'); + + $this->storage = $this->getMockBuilder('\OCA\Files_Sharing\External\Storage') + ->disableOriginalConstructor() + ->getMock(); + $this->storage + ->expects($this->any()) + ->method('getId') + ->will($this->returnValue('dummystorage::')); + $this->cache = new \OCA\Files_Sharing\External\Cache( + $this->storage, + 'http://example.com/owncloud', + $this->remoteUser + ); + $this->cache->put( + 'test.txt', + array( + 'mimetype' => 'text/plain', + 'size' => 5, + 'mtime' => 123, + ) + ); + } + + protected function tearDown() { + if ($this->cache) { + $this->cache->clear(); + } + parent::tearDown(); + } + + public function testGetInjectsOwnerDisplayName() { + $info = $this->cache->get('test.txt'); + $this->assertEquals( + $this->remoteUser . '@example.com/owncloud', + $info['displayname_owner'] + ); + } + + public function testGetReturnsFalseIfNotFound() { + $info = $this->cache->get('unexisting-entry.txt'); + $this->assertFalse($info); + } + + public function testGetFolderPopulatesOwner() { + $dirId = $this->cache->put( + 'subdir', + array( + 'mimetype' => 'httpd/unix-directory', + 'size' => 5, + 'mtime' => 123, + ) + ); + $this->cache->put( + 'subdir/contents.txt', + array( + 'mimetype' => 'text/plain', + 'size' => 5, + 'mtime' => 123, + ) + ); + + $results = $this->cache->getFolderContentsById($dirId); + $this->assertEquals(1, count($results)); + $this->assertEquals( + $this->remoteUser . '@example.com/owncloud', + $results[0]['displayname_owner'] + ); + } + +} diff --git a/apps/files_sharing/tests/External/ManagerTest.php b/apps/files_sharing/tests/External/ManagerTest.php new file mode 100644 index 00000000000..48a9098ae1d --- /dev/null +++ b/apps/files_sharing/tests/External/ManagerTest.php @@ -0,0 +1,253 @@ + + * @author Lukas Reschke + * @author Robin Appelman + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests\External; + +use OC\Files\Storage\StorageFactory; +use OCA\FederatedFileSharing\DiscoveryManager; +use OCA\Files_Sharing\External\Manager; +use OCA\Files_Sharing\External\MountProvider; +use OCA\Files_Sharing\Tests\TestCase; +use Test\Traits\UserTrait; + +/** + * Class ManagerTest + * + * @group DB + * + * @package OCA\Files_Sharing\Tests\External + */ +class ManagerTest extends TestCase { + use UserTrait; + + /** @var Manager **/ + private $manager; + + /** @var \OC\Files\Mount\Manager */ + private $mountManager; + + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $httpHelper; + + private $uid; + + /** + * @var \OCP\IUser + */ + private $user; + private $mountProvider; + + protected function setUp() { + parent::setUp(); + + $this->uid = $this->getUniqueID('user'); + $this->createUser($this->uid, ''); + $this->user = \OC::$server->getUserManager()->get($this->uid); + $this->mountManager = new \OC\Files\Mount\Manager(); + $this->httpHelper = $httpHelper = $this->getMockBuilder('\OC\HTTPHelper')->disableOriginalConstructor()->getMock(); + $discoveryManager = new DiscoveryManager( + \OC::$server->getMemCacheFactory(), + \OC::$server->getHTTPClientService() + ); + /** @var \OC\HTTPHelper $httpHelper */ + $this->manager = new Manager( + \OC::$server->getDatabaseConnection(), + $this->mountManager, + new StorageFactory(), + $httpHelper, + \OC::$server->getNotificationManager(), + $discoveryManager, + $this->uid + ); + $this->mountProvider = new MountProvider(\OC::$server->getDatabaseConnection(), function() { + return $this->manager; + }); + } + + private function setupMounts() { + $mounts = $this->mountProvider->getMountsForUser($this->user, new StorageFactory()); + foreach ($mounts as $mount) { + $this->mountManager->addMount($mount); + } + } + + public function testAddShare() { + + $shareData1 = [ + 'remote' => 'http://localhost', + 'token' => 'token1', + 'password' => '', + 'name' => '/SharedFolder', + 'owner' => 'foobar', + 'accepted' => false, + 'user' => $this->uid, + ]; + $shareData2 = $shareData1; + $shareData2['token'] = 'token2'; + $shareData3 = $shareData1; + $shareData3['token'] = 'token3'; + + // Add a share for "user" + $this->assertSame(null, call_user_func_array([$this->manager, 'addShare'], $shareData1)); + $openShares = $this->manager->getOpenShares(); + $this->assertCount(1, $openShares); + $this->assertExternalShareEntry($shareData1, $openShares[0], 1, '{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); + + $this->setupMounts(); + $this->assertNotMount('SharedFolder'); + $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); + + // Add a second share for "user" with the same name + $this->assertSame(null, call_user_func_array([$this->manager, 'addShare'], $shareData2)); + $openShares = $this->manager->getOpenShares(); + $this->assertCount(2, $openShares); + $this->assertExternalShareEntry($shareData1, $openShares[0], 1, '{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); + // New share falls back to "-1" appendix, because the name is already taken + $this->assertExternalShareEntry($shareData2, $openShares[1], 2, '{{TemporaryMountPointName#' . $shareData2['name'] . '}}-1'); + + $this->setupMounts(); + $this->assertNotMount('SharedFolder'); + $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); + $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}-1'); + + $this->httpHelper->expects($this->at(0)) + ->method('post') + ->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $openShares[0]['remote_id']), $this->anything()); + + // Accept the first share + $this->manager->acceptShare($openShares[0]['id']); + + // Check remaining shares - Accepted + $acceptedShares = self::invokePrivate($this->manager, 'getShares', [true]); + $this->assertCount(1, $acceptedShares); + $shareData1['accepted'] = true; + $this->assertExternalShareEntry($shareData1, $acceptedShares[0], 1, $shareData1['name']); + // Check remaining shares - Open + $openShares = $this->manager->getOpenShares(); + $this->assertCount(1, $openShares); + $this->assertExternalShareEntry($shareData2, $openShares[0], 2, '{{TemporaryMountPointName#' . $shareData2['name'] . '}}-1'); + + $this->setupMounts(); + $this->assertMount($shareData1['name']); + $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); + $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}-1'); + + // Add another share for "user" with the same name + $this->assertSame(null, call_user_func_array([$this->manager, 'addShare'], $shareData3)); + $openShares = $this->manager->getOpenShares(); + $this->assertCount(2, $openShares); + $this->assertExternalShareEntry($shareData2, $openShares[0], 2, '{{TemporaryMountPointName#' . $shareData2['name'] . '}}-1'); + // New share falls back to the original name (no "-\d", because the name is not taken) + $this->assertExternalShareEntry($shareData3, $openShares[1], 3, '{{TemporaryMountPointName#' . $shareData3['name'] . '}}'); + + $this->setupMounts(); + $this->assertMount($shareData1['name']); + $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); + $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}-1'); + + $this->httpHelper->expects($this->at(0)) + ->method('post') + ->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $openShares[1]['remote_id'] . '/decline'), $this->anything()); + + // Decline the third share + $this->manager->declineShare($openShares[1]['id']); + + $this->setupMounts(); + $this->assertMount($shareData1['name']); + $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); + $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}-1'); + + // Check remaining shares - Accepted + $acceptedShares = self::invokePrivate($this->manager, 'getShares', [true]); + $this->assertCount(1, $acceptedShares); + $shareData1['accepted'] = true; + $this->assertExternalShareEntry($shareData1, $acceptedShares[0], 1, $shareData1['name']); + // Check remaining shares - Open + $openShares = $this->manager->getOpenShares(); + $this->assertCount(1, $openShares); + $this->assertExternalShareEntry($shareData2, $openShares[0], 2, '{{TemporaryMountPointName#' . $shareData2['name'] . '}}-1'); + + $this->setupMounts(); + $this->assertMount($shareData1['name']); + $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); + $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}-1'); + + $this->httpHelper->expects($this->at(0)) + ->method('post') + ->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $openShares[0]['remote_id'] . '/decline'), $this->anything()); + $this->httpHelper->expects($this->at(1)) + ->method('post') + ->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $acceptedShares[0]['remote_id'] . '/decline'), $this->anything()); + + $this->manager->removeUserShares($this->uid); + $this->assertEmpty(self::invokePrivate($this->manager, 'getShares', [null]), 'Asserting all shares for the user have been deleted'); + + $this->mountManager->clear(); + self::invokePrivate($this->manager, 'setupMounts'); + $this->assertNotMount($shareData1['name']); + $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); + $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}-1'); + } + + /** + * @param array $expected + * @param array $actual + * @param int $share + * @param string $mountPoint + */ + protected function assertExternalShareEntry($expected, $actual, $share, $mountPoint) { + $this->assertEquals($expected['remote'], $actual['remote'], 'Asserting remote of a share #' . $share); + $this->assertEquals($expected['token'], $actual['share_token'], 'Asserting token of a share #' . $share); + $this->assertEquals($expected['name'], $actual['name'], 'Asserting name of a share #' . $share); + $this->assertEquals($expected['owner'], $actual['owner'], 'Asserting owner of a share #' . $share); + $this->assertEquals($expected['accepted'], (int) $actual['accepted'], 'Asserting accept of a share #' . $share); + $this->assertEquals($expected['user'], $actual['user'], 'Asserting user of a share #' . $share); + $this->assertEquals($mountPoint, $actual['mountpoint'], 'Asserting mountpoint of a share #' . $share); + } + + private function assertMount($mountPoint) { + $mountPoint = rtrim($mountPoint, '/'); + $mount = $this->mountManager->find($this->getFullPath($mountPoint)); + $this->assertInstanceOf('\OCA\Files_Sharing\External\Mount', $mount); + $this->assertInstanceOf('\OCP\Files\Mount\IMountPoint', $mount); + $this->assertEquals($this->getFullPath($mountPoint), rtrim($mount->getMountPoint(), '/')); + $storage = $mount->getStorage(); + $this->assertInstanceOf('\OCA\Files_Sharing\External\Storage', $storage); + } + + private function assertNotMount($mountPoint) { + $mountPoint = rtrim($mountPoint, '/'); + $mount = $this->mountManager->find($this->getFullPath($mountPoint)); + if ($mount) { + $this->assertInstanceOf('\OCP\Files\Mount\IMountPoint', $mount); + $this->assertNotEquals($this->getFullPath($mountPoint), rtrim($mount->getMountPoint(), '/')); + } else { + $this->assertNull($mount); + } + } + + private function getFullPath($path) { + return '/' . $this->uid . '/files' . $path; + } +} diff --git a/apps/files_sharing/tests/External/ScannerTest.php b/apps/files_sharing/tests/External/ScannerTest.php new file mode 100644 index 00000000000..f16e9952fce --- /dev/null +++ b/apps/files_sharing/tests/External/ScannerTest.php @@ -0,0 +1,82 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests\External; + +use OCA\Files_Sharing\External\Scanner; +use Test\TestCase; + +class ScannerTest extends TestCase { + /** @var \OCA\Files_Sharing\External\Scanner */ + protected $scanner; + /** @var \OCA\Files_Sharing\External\Storage|\PHPUnit_Framework_MockObject_MockObject */ + protected $storage; + /** @var \OC\Files\Cache\Cache|\PHPUnit_Framework_MockObject_MockObject */ + protected $cache; + + protected function setUp() { + parent::setUp(); + + $this->storage = $this->getMockBuilder('\OCA\Files_Sharing\External\Storage') + ->disableOriginalConstructor() + ->getMock(); + $this->cache = $this->getMockBuilder('\OC\Files\Cache\Cache') + ->disableOriginalConstructor() + ->getMock(); + $this->storage->expects($this->any()) + ->method('getCache') + ->willReturn($this->cache); + + $this->scanner = new Scanner($this->storage); + } + + public function testScanAll() { + $this->storage->expects($this->any()) + ->method('getShareInfo') + ->willReturn(['status' => 'success', 'data' => []]); + + // FIXME add real tests, we are currently only checking for + // Declaration of OCA\Files_Sharing\External\Scanner::*() should be + // compatible with OC\Files\Cache\Scanner::*() + $this->scanner->scanAll(); + $this->assertTrue(true); + } + + public function testScan() { + $this->storage->expects($this->any()) + ->method('getShareInfo') + ->willReturn(['status' => 'success', 'data' => []]); + + // FIXME add real tests, we are currently only checking for + // Declaration of OCA\Files_Sharing\External\Scanner::*() should be + // compatible with OC\Files\Cache\Scanner::*() + $this->scanner->scan('test', Scanner::SCAN_RECURSIVE); + $this->assertTrue(true); + } + + public function testScanFile() { + // FIXME add real tests, we are currently only checking for + // Declaration of OCA\Files_Sharing\External\Scanner::*() should be + // compatible with OC\Files\Cache\Scanner::*() + $this->scanner->scanFile('test', Scanner::SCAN_RECURSIVE); + $this->assertTrue(true); + } +} diff --git a/apps/files_sharing/tests/ExternalStorageTest.php b/apps/files_sharing/tests/ExternalStorageTest.php new file mode 100644 index 00000000000..c5ff4ad0236 --- /dev/null +++ b/apps/files_sharing/tests/ExternalStorageTest.php @@ -0,0 +1,97 @@ + + * @author Morris Jobke + * @author Robin Appelman + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +/** + * Tests for the external Storage class for remote shares. + * + * @group DB + */ +class ExternalStorageTest extends \Test\TestCase { + + function optionsProvider() { + return array( + array( + 'http://remoteserver:8080/owncloud', + 'http://remoteserver:8080/owncloud/public.php/webdav/', + ), + // extra slash + array( + 'http://remoteserver:8080/owncloud/', + 'http://remoteserver:8080/owncloud/public.php/webdav/', + ), + // extra path + array( + 'http://remoteserver:8080/myservices/owncloud/', + 'http://remoteserver:8080/myservices/owncloud/public.php/webdav/', + ), + // root path + array( + 'http://remoteserver:8080/', + 'http://remoteserver:8080/public.php/webdav/', + ), + // without port + array( + 'http://remoteserver/oc.test', + 'http://remoteserver/oc.test/public.php/webdav/', + ), + // https + array( + 'https://remoteserver/', + 'https://remoteserver/public.php/webdav/', + ), + ); + } + + /** + * @dataProvider optionsProvider + */ + public function testStorageMountOptions($inputUri, $baseUri) { + $certificateManager = \OC::$server->getCertificateManager(); + $storage = new TestSharingExternalStorage( + array( + 'remote' => $inputUri, + 'owner' => 'testOwner', + 'mountpoint' => 'remoteshare', + 'token' => 'abcdef', + 'password' => '', + 'manager' => null, + 'certificateManager' => $certificateManager + ) + ); + $this->assertEquals($baseUri, $storage->getBaseUri()); + } +} + +/** + * Dummy subclass to make it possible to access private members + */ +class TestSharingExternalStorage extends \OCA\Files_Sharing\External\Storage { + + public function getBaseUri() { + return $this->createBaseUri(); + } +} diff --git a/apps/files_sharing/tests/GroupEtagPropagationTest.php b/apps/files_sharing/tests/GroupEtagPropagationTest.php new file mode 100644 index 00000000000..c78be79eaa1 --- /dev/null +++ b/apps/files_sharing/tests/GroupEtagPropagationTest.php @@ -0,0 +1,122 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +use OC\Files\Filesystem; +use OC\Files\View; + +/** + * @group DB + * + * @package OCA\Files_Sharing\Tests + */ +class GroupEtagPropagationTest extends PropagationTestCase { + /** + * "user1" creates /test, /test/sub and shares with group1 + * "user2" (in group1) reshares /test with group2 and reshared /test/sub with group3 + * "user3" (in group 2) + * "user4" (in group 3) + */ + protected function setUpShares() { + $this->fileIds[self::TEST_FILES_SHARING_API_USER1] = []; + $this->fileIds[self::TEST_FILES_SHARING_API_USER2] = []; + $this->fileIds[self::TEST_FILES_SHARING_API_USER3] = []; + $this->fileIds[self::TEST_FILES_SHARING_API_USER4] = []; + + $this->rootView = new View(''); + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + $view1 = new View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files'); + $view1->mkdir('/test/sub'); + + $this->share( + \OCP\Share::SHARE_TYPE_GROUP, + '/test', + self::TEST_FILES_SHARING_API_USER1, + 'group1', + \OCP\Constants::PERMISSION_ALL + ); + $this->fileIds[self::TEST_FILES_SHARING_API_USER1][''] = $view1->getFileInfo('')->getId(); + $this->fileIds[self::TEST_FILES_SHARING_API_USER1]['test'] = $view1->getFileInfo('test')->getId(); + $this->fileIds[self::TEST_FILES_SHARING_API_USER1]['test/sub'] = $view1->getFileInfo('test/sub')->getId(); + + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); + $view2 = new View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); + + $this->share( + \OCP\Share::SHARE_TYPE_GROUP, + '/test', + self::TEST_FILES_SHARING_API_USER2, + 'group2', + \OCP\Constants::PERMISSION_ALL + ); + $this->share( + \OCP\Share::SHARE_TYPE_GROUP, + '/test/sub', + self::TEST_FILES_SHARING_API_USER2, + 'group3', + \OCP\Constants::PERMISSION_ALL + ); + + $this->fileIds[self::TEST_FILES_SHARING_API_USER2][''] = $view2->getFileInfo('')->getId(); + $this->fileIds[self::TEST_FILES_SHARING_API_USER2]['test'] = $view2->getFileInfo('test')->getId(); + $this->fileIds[self::TEST_FILES_SHARING_API_USER2]['test/sub'] = $view2->getFileInfo('test/sub')->getId(); + + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER3); + $view3 = new View('/' . self::TEST_FILES_SHARING_API_USER3 . '/files'); + $this->fileIds[self::TEST_FILES_SHARING_API_USER3][''] = $view3->getFileInfo('')->getId(); + $this->fileIds[self::TEST_FILES_SHARING_API_USER3]['test'] = $view3->getFileInfo('test')->getId(); + $this->fileIds[self::TEST_FILES_SHARING_API_USER3]['test/sub'] = $view3->getFileInfo('test/sub')->getId(); + + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER4); + $view4 = new View('/' . self::TEST_FILES_SHARING_API_USER4 . '/files'); + $this->fileIds[self::TEST_FILES_SHARING_API_USER4][''] = $view4->getFileInfo('')->getId(); + $this->fileIds[self::TEST_FILES_SHARING_API_USER4]['sub'] = $view4->getFileInfo('sub')->getId(); + + foreach ($this->fileIds as $user => $ids) { + $this->loginAsUser($user); + foreach ($ids as $id) { + $path = $this->rootView->getPath($id); + $this->fileEtags[$id] = $this->rootView->getFileInfo($path)->getEtag(); + } + } + } + + public function testGroupReShareRecipientWrites() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER3); + + Filesystem::file_put_contents('/test/sub/file.txt', 'asd'); + + $this->assertEtagsChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); + + $this->assertAllUnchanged(); + } + + public function testGroupReShareSubFolderRecipientWrites() { + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER4); + + Filesystem::file_put_contents('/sub/file.txt', 'asd'); + + $this->assertEtagsChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); + + $this->assertAllUnchanged(); + } +} diff --git a/apps/files_sharing/tests/HelperTest.php b/apps/files_sharing/tests/HelperTest.php new file mode 100644 index 00000000000..6382a8e18ac --- /dev/null +++ b/apps/files_sharing/tests/HelperTest.php @@ -0,0 +1,50 @@ + + * @author Morris Jobke + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +/** + * Class HelperTest + * + * @group DB + */ +class HelperTest extends TestCase { + + /** + * test set and get share folder + */ + function testSetGetShareFolder() { + $this->assertSame('/', \OCA\Files_Sharing\Helper::getShareFolder()); + + \OCA\Files_Sharing\Helper::setShareFolder('/Shared/Folder'); + + $sharedFolder = \OCA\Files_Sharing\Helper::getShareFolder(); + $this->assertSame('/Shared/Folder', \OCA\Files_Sharing\Helper::getShareFolder()); + $this->assertTrue(\OC\Files\Filesystem::is_dir($sharedFolder)); + + // cleanup + \OC::$server->getConfig()->deleteSystemValue('share_folder'); + + } + +} diff --git a/apps/files_sharing/tests/LockingTest.php b/apps/files_sharing/tests/LockingTest.php new file mode 100644 index 00000000000..be6fa04437a --- /dev/null +++ b/apps/files_sharing/tests/LockingTest.php @@ -0,0 +1,113 @@ + + * @author Robin Appelman + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +use OC\Files\Filesystem; +use OC\Files\View; +use OCP\Lock\ILockingProvider; + +/** + * Class LockingTest + * + * @group DB + * + * @package OCA\Files_Sharing\Tests + */ +class LockingTest extends TestCase { + /** + * @var \Test\Util\User\Dummy + */ + private $userBackend; + + private $ownerUid; + private $recipientUid; + + public function setUp() { + parent::setUp(); + + $this->userBackend = new \Test\Util\User\Dummy(); + \OC::$server->getUserManager()->registerBackend($this->userBackend); + + $this->ownerUid = $this->getUniqueID('owner_'); + $this->recipientUid = $this->getUniqueID('recipient_'); + $this->userBackend->createUser($this->ownerUid, ''); + $this->userBackend->createUser($this->recipientUid, ''); + + $this->loginAsUser($this->ownerUid); + Filesystem::mkdir('/foo'); + Filesystem::file_put_contents('/foo/bar.txt', 'asd'); + $fileId = Filesystem::getFileInfo('/foo/bar.txt')->getId(); + + $this->share( + \OCP\Share::SHARE_TYPE_USER, + '/foo/bar.txt', + $this->ownerUid, + $this->recipientUid, + \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE + ); + + $this->loginAsUser($this->recipientUid); + $this->assertTrue(Filesystem::file_exists('bar.txt')); + } + + public function tearDown() { + \OC::$server->getUserManager()->removeBackend($this->userBackend); + parent::tearDown(); + } + + /** + * @expectedException \OCP\Lock\LockedException + */ + public function testLockAsRecipient() { + $this->loginAsUser($this->ownerUid); + + Filesystem::initMountPoints($this->recipientUid); + $recipientView = new View('/' . $this->recipientUid . '/files'); + $recipientView->lockFile('bar.txt', ILockingProvider::LOCK_EXCLUSIVE); + + Filesystem::rename('/foo', '/asd'); + } + + public function testUnLockAsRecipient() { + $this->loginAsUser($this->ownerUid); + + Filesystem::initMountPoints($this->recipientUid); + $recipientView = new View('/' . $this->recipientUid . '/files'); + $recipientView->lockFile('bar.txt', ILockingProvider::LOCK_EXCLUSIVE); + $recipientView->unlockFile('bar.txt', ILockingProvider::LOCK_EXCLUSIVE); + + $this->assertTrue(Filesystem::rename('/foo', '/asd')); + } + + public function testChangeLock() { + + Filesystem::initMountPoints($this->recipientUid); + $recipientView = new View('/' . $this->recipientUid . '/files'); + $recipientView->lockFile('bar.txt', ILockingProvider::LOCK_SHARED); + $recipientView->changeLock('bar.txt', ILockingProvider::LOCK_EXCLUSIVE); + $recipientView->unlockFile('bar.txt', ILockingProvider::LOCK_EXCLUSIVE); + + $this->assertTrue(true); + } +} diff --git a/apps/files_sharing/tests/Middleware/SharingCheckMiddlewareTest.php b/apps/files_sharing/tests/Middleware/SharingCheckMiddlewareTest.php new file mode 100644 index 00000000000..e80be772a92 --- /dev/null +++ b/apps/files_sharing/tests/Middleware/SharingCheckMiddlewareTest.php @@ -0,0 +1,287 @@ + + * @author Morris Jobke + * @author Roeland Jago Douma + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Middleware; +use OCP\AppFramework\Http\NotFoundResponse; +use OCP\Files\NotFoundException; +use OCP\AppFramework\Utility\IControllerMethodReflector; +use OCA\Files_Sharing\Exceptions\S2SException; +use OCP\AppFramework\Http\JSONResponse; + +/** + * @package OCA\Files_Sharing\Middleware\SharingCheckMiddleware + */ +class SharingCheckMiddlewareTest extends \Test\TestCase { + + /** @var \OCP\IConfig */ + private $config; + /** @var \OCP\App\IAppManager */ + private $appManager; + /** @var SharingCheckMiddleware */ + private $sharingCheckMiddleware; + /** @var \OCP\AppFramework\Controller */ + private $controllerMock; + /** @var IControllerMethodReflector */ + private $reflector; + + protected function setUp() { + $this->config = $this->getMockBuilder('\OCP\IConfig') + ->disableOriginalConstructor()->getMock(); + $this->appManager = $this->getMockBuilder('\OCP\App\IAppManager') + ->disableOriginalConstructor()->getMock(); + $this->controllerMock = $this->getMockBuilder('\OCP\AppFramework\Controller') + ->disableOriginalConstructor()->getMock(); + $this->reflector = $this->getMockBuilder('\OCP\AppFramework\Utility\IControllerMethodReflector') + ->disableOriginalConstructor()->getMock(); + + $this->sharingCheckMiddleware = new SharingCheckMiddleware( + 'files_sharing', + $this->config, + $this->appManager, + $this->reflector); + } + + public function testIsSharingEnabledWithAppEnabled() { + $this->appManager + ->expects($this->once()) + ->method('isEnabledForUser') + ->with('files_sharing') + ->will($this->returnValue(true)); + + $this->assertTrue(self::invokePrivate($this->sharingCheckMiddleware, 'isSharingEnabled')); + } + + public function testIsSharingEnabledWithAppDisabled() { + $this->appManager + ->expects($this->once()) + ->method('isEnabledForUser') + ->with('files_sharing') + ->will($this->returnValue(false)); + + $this->assertFalse(self::invokePrivate($this->sharingCheckMiddleware, 'isSharingEnabled')); + } + + public function testIsLinkSharingEnabledWithEverythinEnabled() { + $this->config + ->expects($this->at(0)) + ->method('getAppValue') + ->with('core', 'shareapi_enabled', 'yes') + ->will($this->returnValue('yes')); + + $this->config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('core', 'shareapi_allow_links', 'yes') + ->will($this->returnValue('yes')); + + $this->assertTrue(self::invokePrivate($this->sharingCheckMiddleware, 'isLinkSharingEnabled')); + } + + + public function testIsLinkSharingEnabledWithLinkSharingDisabled() { + $this->config + ->expects($this->at(0)) + ->method('getAppValue') + ->with('core', 'shareapi_enabled', 'yes') + ->will($this->returnValue('yes')); + + $this->config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('core', 'shareapi_allow_links', 'yes') + ->will($this->returnValue('no')); + + $this->assertFalse(self::invokePrivate($this->sharingCheckMiddleware, 'isLinkSharingEnabled')); + } + + public function testIsLinkSharingEnabledWithSharingAPIDisabled() { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('core', 'shareapi_enabled', 'yes') + ->will($this->returnValue('no')); + + $this->assertFalse(self::invokePrivate($this->sharingCheckMiddleware, 'isLinkSharingEnabled')); + } + + public function externalSharesChecksDataProvider() { + + $data = []; + + foreach ([false, true] as $annIn) { + foreach ([false, true] as $annOut) { + foreach ([false, true] as $confIn) { + foreach ([false, true] as $confOut) { + + $res = true; + if (!$annIn && !$confIn) { + $res = false; + } elseif (!$annOut && !$confOut) { + $res = false; + } + + $d = [ + [ + ['NoIncomingFederatedSharingRequired', $annIn], + ['NoOutgoingFederatedSharingRequired', $annOut], + ], + [ + ['files_sharing', 'incoming_server2server_share_enabled', 'yes', $confIn ? 'yes' : 'no'], + ['files_sharing', 'outgoing_server2server_share_enabled', 'yes', $confOut ? 'yes' : 'no'], + ], + $res + ]; + + $data[] = $d; + } + } + } + } + + return $data; + } + + /** + * @dataProvider externalSharesChecksDataProvider + */ + public function testExternalSharesChecks($annotations, $config, $expectedResult) { + $this->reflector + ->expects($this->atLeastOnce()) + ->method('hasAnnotation') + ->will($this->returnValueMap($annotations)); + + $this->config + ->method('getAppValue') + ->will($this->returnValueMap($config)); + + $this->assertEquals($expectedResult, self::invokePrivate($this->sharingCheckMiddleware, 'externalSharesChecks')); + } + + /** + * @dataProvider externalSharesChecksDataProvider + */ + public function testBeforeControllerWithExternalShareControllerWithSharingEnabled($annotations, $config, $noException) { + $this->appManager + ->expects($this->once()) + ->method('isEnabledForUser') + ->with('files_sharing') + ->will($this->returnValue(true)); + + $this->reflector + ->expects($this->atLeastOnce()) + ->method('hasAnnotation') + ->will($this->returnValueMap($annotations)); + + $this->config + ->method('getAppValue') + ->will($this->returnValueMap($config)); + + $controller = $this->getMockBuilder('\OCA\Files_Sharing\Controllers\ExternalSharesController') + ->disableOriginalConstructor()->getMock(); + + $exceptionThrown = false; + + try { + $this->sharingCheckMiddleware->beforeController($controller, 'myMethod'); + } catch (\OCA\Files_Sharing\Exceptions\S2SException $exception) { + $exceptionThrown = true; + } + + $this->assertNotEquals($noException, $exceptionThrown); + } + + public function testBeforeControllerWithShareControllerWithSharingEnabled() { + $this->appManager + ->expects($this->once()) + ->method('isEnabledForUser') + ->with('files_sharing') + ->will($this->returnValue(true)); + + $this->config + ->expects($this->at(0)) + ->method('getAppValue') + ->with('core', 'shareapi_enabled', 'yes') + ->will($this->returnValue('yes')); + + $this->config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('core', 'shareapi_allow_links', 'yes') + ->will($this->returnValue('yes')); + + $controller = $this->getMockBuilder('\OCA\Files_Sharing\Controllers\ShareController') + ->disableOriginalConstructor()->getMock(); + + $this->sharingCheckMiddleware->beforeController($controller, 'myMethod'); + } + + /** + * @expectedException \OCP\Files\NotFoundException + * @expectedExceptionMessage Link sharing is disabled + */ + public function testBeforeControllerWithShareControllerWithSharingEnabledAPIDisabled() { + $this->appManager + ->expects($this->once()) + ->method('isEnabledForUser') + ->with('files_sharing') + ->will($this->returnValue(true)); + + $controller = $this->getMockBuilder('\OCA\Files_Sharing\Controllers\ShareController') + ->disableOriginalConstructor()->getMock(); + + $this->sharingCheckMiddleware->beforeController($controller, 'myMethod'); + } + + /** + * @expectedException \OCP\Files\NotFoundException + * @expectedExceptionMessage Sharing is disabled. + */ + public function testBeforeControllerWithSharingDisabled() { + $this->appManager + ->expects($this->once()) + ->method('isEnabledForUser') + ->with('files_sharing') + ->will($this->returnValue(false)); + + $this->sharingCheckMiddleware->beforeController($this->controllerMock, 'myMethod'); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage My Exception message + */ + public function testAfterExceptionWithRegularException() { + $this->sharingCheckMiddleware->afterException($this->controllerMock, 'myMethod', new \Exception('My Exception message')); + } + + public function testAfterExceptionWithNotFoundException() { + $this->assertEquals(new NotFoundResponse(), $this->sharingCheckMiddleware->afterException($this->controllerMock, 'myMethod', new NotFoundException('My Exception message'))); + } + + public function testAfterExceptionWithS2SException() { + $this->assertEquals(new JSONResponse('My Exception message', 405), $this->sharingCheckMiddleware->afterException($this->controllerMock, 'myMethod', new S2SException('My Exception message'))); + } + + +} diff --git a/apps/files_sharing/tests/MigrationTest.php b/apps/files_sharing/tests/MigrationTest.php new file mode 100644 index 00000000000..4b44d7a367e --- /dev/null +++ b/apps/files_sharing/tests/MigrationTest.php @@ -0,0 +1,352 @@ + + * @author Morris Jobke + * @author Roeland Jago Douma + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + + +use OCA\Files_Sharing\Migration; + +/** + * Class MigrationTest + * + * @group DB + */ +class MigrationTest extends TestCase { + + /** @var \OCP\IDBConnection */ + private $connection; + + /** @var Migration */ + private $migration; + + private $table = 'share'; + + public function setUp() { + parent::setUp(); + + $this->connection = \OC::$server->getDatabaseConnection(); + $this->migration = new Migration($this->connection); + + $this->cleanDB(); + } + + public function tearDown() { + parent::tearDown(); + $this->cleanDB(); + } + + private function cleanDB() { + $query = $this->connection->getQueryBuilder(); + $query->delete($this->table)->execute(); + } + + public function addDummyValues() { + $query = $this->connection->getQueryBuilder(); + $query->insert($this->table) + ->values( + array( + 'share_type' => $query->createParameter('share_type'), + 'share_with' => $query->createParameter('share_with'), + 'uid_owner' => $query->createParameter('uid_owner'), + 'uid_initiator' => $query->createParameter('uid_initiator'), + 'parent' => $query->createParameter('parent'), + 'item_type' => $query->createParameter('item_type'), + 'item_source' => $query->createParameter('item_source'), + 'item_target' => $query->createParameter('item_target'), + 'file_source' => $query->createParameter('file_source'), + 'file_target' => $query->createParameter('file_target'), + 'permissions' => $query->createParameter('permissions'), + 'stime' => $query->createParameter('stime'), + ) + ); + // shared contact, shouldn't be modified + $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_CONTACT) + ->setParameter('share_with', 'user1') + ->setParameter('uid_owner', 'owner1') + ->setParameter('uid_initiator', '') + ->setParameter('parent', null) + ->setParameter('item_type', 'contact') + ->setParameter('item_source', '2') + ->setParameter('item_target', '/2') + ->setParameter('file_source', null) + ->setParameter('file_target', null) + ->setParameter('permissions', 31) + ->setParameter('stime', time()); + $this->assertSame(1, + $query->execute() + ); + // shared calendar, shouldn't be modified + $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) + ->setParameter('share_with', 'user1') + ->setParameter('uid_owner', 'owner1') + ->setParameter('uid_initiator', '') + ->setParameter('parent', null) + ->setParameter('item_type', 'calendar') + ->setParameter('item_source', '2') + ->setParameter('item_target', '/2') + ->setParameter('file_source', null) + ->setParameter('file_target', null) + ->setParameter('permissions', 31) + ->setParameter('stime', time()); + $this->assertSame(1, + $query->execute() + ); + // single user share, shouldn't be modified + $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) + ->setParameter('share_with', 'user1') + ->setParameter('uid_owner', 'owner1') + ->setParameter('uid_initiator', '') + ->setParameter('parent', null) + ->setParameter('item_type', 'file') + ->setParameter('item_source', '2') + ->setParameter('item_target', '/2') + ->setParameter('file_source', 2) + ->setParameter('file_target', '/foo') + ->setParameter('permissions', 31) + ->setParameter('stime', time()); + $this->assertSame(1, + $query->execute() + ); + // single group share, shouldn't be modified + $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_GROUP) + ->setParameter('share_with', 'group1') + ->setParameter('uid_owner', 'owner1') + ->setParameter('uid_initiator', '') + ->setParameter('parent', null) + ->setParameter('item_type', 'file') + ->setParameter('item_source', '2') + ->setParameter('item_target', '/2') + ->setParameter('file_source', 2) + ->setParameter('file_target', '/foo') + ->setParameter('permissions', 31) + ->setParameter('stime', time()); + $this->assertSame(1, + $query->execute() + ); + $parent = $query->getLastInsertId(); + // unique target for group share, shouldn't be modified + $query->setParameter('share_type', 2) + ->setParameter('share_with', 'group1') + ->setParameter('uid_owner', 'owner1') + ->setParameter('uid_initiator', '') + ->setParameter('parent', $parent) + ->setParameter('item_type', 'file') + ->setParameter('item_source', '2') + ->setParameter('item_target', '/2') + ->setParameter('file_source', 2) + ->setParameter('file_target', '/foo renamed') + ->setParameter('permissions', 31) + ->setParameter('stime', time()); + $this->assertSame(1, + $query->execute() + ); + // first user share, shouldn't be modified + $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) + ->setParameter('share_with', 'user1') + ->setParameter('uid_owner', 'owner2') + ->setParameter('uid_initiator', '') + ->setParameter('parent', null) + ->setParameter('item_type', 'file') + ->setParameter('item_source', '2') + ->setParameter('item_target', '/2') + ->setParameter('file_source', 2) + ->setParameter('file_target', '/foobar') + ->setParameter('permissions', 31) + ->setParameter('stime', time()); + $this->assertSame(1, + $query->execute() + ); + $parent = $query->getLastInsertId(); + // first re-share, should be attached to the first user share after migration + $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) + ->setParameter('share_with', 'user2') + ->setParameter('uid_owner', 'user1') + ->setParameter('uid_initiator', '') + ->setParameter('parent', $parent) + ->setParameter('item_type', 'file') + ->setParameter('item_source', '2') + ->setParameter('item_target', '/2') + ->setParameter('file_source', 2) + ->setParameter('file_target', '/foobar') + ->setParameter('permissions', 31) + ->setParameter('stime', time()); + $this->assertSame(1, + $query->execute() + ); + $parent = $query->getLastInsertId(); + // second re-share, should be attached to the first user share after migration + $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) + ->setParameter('share_with', 'user3') + ->setParameter('uid_owner', 'user2') + ->setParameter('uid_initiator', '') + ->setParameter('parent', $parent) + ->setParameter('item_type', 'file') + ->setParameter('item_source', '2') + ->setParameter('item_target', '/2') + ->setParameter('file_source', 2) + ->setParameter('file_target', '/foobar') + ->setParameter('permissions', 31) + ->setParameter('stime', time()); + $this->assertSame(1, + $query->execute() + ); + $parent = $query->getLastInsertId(); + // third re-share, should be attached to the first user share after migration + $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_REMOTE) + ->setParameter('share_with', 'user@server.com') + ->setParameter('uid_owner', 'user3') + ->setParameter('uid_initiator', '') + ->setParameter('parent', $parent) + ->setParameter('item_type', 'file') + ->setParameter('item_source', '2') + ->setParameter('item_target', '/2') + ->setParameter('file_source', 2) + ->setParameter('file_target', '/foobar') + ->setParameter('permissions', 31) + ->setParameter('stime', time()); + $this->assertSame(1, + $query->execute() + ); + + // Link reshare should keep its parent + $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_LINK) + ->setParameter('share_with', null) + ->setParameter('uid_owner', 'user3') + ->setParameter('uid_initiator', '') + ->setParameter('parent', $parent) + ->setParameter('item_type', 'file') + ->setParameter('item_source', '2') + ->setParameter('item_target', '/2') + ->setParameter('file_source', 2) + ->setParameter('file_target', '/foobar') + ->setParameter('permissions', 31) + ->setParameter('stime', time()); + $this->assertSame(1, + $query->execute() + ); + } + + public function testRemoveReShares() { + $this->addDummyValues(); + $this->migration->removeReShares(); + $this->verifyResult(); + } + + public function verifyResult() { + $query = $this->connection->getQueryBuilder(); + $query->select('*')->from($this->table)->orderBy('id'); + $result = $query->execute()->fetchAll(); + $this->assertSame(10, count($result)); + + // shares which shouldn't be modified + for ($i = 0; $i < 4; $i++) { + $this->assertSame('owner1', $result[$i]['uid_owner']); + $this->assertEmpty($result[$i]['uid_initiator']); + $this->assertNull($result[$i]['parent']); + } + // group share with unique target + $this->assertSame('owner1', $result[4]['uid_owner']); + $this->assertEmpty($result[4]['uid_initiator']); + $this->assertNotEmpty($result[4]['parent']); + // initial user share which was re-shared + $this->assertSame('owner2', $result[5]['uid_owner']); + $this->assertEmpty($result[5]['uid_initiator']); + $this->assertNull($result[5]['parent']); + // flatted re-shares + for($i = 6; $i < 9; $i++) { + $this->assertSame('owner2', $result[$i]['uid_owner']); + $user = 'user' . ($i - 5); + $this->assertSame($user, $result[$i]['uid_initiator']); + $this->assertNull($result[$i]['parent']); + } + + /* + * The link share is flattend but has an owner to avoid invisible shares + * see: https://github.com/owncloud/core/pull/22317 + */ + $this->assertSame('owner2', $result[9]['uid_owner']); + $this->assertSame('user3', $result[9]['uid_initiator']); + $this->assertSame($result[7]['id'], $result[9]['parent']); + } + + public function test1001DeepReshares() { + $parent = null; + for ($i = 0; $i < 1001; $i++) { + $query = $this->connection->getQueryBuilder(); + $query->insert($this->table) + ->values( + [ + 'share_type' => $query->createParameter('share_type'), + 'share_with' => $query->createParameter('share_with'), + 'uid_owner' => $query->createParameter('uid_owner'), + 'uid_initiator' => $query->createParameter('uid_initiator'), + 'parent' => $query->createParameter('parent'), + 'item_type' => $query->createParameter('item_type'), + 'item_source' => $query->createParameter('item_source'), + 'item_target' => $query->createParameter('item_target'), + 'file_source' => $query->createParameter('file_source'), + 'file_target' => $query->createParameter('file_target'), + 'permissions' => $query->createParameter('permissions'), + 'stime' => $query->createParameter('stime'), + ] + ) + ->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) + ->setParameter('share_with', 'user'.($i+1)) + ->setParameter('uid_owner', 'user'.($i)) + ->setParameter('uid_initiator', null) + ->setParameter('parent', $parent) + ->setParameter('item_type', 'file') + ->setParameter('item_source', '2') + ->setParameter('item_target', '/2') + ->setParameter('file_source', 2) + ->setParameter('file_target', '/foobar') + ->setParameter('permissions', 31) + ->setParameter('stime', time()); + + $this->assertSame(1, $query->execute()); + $parent = $query->getLastInsertId(); + } + + $this->migration->removeReShares(); + $this->migration->updateInitiatorInfo(); + + $qb = $this->connection->getQueryBuilder(); + + $stmt = $qb->select('id', 'share_with', 'uid_owner', 'uid_initiator', 'parent') + ->from('share') + ->orderBy('id', 'asc') + ->execute(); + + $i = 0; + while($share = $stmt->fetch()) { + $this->assertEquals('user'.($i+1), $share['share_with']); + $this->assertEquals('user' . ($i), $share['uid_initiator']); + $this->assertEquals('user0', $share['uid_owner']); + $this->assertEquals(null, $share['parent']); + $i++; + } + $stmt->closeCursor(); + $this->assertEquals(1001, $i); + } +} diff --git a/apps/files_sharing/tests/PermissionsTest.php b/apps/files_sharing/tests/PermissionsTest.php new file mode 100644 index 00000000000..f22003c468c --- /dev/null +++ b/apps/files_sharing/tests/PermissionsTest.php @@ -0,0 +1,162 @@ + + * @author Joas Schilling + * @author Robin Appelman + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + + +namespace OCA\Files_Sharing\Tests; + +use OC\Files\Cache\Cache; +use OC\Files\Storage\Storage; +use OC\Files\View; + +/** + * Class PermissionsTest + * + * @group DB + */ +class PermissionsTest extends TestCase { + + /** @var Storage */ + private $sharedStorageRestrictedShare; + + /** @var Storage */ + private $sharedCacheRestrictedShare; + + /** @var View */ + private $secondView; + + /** @var Storage */ + private $ownerStorage; + + /** @var Storage */ + private $sharedStorage; + + /** @var Cache */ + private $sharedCache; + + /** @var Cache */ + private $ownerCache; + + protected function setUp() { + parent::setUp(); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + // prepare user1's dir structure + $textData = "dummy file data\n"; + $this->view->mkdir('container'); + $this->view->mkdir('container/shareddir'); + $this->view->mkdir('container/shareddir/subdir'); + $this->view->mkdir('container/shareddirrestricted'); + $this->view->mkdir('container/shareddirrestricted/subdir'); + $this->view->file_put_contents('container/shareddir/textfile.txt', $textData); + $this->view->file_put_contents('container/shareddirrestricted/textfile1.txt', $textData); + + list($this->ownerStorage, $internalPath) = $this->view->resolvePath(''); + $this->ownerCache = $this->ownerStorage->getCache(); + $this->ownerStorage->getScanner()->scan(''); + + // share "shareddir" with user2 + $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1); + + $node = $rootFolder->get('container/shareddir'); + $share = $this->shareManager->newShare(); + $share->setNode($node) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setPermissions(\OCP\Constants::PERMISSION_ALL); + $this->shareManager->createShare($share); + + $node = $rootFolder->get('container/shareddirrestricted'); + $share = $this->shareManager->newShare(); + $share->setNode($node) + ->setShareType(\OCP\Share::SHARE_TYPE_USER) + ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) + ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) + ->setPermissions(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE); + $this->shareManager->createShare($share); + + // login as user2 + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + // retrieve the shared storage + $this->secondView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2); + list($this->sharedStorage, $internalPath) = $this->secondView->resolvePath('files/shareddir'); + list($this->sharedStorageRestrictedShare, $internalPath) = $this->secondView->resolvePath('files/shareddirrestricted'); + $this->sharedCache = $this->sharedStorage->getCache(); + $this->sharedCacheRestrictedShare = $this->sharedStorageRestrictedShare->getCache(); + } + + protected function tearDown() { + if ($this->sharedCache) { + $this->sharedCache->clear(); + } + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $shares = $this->shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER1, \OCP\Share::SHARE_TYPE_USER); + foreach ($shares as $share) { + $this->shareManager->deleteShare($share); + } + + $this->view->deleteAll('container'); + + $this->ownerCache->clear(); + + parent::tearDown(); + } + + /** + * Test that the permissions of shared directory are returned correctly + */ + function testGetPermissions() { + $sharedDirPerms = $this->sharedStorage->getPermissions('shareddir'); + $this->assertEquals(31, $sharedDirPerms); + $sharedDirPerms = $this->sharedStorage->getPermissions('shareddir/textfile.txt'); + $this->assertEquals(31, $sharedDirPerms); + $sharedDirRestrictedPerms = $this->sharedStorageRestrictedShare->getPermissions('shareddirrestricted'); + $this->assertEquals(7, $sharedDirRestrictedPerms); + $sharedDirRestrictedPerms = $this->sharedStorageRestrictedShare->getPermissions('shareddirrestricted/textfile.txt'); + $this->assertEquals(7, $sharedDirRestrictedPerms); + } + + /** + * Test that the permissions of shared directory are returned correctly + */ + function testGetDirectoryPermissions() { + $contents = $this->secondView->getDirectoryContent('files/shareddir'); + $this->assertEquals('subdir', $contents[0]['name']); + $this->assertEquals(31, $contents[0]['permissions']); + $this->assertEquals('textfile.txt', $contents[1]['name']); + // 27 is correct because create is reserved to folders only - requires more unit tests overall to ensure this + $this->assertEquals(27, $contents[1]['permissions']); + $contents = $this->secondView->getDirectoryContent('files/shareddirrestricted'); + $this->assertEquals('subdir', $contents[0]['name']); + $this->assertEquals(7, $contents[0]['permissions']); + $this->assertEquals('textfile1.txt', $contents[1]['name']); + // 3 is correct because create is reserved to folders only + $this->assertEquals(3, $contents[1]['permissions']); + } +} diff --git a/apps/files_sharing/tests/PropagationTestCase.php b/apps/files_sharing/tests/PropagationTestCase.php new file mode 100644 index 00000000000..1eec2093f7e --- /dev/null +++ b/apps/files_sharing/tests/PropagationTestCase.php @@ -0,0 +1,103 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +abstract class PropagationTestCase extends TestCase { + /** + * @var \OC\Files\View + */ + protected $rootView; + protected $fileIds = []; // [$user=>[$path=>$id]] + protected $fileEtags = []; // [$id=>$etag] + + public static function setUpBeforeClass() { + parent::setUpBeforeClass(); + \OCA\Files_Sharing\Helper::registerHooks(); + } + + protected function setUp() { + parent::setUp(); + $this->setUpShares(); + } + + protected function tearDown() { + \OC_Hook::clear('OC_Filesystem', 'post_write'); + \OC_Hook::clear('OC_Filesystem', 'post_delete'); + \OC_Hook::clear('OC_Filesystem', 'post_rename'); + \OC_Hook::clear('OCP\Share', 'post_update_permissions'); + parent::tearDown(); + } + + abstract protected function setUpShares(); + + /** + * @param string[] $users + * @param string $subPath + */ + protected function assertEtagsChanged($users, $subPath = '') { + $oldUser = \OC::$server->getUserSession()->getUser(); + foreach ($users as $user) { + $this->loginAsUser($user); + $id = $this->fileIds[$user][$subPath]; + $path = $this->rootView->getPath($id); + $etag = $this->rootView->getFileInfo($path)->getEtag(); + $this->assertNotEquals($this->fileEtags[$id], $etag, 'Failed asserting that the etag for "' . $subPath . '" of user ' . $user . ' has changed'); + $this->fileEtags[$id] = $etag; + } + $this->loginAsUser($oldUser->getUID()); + } + + /** + * @param string[] $users + * @param string $subPath + */ + protected function assertEtagsNotChanged($users, $subPath = '') { + $oldUser = \OC::$server->getUserSession()->getUser(); + foreach ($users as $user) { + $this->loginAsUser($user); + $id = $this->fileIds[$user][$subPath]; + $path = $this->rootView->getPath($id); + $etag = $this->rootView->getFileInfo($path)->getEtag(); + $this->assertEquals($this->fileEtags[$id], $etag, 'Failed asserting that the etag for "' . $subPath . '" of user ' . $user . ' has not changed'); + $this->fileEtags[$id] = $etag; + } + $this->loginAsUser($oldUser->getUID()); + } + + /** + * Assert that the etags for the root, /sub1 and /sub1/sub2 have changed + * + * @param string[] $users + */ + protected function assertEtagsForFoldersChanged($users) { + $this->assertEtagsChanged($users); + + $this->assertEtagsChanged($users, 'sub1'); + $this->assertEtagsChanged($users, 'sub1/sub2'); + } + + protected function assertAllUnchanged() { + $users = [self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]; + $this->assertEtagsNotChanged($users); + } +} diff --git a/apps/files_sharing/tests/ShareTest.php b/apps/files_sharing/tests/ShareTest.php new file mode 100644 index 00000000000..b4ebfde88ed --- /dev/null +++ b/apps/files_sharing/tests/ShareTest.php @@ -0,0 +1,249 @@ + + * @author Joas Schilling + * @author Morris Jobke + * @author Robin Appelman + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +/** + * Class ShareTest + * + * @group DB + */ +class ShareTest extends TestCase { + + const TEST_FOLDER_NAME = '/folder_share_api_test'; + + private static $tempStorage; + + protected function setUp() { + parent::setUp(); + + $this->folder = self::TEST_FOLDER_NAME; + $this->subfolder = '/subfolder_share_api_test'; + $this->subsubfolder = '/subsubfolder_share_api_test'; + + $this->filename = '/share-api-test.txt'; + + // save file with content + $this->view->file_put_contents($this->filename, $this->data); + $this->view->mkdir($this->folder); + $this->view->mkdir($this->folder . $this->subfolder); + $this->view->mkdir($this->folder . $this->subfolder . $this->subsubfolder); + $this->view->file_put_contents($this->folder.$this->filename, $this->data); + $this->view->file_put_contents($this->folder . $this->subfolder . $this->filename, $this->data); + } + + protected function tearDown() { + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + $this->view->unlink($this->filename); + $this->view->deleteAll($this->folder); + + self::$tempStorage = null; + + // clear database table + $query = \OCP\DB::prepare('DELETE FROM `*PREFIX*share`'); + $query->execute(); + + parent::tearDown(); + } + + public function testUnshareFromSelf() { + + \OC_Group::createGroup('testGroup'); + \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup'); + \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup'); + + $share1 = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->filename, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE + ); + + $share2 = $this->share( + \OCP\Share::SHARE_TYPE_GROUP, + $this->filename, + self::TEST_FILES_SHARING_API_USER1, + 'testGroup', + \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER3); + $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + \OC\Files\Filesystem::unlink($this->filename); + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + // both group share and user share should be gone + $this->assertFalse(\OC\Files\Filesystem::file_exists($this->filename)); + + // for user3 nothing should change + self::loginHelper(self::TEST_FILES_SHARING_API_USER3); + $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); + + $this->shareManager->deleteShare($share1); + $this->shareManager->deleteShare($share2); + } + + /** + * @param \OC\Files\FileInfo[] $content + * @param string[] $expected + */ + public function verifyDirContent($content, $expected) { + foreach ($content as $c) { + if (!in_array($c['name'], $expected)) { + $this->assertTrue(false, "folder should only contain '" . implode(',', $expected) . "', found: " .$c['name']); + } + } + } + + public function testShareWithDifferentShareFolder() { + + $fileinfo = $this->view->getFileInfo($this->filename); + $folderinfo = $this->view->getFileInfo($this->folder); + + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->filename, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE + ); + + \OCA\Files_Sharing\Helper::setShareFolder('/Shared/subfolder'); + + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); + $this->assertTrue(\OC\Files\Filesystem::file_exists('/Shared/subfolder/' . $this->folder)); + + //cleanup + \OC::$server->getConfig()->deleteSystemValue('share_folder'); + } + + public function testShareWithGroupUniqueName() { + $this->loginHelper(self::TEST_FILES_SHARING_API_USER1); + \OC\Files\Filesystem::file_put_contents('test.txt', 'test'); + + $share = $this->share( + \OCP\Share::SHARE_TYPE_GROUP, + 'test.txt', + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_GROUP1, + \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE + ); + + $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); + + $shares = $this->shareManager->getSharedWith(self::TEST_FILES_SHARING_API_USER2, \OCP\Share::SHARE_TYPE_GROUP); + $share = $shares[0]; + $this->assertSame('/test.txt' ,$share->getTarget()); + $this->assertSame(19, $share->getPermissions()); + + \OC\Files\Filesystem::rename('test.txt', 'new test.txt'); + + $shares = $this->shareManager->getSharedWith(self::TEST_FILES_SHARING_API_USER2, \OCP\Share::SHARE_TYPE_GROUP); + $share = $shares[0]; + $this->assertSame('/new test.txt' ,$share->getTarget()); + $this->assertSame(19, $share->getPermissions()); + + $share->setPermissions(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE); + $this->shareManager->updateShare($share); + + $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); + $shares = $this->shareManager->getSharedWith(self::TEST_FILES_SHARING_API_USER2, \OCP\Share::SHARE_TYPE_GROUP); + $share = $shares[0]; + + $this->assertSame('/new test.txt' ,$share->getTarget()); + $this->assertSame(3, $share->getPermissions()); + } + + /** + * shared files should never have delete permissions + * @dataProvider dataProviderTestFileSharePermissions + */ + public function testFileSharePermissions($permission, $expectedvalid) { + + $pass = true; + try { + $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->filename, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + $permission + ); + } catch (\Exception $e) { + $pass = false; + } + + $this->assertEquals($expectedvalid, $pass); + } + + public function dataProviderTestFileSharePermissions() { + $permission1 = \OCP\Constants::PERMISSION_ALL; + $permission3 = \OCP\Constants::PERMISSION_READ; + $permission4 = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE; + $permission5 = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_DELETE; + $permission6 = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; + + return array( + array($permission1, false), + array($permission3, true), + array($permission4, true), + array($permission5, false), + array($permission6, false), + ); + } + + public function testFileOwner() { + + $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->filename, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_READ + ); + + $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); + + $info = \OC\Files\Filesystem::getFileInfo($this->filename); + + $this->assertSame(self::TEST_FILES_SHARING_API_USER1, $info->getOwner()->getUID()); + } +} diff --git a/apps/files_sharing/tests/SharedMountTest.php b/apps/files_sharing/tests/SharedMountTest.php new file mode 100644 index 00000000000..300291357ba --- /dev/null +++ b/apps/files_sharing/tests/SharedMountTest.php @@ -0,0 +1,436 @@ + + * @author Joas Schilling + * @author Morris Jobke + * @author Robin Appelman + * @author Roeland Jago Douma + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +/** + * Class SharedMountTest + * + * @group DB + */ +class SharedMountTest extends TestCase { + + protected function setUp() { + parent::setUp(); + + $this->folder = '/folder_share_storage_test'; + + $this->filename = '/share-api-storage.txt'; + + + $this->view->mkdir($this->folder); + + // save file with content + $this->view->file_put_contents($this->filename, "root file"); + $this->view->file_put_contents($this->folder . $this->filename, "file in subfolder"); + } + + protected function tearDown() { + if ($this->view) { + if ($this->view->file_exists($this->folder)) { + $this->view->unlink($this->folder); + } + if ($this->view->file_exists($this->filename)) { + $this->view->unlink($this->filename); + } + } + + parent::tearDown(); + } + + /** + * test if the mount point moves up if the parent folder no longer exists + */ + public function testShareMountLoseParentFolder() { + + // share to user + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL); + + $share->setTarget('/foo/bar' . $this->folder); + $this->shareManager->moveShare($share, self::TEST_FILES_SHARING_API_USER2); + + $share = $this->shareManager->getShareById($share->getFullId()); + $this->assertSame('/foo/bar' . $this->folder, $share->getTarget()); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + // share should have moved up + + $share = $this->shareManager->getShareById($share->getFullId()); + $this->assertSame($this->folder, $share->getTarget()); + + //cleanup + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + $this->shareManager->deleteShare($share); + $this->view->unlink($this->folder); + } + + /** + * @medium + */ + public function testDeleteParentOfMountPoint() { + // share to user + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); + $this->assertTrue($user2View->file_exists($this->folder)); + + // create a local folder + $result = $user2View->mkdir('localfolder'); + $this->assertTrue($result); + + // move mount point to local folder + $result = $user2View->rename($this->folder, '/localfolder/' . $this->folder); + $this->assertTrue($result); + + // mount point in the root folder should no longer exist + $this->assertFalse($user2View->is_dir($this->folder)); + + // delete the local folder + $result = $user2View->unlink('/localfolder'); + $this->assertTrue($result); + + //enforce reload of the mount points + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + //mount point should be back at the root + $this->assertTrue($user2View->is_dir($this->folder)); + + //cleanup + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + $this->view->unlink($this->folder); + } + + public function testMoveSharedFile() { + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->filename, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + \OC\Files\Filesystem::rename($this->filename, $this->filename . '_renamed'); + + $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename . '_renamed')); + $this->assertFalse(\OC\Files\Filesystem::file_exists($this->filename)); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); + $this->assertFalse(\OC\Files\Filesystem::file_exists($this->filename . '_renamed')); + + // rename back to original name + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + \OC\Files\Filesystem::rename($this->filename . '_renamed', $this->filename); + $this->assertFalse(\OC\Files\Filesystem::file_exists($this->filename . '_renamed')); + $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); + + //cleanup + $this->shareManager->deleteShare($share); + } + + /** + * share file with a group if a user renames the file the filename should not change + * for the other users + */ + public function testMoveGroupShare () { + \OC_Group::createGroup('testGroup'); + \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER1, 'testGroup'); + \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup'); + \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup'); + + $fileinfo = $this->view->getFileInfo($this->filename); + $share = $this->share( + \OCP\Share::SHARE_TYPE_GROUP, + $this->filename, + self::TEST_FILES_SHARING_API_USER1, + 'testGroup', + \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); + + \OC\Files\Filesystem::rename($this->filename, "newFileName"); + + $this->assertTrue(\OC\Files\Filesystem::file_exists('newFileName')); + $this->assertFalse(\OC\Files\Filesystem::file_exists($this->filename)); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER3); + $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); + $this->assertFalse(\OC\Files\Filesystem::file_exists("newFileName")); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER3); + $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); + $this->assertFalse(\OC\Files\Filesystem::file_exists("newFileName")); + + //cleanup + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + $this->shareManager->deleteShare($share); + \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER1, 'testGroup'); + \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup'); + \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup'); + } + + /** + * @dataProvider dataProviderTestStripUserFilesPath + * @param string $path + * @param string $expectedResult + * @param bool $exception if a exception is expected + */ + public function testStripUserFilesPath($path, $expectedResult, $exception) { + $testClass = new DummyTestClassSharedMount(null, null); + try { + $result = $testClass->stripUserFilesPathDummy($path); + $this->assertSame($expectedResult, $result); + } catch (\Exception $e) { + if ($exception) { + $this->assertSame(10, $e->getCode()); + } else { + $this->assertTrue(false, "Exception catched, but expected: " . $expectedResult); + } + } + } + + public function dataProviderTestStripUserFilesPath() { + return array( + array('/user/files/foo.txt', '/foo.txt', false), + array('/user/files/folder/foo.txt', '/folder/foo.txt', false), + array('/data/user/files/foo.txt', null, true), + array('/data/user/files/', null, true), + array('/files/foo.txt', null, true), + array('/foo.txt', null, true), + ); + } + + public function dataPermissionMovedGroupShare() { + $data = []; + + $powerset = function($permissions) { + $results = [\OCP\Constants::PERMISSION_READ]; + + foreach ($permissions as $permission) { + foreach ($results as $combination) { + $results[] = $permission | $combination; + } + } + return $results; + }; + + //Generate file permissions + $permissions = [ + \OCP\Constants::PERMISSION_UPDATE, + \OCP\Constants::PERMISSION_SHARE, + ]; + + $allPermissions = $powerset($permissions); + + foreach ($allPermissions as $before) { + foreach ($allPermissions as $after) { + if ($before === $after) { continue; } + + $data[] = [ + 'file', + $before, + $after, + ]; + } + } + + //Generate folder permissions + $permissions = [ + \OCP\Constants::PERMISSION_UPDATE, + \OCP\Constants::PERMISSION_CREATE, + \OCP\Constants::PERMISSION_SHARE, + \OCP\Constants::PERMISSION_DELETE, + ]; + + $allPermissions = $powerset($permissions); + + foreach ($allPermissions as $before) { + foreach ($allPermissions as $after) { + if ($before === $after) { continue; } + + $data[] = [ + 'folder', + $before, + $after, + ]; + } + } + + return $data; + } + + + + /** + * moved mountpoints of a group share should keep the same permission as their parent group share. + * See #15253 + * + * @dataProvider dataPermissionMovedGroupShare + */ + function testPermissionMovedGroupShare($type, $beforePerm, $afterPerm) { + + if ($type === 'file') { + $path = $this->filename; + } else if ($type === 'folder') { + $path = $this->folder; + } + + \OC_Group::createGroup('testGroup'); + \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER1, 'testGroup'); + \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup'); + \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup'); + + // Share item with group + $share = $this->share( + \OCP\Share::SHARE_TYPE_GROUP, + $path, + self::TEST_FILES_SHARING_API_USER1, + 'testGroup', + $beforePerm + ); + + // Login as user 2 and verify the item exists + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $this->assertTrue(\OC\Files\Filesystem::file_exists($path)); + $result = $this->shareManager->getShareById($share->getFullId(), self::TEST_FILES_SHARING_API_USER2); + $this->assertEquals($beforePerm, $result->getPermissions()); + + // Now move the item forcing a new entry in the share table + \OC\Files\Filesystem::rename($path, "newPath"); + $this->assertTrue(\OC\Files\Filesystem::file_exists('newPath')); + $this->assertFalse(\OC\Files\Filesystem::file_exists($path)); + + // change permissions + $share->setPermissions($afterPerm); + $this->shareManager->updateShare($share); + + // Login as user 3 and verify that the permissions are changed + self::loginHelper(self::TEST_FILES_SHARING_API_USER3); + $result = $this->shareManager->getShareById($share->getFullId(), self::TEST_FILES_SHARING_API_USER3); + $this->assertNotEmpty($result); + $this->assertEquals($afterPerm, $result->getPermissions()); + + // Login as user 2 and verify that the permissions are changed + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $result = $this->shareManager->getShareById($share->getFullId(), self::TEST_FILES_SHARING_API_USER2); + $this->assertNotEmpty($result); + $this->assertEquals($afterPerm, $result->getPermissions()); + $this->assertEquals('/newPath', $result->getTarget()); + + //cleanup + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + $this->shareManager->deleteShare($share); + \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER1, 'testGroup'); + \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup'); + \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup'); + } + + /** + * If the permissions on a group share are upgraded be sure to still respect + * removed shares by a member of that group + */ + function testPermissionUpgradeOnUserDeletedGroupShare() { + \OC_Group::createGroup('testGroup'); + \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER1, 'testGroup'); + \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup'); + \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup'); + + $connection = \OC::$server->getDatabaseConnection(); + + // Share item with group + $fileinfo = $this->view->getFileInfo($this->folder); + $share = $this->share( + \OCP\Share::SHARE_TYPE_GROUP, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + 'testGroup', + \OCP\Constants::PERMISSION_READ + ); + + // Login as user 2 and verify the item exists + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $this->assertTrue(\OC\Files\Filesystem::file_exists($this->folder)); + $result = $this->shareManager->getShareById($share->getFullId(), self::TEST_FILES_SHARING_API_USER2); + $this->assertNotEmpty($result); + $this->assertEquals(\OCP\Constants::PERMISSION_READ, $result->getPermissions()); + + // Delete the share + $this->assertTrue(\OC\Files\Filesystem::rmdir($this->folder)); + $this->assertFalse(\OC\Files\Filesystem::file_exists($this->folder)); + + // Verify we do not get a share + $result = $this->shareManager->getShareById($share->getFullId(), self::TEST_FILES_SHARING_API_USER2); + $this->assertEquals(0, $result->getPermissions()); + + // Login as user 1 again and change permissions + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + $share->setPermissions(\OCP\Constants::PERMISSION_ALL); + $share = $this->shareManager->updateShare($share); + + // Login as user 2 and verify + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $this->assertFalse(\OC\Files\Filesystem::file_exists($this->folder)); + $result = $this->shareManager->getShareById($share->getFullId(), self::TEST_FILES_SHARING_API_USER2); + $this->assertEquals(0, $result->getPermissions()); + + $this->shareManager->deleteShare($share); + + //cleanup + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER1, 'testGroup'); + \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup'); + \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup'); + } + +} + +class DummyTestClassSharedMount extends \OCA\Files_Sharing\SharedMount { + public function __construct($storage, $mountpoint, $arguments = null, $loader = null){ + // noop + } + + public function stripUserFilesPathDummy($path) { + return $this->stripUserFilesPath($path); + } +} diff --git a/apps/files_sharing/tests/SharedStorageTest.php b/apps/files_sharing/tests/SharedStorageTest.php new file mode 100644 index 00000000000..6d9eaf6c34b --- /dev/null +++ b/apps/files_sharing/tests/SharedStorageTest.php @@ -0,0 +1,532 @@ + + * @author Joas Schilling + * @author Morris Jobke + * @author Robin Appelman + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +/** + * Class SharedStorageTest + * + * @group DB + */ +class SharedStorageTest extends TestCase { + + protected function setUp() { + parent::setUp(); + \OCA\Files_Trashbin\Trashbin::registerHooks(); + $this->folder = '/folder_share_storage_test'; + + $this->filename = '/share-api-storage.txt'; + + + $this->view->mkdir($this->folder); + + // save file with content + $this->view->file_put_contents($this->filename, "root file"); + $this->view->file_put_contents($this->folder . $this->filename, "file in subfolder"); + } + + protected function tearDown() { + if ($this->view) { + if ($this->view->file_exists($this->folder)) { + $this->view->unlink($this->folder); + } + if ($this->view->file_exists($this->filename)) { + $this->view->unlink($this->filename); + } + } + + \OC\Files\Filesystem::getLoader()->removeStorageWrapper('oc_trashbin'); + + parent::tearDown(); + } + + /** + * if the parent of the mount point is gone then the mount point should move up + * + * @medium + */ + public function testParentOfMountPointIsGone() { + + // share to user + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); + $this->assertTrue($user2View->file_exists($this->folder)); + + // create a local folder + $result = $user2View->mkdir('localfolder'); + $this->assertTrue($result); + + // move mount point to local folder + $result = $user2View->rename($this->folder, '/localfolder/' . $this->folder); + $this->assertTrue($result); + + // mount point in the root folder should no longer exist + $this->assertFalse($user2View->is_dir($this->folder)); + + // delete the local folder + /** @var \OC\Files\Storage\Storage $storage */ + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/localfolder'); + $storage->rmdir($internalPath); + + //enforce reload of the mount points + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + //mount point should be back at the root + $this->assertTrue($user2View->is_dir($this->folder)); + + //cleanup + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + $this->view->unlink($this->folder); + } + + /** + * @medium + */ + public function testRenamePartFile() { + + // share to user + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL + ); + + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); + + $this->assertTrue($user2View->file_exists($this->folder)); + + // create part file + $result = $user2View->file_put_contents($this->folder . '/foo.txt.part', 'some test data'); + + $this->assertTrue(is_int($result)); + // rename part file to real file + $result = $user2View->rename($this->folder . '/foo.txt.part', $this->folder . '/foo.txt'); + + $this->assertTrue($result); + + // check if the new file really exists + $this->assertTrue($user2View->file_exists($this->folder . '/foo.txt')); + + // check if the rename also affected the owner + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $this->assertTrue($this->view->file_exists($this->folder . '/foo.txt')); + + //cleanup + $this->shareManager->deleteShare($share); + } + + public function testFilesize() { + $folderSize = $this->view->filesize($this->folder); + $file1Size = $this->view->filesize($this->folder . $this->filename); + $file2Size = $this->view->filesize($this->filename); + + $share1 = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL + ); + + $share2 = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->filename, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE + ); + + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + // compare file size between user1 and user2, should always be the same + $this->assertSame($folderSize, \OC\Files\Filesystem::filesize($this->folder)); + $this->assertSame($file1Size, \OC\Files\Filesystem::filesize($this->folder . $this->filename)); + $this->assertSame($file2Size, \OC\Files\Filesystem::filesize($this->filename)); + + //cleanup + $this->shareManager->deleteShare($share1); + $this->shareManager->deleteShare($share2); + } + + public function testGetPermissions() { + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_READ + ); + + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + $this->assertTrue(\OC\Files\Filesystem::is_dir($this->folder)); + + // for the share root we expect: + // the shared permissions (1) + // the delete permission (8), to enable unshare + $rootInfo = \OC\Files\Filesystem::getFileInfo($this->folder); + $this->assertSame(9, $rootInfo->getPermissions()); + + // for the file within the shared folder we expect: + // the shared permissions (1) + $subfileInfo = \OC\Files\Filesystem::getFileInfo($this->folder . $this->filename); + $this->assertSame(1, $subfileInfo->getPermissions()); + + + //cleanup + $this->shareManager->deleteShare($share); + } + + public function testFopenWithReadOnlyPermission() { + $this->view->file_put_contents($this->folder . '/existing.txt', 'foo'); + + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_READ + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); + + // part file should be forbidden + $handle = $user2View->fopen($this->folder . '/test.txt.part', 'w'); + $this->assertFalse($handle); + + // regular file forbidden + $handle = $user2View->fopen($this->folder . '/test.txt', 'w'); + $this->assertFalse($handle); + + // rename forbidden + $this->assertFalse($user2View->rename($this->folder . '/existing.txt', $this->folder . '/existing2.txt')); + + // delete forbidden + $this->assertFalse($user2View->unlink($this->folder . '/existing.txt')); + + //cleanup + $this->shareManager->deleteShare($share); + } + + public function testFopenWithCreateOnlyPermission() { + $this->view->file_put_contents($this->folder . '/existing.txt', 'foo'); + $fileinfoFolder = $this->view->getFileInfo($this->folder); + + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); + + // create part file allowed + $handle = $user2View->fopen($this->folder . '/test.txt.part', 'w'); + $this->assertNotFalse($handle); + fclose($handle); + + // create regular file allowed + $handle = $user2View->fopen($this->folder . '/test-create.txt', 'w'); + $this->assertNotFalse($handle); + fclose($handle); + + // rename file never allowed + $this->assertFalse($user2View->rename($this->folder . '/test-create.txt', $this->folder . '/newtarget.txt')); + $this->assertFalse($user2View->file_exists($this->folder . '/newtarget.txt')); + + // rename file not allowed if target exists + $this->assertFalse($user2View->rename($this->folder . '/newtarget.txt', $this->folder . '/existing.txt')); + + // overwriting file not allowed + $handle = $user2View->fopen($this->folder . '/existing.txt', 'w'); + $this->assertFalse($handle); + + // overwrite forbidden (no update permission) + $this->assertFalse($user2View->rename($this->folder . '/test.txt.part', $this->folder . '/existing.txt')); + + // delete forbidden + $this->assertFalse($user2View->unlink($this->folder . '/existing.txt')); + + //cleanup + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + $result = \OCP\Share::unshare('folder', $fileinfoFolder['fileid'], \OCP\Share::SHARE_TYPE_USER, + self::TEST_FILES_SHARING_API_USER2); + $this->assertTrue($result); + } + + public function testFopenWithUpdateOnlyPermission() { + $this->view->file_put_contents($this->folder . '/existing.txt', 'foo'); + + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); + + // create part file allowed + $handle = $user2View->fopen($this->folder . '/test.txt.part', 'w'); + $this->assertNotFalse($handle); + fclose($handle); + + // create regular file not allowed + $handle = $user2View->fopen($this->folder . '/test-create.txt', 'w'); + $this->assertFalse($handle); + + // rename part file not allowed to non-existing file + $this->assertFalse($user2View->rename($this->folder . '/test.txt.part', $this->folder . '/nonexist.txt')); + + // rename part file allowed to target existing file + $this->assertTrue($user2View->rename($this->folder . '/test.txt.part', $this->folder . '/existing.txt')); + $this->assertTrue($user2View->file_exists($this->folder . '/existing.txt')); + + // rename regular file allowed + $this->assertTrue($user2View->rename($this->folder . '/existing.txt', $this->folder . '/existing-renamed.txt')); + $this->assertTrue($user2View->file_exists($this->folder . '/existing-renamed.txt')); + + // overwriting file directly is allowed + $handle = $user2View->fopen($this->folder . '/existing-renamed.txt', 'w'); + $this->assertNotFalse($handle); + fclose($handle); + + // delete forbidden + $this->assertFalse($user2View->unlink($this->folder . '/existing-renamed.txt')); + + //cleanup + $this->shareManager->deleteShare($share); + } + + public function testFopenWithDeleteOnlyPermission() { + $this->view->file_put_contents($this->folder . '/existing.txt', 'foo'); + + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_DELETE + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); + + // part file should be forbidden + $handle = $user2View->fopen($this->folder . '/test.txt.part', 'w'); + $this->assertFalse($handle); + + // regular file forbidden + $handle = $user2View->fopen($this->folder . '/test.txt', 'w'); + $this->assertFalse($handle); + + // rename forbidden + $this->assertFalse($user2View->rename($this->folder . '/existing.txt', $this->folder . '/existing2.txt')); + + // delete allowed + $this->assertTrue($user2View->unlink($this->folder . '/existing.txt')); + + //cleanup + $this->shareManager->deleteShare($share); + } + + public function testMountSharesOtherUser() { + $rootView = new \OC\Files\View(''); + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + // share 2 different files with 2 different users + $share1 = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL + ); + $share2 = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->filename, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER3, + \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $this->assertTrue($rootView->file_exists('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/' . $this->folder)); + + $mountConfigManager = \OC::$server->getMountProviderCollection(); + $mounts = $mountConfigManager->getMountsForUser(\OC::$server->getUserManager()->get(self::TEST_FILES_SHARING_API_USER3)); + array_walk($mounts, array(\OC\Files\Filesystem::getMountManager(), 'addMount')); + + $this->assertTrue($rootView->file_exists('/' . self::TEST_FILES_SHARING_API_USER3 . '/files/' . $this->filename)); + + // make sure we didn't double setup shares for user 2 or mounted the shares for user 3 in user's 2 home + $this->assertFalse($rootView->file_exists('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/' . $this->folder . ' (2)')); + $this->assertFalse($rootView->file_exists('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/' . $this->filename)); + + //cleanup + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + $this->view->unlink($this->folder); + + $this->shareManager->deleteShare($share1); + $this->shareManager->deleteShare($share2); + } + + public function testCopyFromStorage() { + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $view = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); + $this->assertTrue($view->file_exists($this->folder)); + + /** + * @var \OCP\Files\Storage $sharedStorage + */ + list($sharedStorage,) = $view->resolvePath($this->folder); + $this->assertTrue($sharedStorage->instanceOfStorage('OCA\Files_Sharing\ISharedStorage')); + + $sourceStorage = new \OC\Files\Storage\Temporary(array()); + $sourceStorage->file_put_contents('foo.txt', 'asd'); + + $sharedStorage->copyFromStorage($sourceStorage, 'foo.txt', 'bar.txt'); + $this->assertTrue($sharedStorage->file_exists('bar.txt')); + $this->assertEquals('asd', $sharedStorage->file_get_contents('bar.txt')); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + $this->view->unlink($this->folder); + $this->shareManager->deleteShare($share); + } + + public function testMoveFromStorage() { + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $view = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); + $this->assertTrue($view->file_exists($this->folder)); + + /** + * @var \OCP\Files\Storage $sharedStorage + */ + list($sharedStorage,) = $view->resolvePath($this->folder); + $this->assertTrue($sharedStorage->instanceOfStorage('OCA\Files_Sharing\ISharedStorage')); + + $sourceStorage = new \OC\Files\Storage\Temporary(array()); + $sourceStorage->file_put_contents('foo.txt', 'asd'); + + $sharedStorage->moveFromStorage($sourceStorage, 'foo.txt', 'bar.txt'); + $this->assertTrue($sharedStorage->file_exists('bar.txt')); + $this->assertEquals('asd', $sharedStorage->file_get_contents('bar.txt')); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + $this->view->unlink($this->folder); + $this->shareManager->deleteShare($share); + } + + public function testNameConflict() { + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + $view1 = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files'); + $view1->mkdir('foo'); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER3); + $view3 = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER3 . '/files'); + $view3->mkdir('foo'); + + // share a folder with the same name from two different users to the same user + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $share1 = $this->share( + \OCP\Share::SHARE_TYPE_GROUP, + 'foo', + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_GROUP1, + \OCP\Constants::PERMISSION_ALL + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER3); + + $share2 = $this->share( + \OCP\Share::SHARE_TYPE_GROUP, + 'foo', + self::TEST_FILES_SHARING_API_USER3, + self::TEST_FILES_SHARING_API_GROUP1, + \OCP\Constants::PERMISSION_ALL + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $view2 = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); + + $this->assertTrue($view2->file_exists('/foo')); + $this->assertTrue($view2->file_exists('/foo (2)')); + + $mount = $view2->getMount('/foo'); + $this->assertInstanceOf('\OCA\Files_Sharing\SharedMount', $mount); + /** @var \OC\Files\Storage\Shared $storage */ + $storage = $mount->getStorage(); + + $this->assertEquals(self::TEST_FILES_SHARING_API_USER1, $storage->getOwner('')); + + $this->shareManager->deleteShare($share1); + $this->shareManager->deleteShare($share2); + } +} diff --git a/apps/files_sharing/tests/SizePropagationTest.php b/apps/files_sharing/tests/SizePropagationTest.php new file mode 100644 index 00000000000..b96532b7f3e --- /dev/null +++ b/apps/files_sharing/tests/SizePropagationTest.php @@ -0,0 +1,121 @@ + + * @author Robin Appelman + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +use OC\Files\View; +use Test\Traits\MountProviderTrait; +use Test\Traits\UserTrait; + +/** + * Class SizePropagationTest + * + * @group DB + * + * @package OCA\Files_Sharing\Tests + */ +class SizePropagationTest extends TestCase { + use UserTrait; + use MountProviderTrait; + + protected function setupUser($name, $password = '') { + $this->createUser($name, $password); + $tmpFolder = \OC::$server->getTempManager()->getTemporaryFolder(); + $this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]); + $this->loginAsUser($name); + return new View('/' . $name . '/files'); + } + + public function testSizePropagationWhenOwnerChangesFile() { + $recipientView = $this->setupUser(self::TEST_FILES_SHARING_API_USER1); + + $ownerView = $this->setupUser(self::TEST_FILES_SHARING_API_USER2); + $ownerView->mkdir('/sharedfolder/subfolder'); + $ownerView->file_put_contents('/sharedfolder/subfolder/foo.txt', 'bar'); + + $this->share( + \OCP\Share::SHARE_TYPE_USER, + '/sharedfolder', + self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER1, + \OCP\Constants::PERMISSION_ALL + ); + $ownerRootInfo = $ownerView->getFileInfo('', false); + + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + $this->assertTrue($recipientView->file_exists('/sharedfolder/subfolder/foo.txt')); + $recipientRootInfo = $recipientView->getFileInfo('', false); + + // when file changed as owner + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); + $ownerView->file_put_contents('/sharedfolder/subfolder/foo.txt', 'foobar'); + + // size of recipient's root stays the same + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + $newRecipientRootInfo = $recipientView->getFileInfo('', false); + $this->assertEquals($recipientRootInfo->getSize(), $newRecipientRootInfo->getSize()); + + // size of owner's root increases + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); + $newOwnerRootInfo = $ownerView->getFileInfo('', false); + $this->assertEquals($ownerRootInfo->getSize() + 3, $newOwnerRootInfo->getSize()); + } + + public function testSizePropagationWhenRecipientChangesFile() { + $recipientView = $this->setupUser(self::TEST_FILES_SHARING_API_USER1); + + $ownerView = $this->setupUser(self::TEST_FILES_SHARING_API_USER2); + $ownerView->mkdir('/sharedfolder/subfolder'); + $ownerView->file_put_contents('/sharedfolder/subfolder/foo.txt', 'bar'); + + $this->share( + \OCP\Share::SHARE_TYPE_USER, + '/sharedfolder', + self::TEST_FILES_SHARING_API_USER2, + self::TEST_FILES_SHARING_API_USER1, + \OCP\Constants::PERMISSION_ALL + ); + $ownerRootInfo = $ownerView->getFileInfo('', false); + + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); + $this->assertTrue($recipientView->file_exists('/sharedfolder/subfolder/foo.txt')); + $recipientRootInfo = $recipientView->getFileInfo('', false); + $recipientRootInfoWithMounts = $recipientView->getFileInfo('', true); + + // when file changed as recipient + $recipientView->file_put_contents('/sharedfolder/subfolder/foo.txt', 'foobar'); + + // size of recipient's root stays the same + $newRecipientRootInfo = $recipientView->getFileInfo('', false); + $this->assertEquals($recipientRootInfo->getSize(), $newRecipientRootInfo->getSize()); + + // but the size including mountpoints increases + $newRecipientRootInfo = $recipientView->getFileInfo('', true); + $this->assertEquals($recipientRootInfoWithMounts->getSize() +3, $newRecipientRootInfo->getSize()); + + // size of owner's root increases + $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); + $newOwnerRootInfo = $ownerView->getFileInfo('', false); + $this->assertEquals($ownerRootInfo->getSize() + 3, $newOwnerRootInfo->getSize()); + } +} diff --git a/apps/files_sharing/tests/TestCase.php b/apps/files_sharing/tests/TestCase.php new file mode 100644 index 00000000000..a5c412639e7 --- /dev/null +++ b/apps/files_sharing/tests/TestCase.php @@ -0,0 +1,232 @@ + + * @author Joas Schilling + * @author Jörn Friedrich Dreyer + * @author Lukas Reschke + * @author Morris Jobke + * @author Robin Appelman + * @author Robin McCorkell + * @author Roeland Jago Douma + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +use OC\Files\Filesystem; +use OCA\Files_Sharing\AppInfo\Application; + +/** + * Class TestCase + * + * @group DB + * + * Base class for sharing tests. + */ +abstract class TestCase extends \Test\TestCase { + + const TEST_FILES_SHARING_API_USER1 = "test-share-user1"; + const TEST_FILES_SHARING_API_USER2 = "test-share-user2"; + const TEST_FILES_SHARING_API_USER3 = "test-share-user3"; + const TEST_FILES_SHARING_API_USER4 = "test-share-user4"; + + const TEST_FILES_SHARING_API_GROUP1 = "test-share-group1"; + + public $filename; + public $data; + /** + * @var \OC\Files\View + */ + public $view; + public $folder; + public $subfolder; + + /** @var \OCP\Share\IManager */ + protected $shareManager; + /** @var \OCP\Files\IRootFolder */ + protected $rootFolder; + + public static function setUpBeforeClass() { + parent::setUpBeforeClass(); + + $application = new Application(); + $application->registerMountProviders(); + + // reset backend + \OC_User::clearBackends(); + \OC_Group::clearBackends(); + + // clear share hooks + \OC_Hook::clear('OCP\\Share'); + \OC::registerShareHooks(); + + // create users + $backend = new \Test\Util\User\Dummy(); + \OC_User::useBackend($backend); + $backend->createUser(self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER1); + $backend->createUser(self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER2); + $backend->createUser(self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER3); + $backend->createUser(self::TEST_FILES_SHARING_API_USER4, self::TEST_FILES_SHARING_API_USER4); + + // create group + $groupBackend = new \Test\Util\Group\Dummy(); + $groupBackend->createGroup(self::TEST_FILES_SHARING_API_GROUP1); + $groupBackend->createGroup('group'); + $groupBackend->createGroup('group1'); + $groupBackend->createGroup('group2'); + $groupBackend->createGroup('group3'); + $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER1, 'group'); + $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER2, 'group'); + $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER3, 'group'); + $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER2, 'group1'); + $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER3, 'group2'); + $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER4, 'group3'); + $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_GROUP1); + \OC_Group::useBackend($groupBackend); + } + + protected function setUp() { + parent::setUp(); + + //login as user1 + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $this->data = 'foobar'; + $this->view = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files'); + + $this->shareManager = \OC::$server->getShareManager(); + $this->rootFolder = \OC::$server->getRootFolder(); + } + + protected function tearDown() { + $query = \OCP\DB::prepare('DELETE FROM `*PREFIX*share`'); + $query->execute(); + + parent::tearDown(); + } + + public static function tearDownAfterClass() { + // cleanup users + $user = \OC::$server->getUserManager()->get(self::TEST_FILES_SHARING_API_USER1); + if ($user !== null) { $user->delete(); } + $user = \OC::$server->getUserManager()->get(self::TEST_FILES_SHARING_API_USER2); + if ($user !== null) { $user->delete(); } + $user = \OC::$server->getUserManager()->get(self::TEST_FILES_SHARING_API_USER3); + if ($user !== null) { $user->delete(); } + + // delete group + \OC_Group::deleteGroup(self::TEST_FILES_SHARING_API_GROUP1); + + \OC_Util::tearDownFS(); + \OC_User::setUserId(''); + Filesystem::tearDown(); + + // reset backend + \OC_User::clearBackends(); + \OC_User::useBackend('database'); + \OC_Group::clearBackends(); + \OC_Group::useBackend(new \OC\Group\Database()); + + parent::tearDownAfterClass(); + } + + /** + * @param string $user + * @param bool $create + * @param bool $password + */ + protected static function loginHelper($user, $create = false, $password = false) { + + if ($password === false) { + $password = $user; + } + + if ($create) { + \OC::$server->getUserManager()->createUser($user, $password); + \OC_Group::createGroup('group'); + \OC_Group::addToGroup($user, 'group'); + } + + self::resetStorage(); + + \OC_Util::tearDownFS(); + \OC::$server->getUserSession()->setUser(null); + \OC\Files\Filesystem::tearDown(); + \OC::$server->getUserSession()->login($user, $password); + \OC::$server->getUserFolder($user); + + \OC_Util::setupFS($user); + } + + /** + * reset init status for the share storage + */ + protected static function resetStorage() { + $storage = new \ReflectionClass('\OC\Files\Storage\Shared'); + $isInitialized = $storage->getProperty('initialized'); + $isInitialized->setAccessible(true); + $isInitialized->setValue($storage, false); + $isInitialized->setAccessible(false); + } + + /** + * get some information from a given share + * @param int $shareID + * @return array with: item_source, share_type, share_with, item_type, permissions + */ + protected function getShareFromId($shareID) { + $sql = 'SELECT `item_source`, `share_type`, `share_with`, `item_type`, `permissions` FROM `*PREFIX*share` WHERE `id` = ?'; + $args = array($shareID); + $query = \OCP\DB::prepare($sql); + $result = $query->execute($args); + + $share = Null; + + if ($result) { + $share = $result->fetchRow(); + } + + return $share; + + } + + /** + * @param int $type The share type + * @param string $path The path to share relative to $initiators root + * @param string $initiator + * @param string $recipient + * @param int $permissions + * @return \OCP\Share\IShare + */ + protected function share($type, $path, $initiator, $recipient, $permissions) { + $userFolder = $this->rootFolder->getUserFolder($initiator); + $node = $userFolder->get($path); + + $share = $this->shareManager->newShare(); + $share->setShareType($type) + ->setSharedWith($recipient) + ->setSharedBy($initiator) + ->setNode($node) + ->setPermissions($permissions); + $share = $this->shareManager->createShare($share); + + return $share; + } +} diff --git a/apps/files_sharing/tests/UnshareChildrenTest.php b/apps/files_sharing/tests/UnshareChildrenTest.php new file mode 100644 index 00000000000..63e4428a25e --- /dev/null +++ b/apps/files_sharing/tests/UnshareChildrenTest.php @@ -0,0 +1,111 @@ + + * @author Joas Schilling + * @author Morris Jobke + * @author Robin Appelman + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +/** + * Class UnshareChildrenTest + * + * @group DB + * + * @package OCA\Files_Sharing\Tests + */ +class UnshareChildrenTest extends TestCase { + + protected $subsubfolder; + + const TEST_FOLDER_NAME = '/folder_share_api_test'; + + private static $tempStorage; + + protected function setUp() { + parent::setUp(); + + \OCP\Util::connectHook('OC_Filesystem', 'post_delete', '\OCA\Files_Sharing\Hooks', 'unshareChildren'); + + $this->folder = self::TEST_FOLDER_NAME; + $this->subfolder = '/subfolder_share_api_test'; + $this->subsubfolder = '/subsubfolder_share_api_test'; + + $this->filename = '/share-api-test'; + + // save file with content + $this->view->mkdir($this->folder); + $this->view->mkdir($this->folder . $this->subfolder); + $this->view->mkdir($this->folder . $this->subfolder . $this->subsubfolder); + $this->view->file_put_contents($this->folder . $this->filename, $this->data); + $this->view->file_put_contents($this->folder . $this->subfolder . $this->filename, $this->data); + } + + protected function tearDown() { + if ($this->view) { + $this->view->deleteAll($this->folder); + } + + self::$tempStorage = null; + + parent::tearDown(); + } + + /** + * @medium + */ + function testUnshareChildren() { + + $fileInfo2 = \OC\Files\Filesystem::getFileInfo($this->folder); + + $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL + ); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + // one folder should be shared with the user + $shares = $this->shareManager->getSharedWith(self::TEST_FILES_SHARING_API_USER2, \OCP\Share::SHARE_TYPE_USER); + $this->assertCount(1, $shares); + + // move shared folder to 'localDir' + \OC\Files\Filesystem::mkdir('localDir'); + $result = \OC\Files\Filesystem::rename($this->folder, '/localDir/' . $this->folder); + $this->assertTrue($result); + + \OC\Files\Filesystem::unlink('localDir'); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + // after the parent directory was deleted the share should be unshared + $shares = $this->shareManager->getSharedWith(self::TEST_FILES_SHARING_API_USER2, \OCP\Share::SHARE_TYPE_USER); + $this->assertEmpty($shares); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + // the folder for the owner should still exists + $this->assertTrue(\OC\Files\Filesystem::file_exists($this->folder)); + } +} diff --git a/apps/files_sharing/tests/UpdaterTest.php b/apps/files_sharing/tests/UpdaterTest.php new file mode 100644 index 00000000000..659c04ad987 --- /dev/null +++ b/apps/files_sharing/tests/UpdaterTest.php @@ -0,0 +1,233 @@ + + * @author Joas Schilling + * @author Morris Jobke + * @author Robin Appelman + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +/** + * Class UpdaterTest + * + * @group DB + */ +class UpdaterTest extends TestCase { + + const TEST_FOLDER_NAME = '/folder_share_updater_test'; + + public static function setUpBeforeClass() { + parent::setUpBeforeClass(); + \OCA\Files_Sharing\Helper::registerHooks(); + } + + protected function setUp() { + parent::setUp(); + + $this->folder = self::TEST_FOLDER_NAME; + + $this->filename = '/share-updater-test.txt'; + + // save file with content + $this->view->file_put_contents($this->filename, $this->data); + $this->view->mkdir($this->folder); + $this->view->file_put_contents($this->folder . '/' . $this->filename, $this->data); + } + + protected function tearDown() { + if ($this->view) { + $this->view->unlink($this->filename); + $this->view->deleteAll($this->folder); + } + + parent::tearDown(); + } + + /** + * test deletion of a folder which contains share mount points. Share mount + * points should be unshared before the folder gets deleted so + * that the mount point doesn't end up at the trash bin + */ + function testDeleteParentFolder() { + $status = \OC_App::isEnabled('files_trashbin'); + \OC_App::enable('files_trashbin'); + + \OCA\Files_Trashbin\Trashbin::registerHooks(); + + $fileinfo = \OC\Files\Filesystem::getFileInfo($this->folder); + $this->assertTrue($fileinfo instanceof \OC\Files\FileInfo); + + $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL + ); + + $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); + $view = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); + + // check if user2 can see the shared folder + $this->assertTrue($view->file_exists($this->folder)); + + $foldersShared = \OCP\Share::getItemsSharedWith('folder'); + $this->assertSame(1, count($foldersShared)); + + $view->mkdir("localFolder"); + $view->file_put_contents("localFolder/localFile.txt", "local file"); + + $view->rename($this->folder, 'localFolder/' . $this->folder); + + // share mount point should now be moved to the subfolder + $this->assertFalse($view->file_exists($this->folder)); + $this->assertTrue($view->file_exists('localFolder/' .$this->folder)); + + $view->unlink('localFolder'); + + $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); + + // shared folder should be unshared + $foldersShared = \OCP\Share::getItemsSharedWith('folder'); + $this->assertTrue(empty($foldersShared)); + + // trashbin should contain the local file but not the mount point + $rootView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2); + $trashContent = \OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_FILES_SHARING_API_USER2); + $this->assertSame(1, count($trashContent)); + $firstElement = reset($trashContent); + $timestamp = $firstElement['mtime']; + $this->assertTrue($rootView->file_exists('files_trashbin/files/localFolder.d' . $timestamp . '/localFile.txt')); + $this->assertFalse($rootView->file_exists('files_trashbin/files/localFolder.d' . $timestamp . '/' . $this->folder)); + + //cleanup + $rootView->deleteAll('files_trashin'); + + if ($status === false) { + \OC_App::disable('files_trashbin'); + } + + \OC\Files\Filesystem::getLoader()->removeStorageWrapper('oc_trashbin'); + } + + public function shareFolderProvider() { + return [ + ['/'], + ['/my_shares'], + ]; + } + + /** + * if a file gets shared the etag for the recipients root should change + * + * @dataProvider shareFolderProvider + * + * @param string $shareFolder share folder to use + */ + public function testShareFile($shareFolder) { + $config = \OC::$server->getConfig(); + $oldShareFolder = $config->getSystemValue('share_folder'); + $config->setSystemValue('share_folder', $shareFolder); + + $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); + + $beforeShareRoot = \OC\Files\Filesystem::getFileInfo(''); + $etagBeforeShareRoot = $beforeShareRoot->getEtag(); + + \OC\Files\Filesystem::mkdir($shareFolder); + + $beforeShareDir = \OC\Files\Filesystem::getFileInfo($shareFolder); + $etagBeforeShareDir = $beforeShareDir->getEtag(); + + $this->loginHelper(self::TEST_FILES_SHARING_API_USER1); + + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL + ); + + $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); + + $afterShareRoot = \OC\Files\Filesystem::getFileInfo(''); + $etagAfterShareRoot = $afterShareRoot->getEtag(); + + $afterShareDir = \OC\Files\Filesystem::getFileInfo($shareFolder); + $etagAfterShareDir = $afterShareDir->getEtag(); + + $this->assertTrue(is_string($etagBeforeShareRoot)); + $this->assertTrue(is_string($etagBeforeShareDir)); + $this->assertTrue(is_string($etagAfterShareRoot)); + $this->assertTrue(is_string($etagAfterShareDir)); + $this->assertTrue($etagBeforeShareRoot !== $etagAfterShareRoot); + $this->assertTrue($etagBeforeShareDir !== $etagAfterShareDir); + + // cleanup + $this->loginHelper(self::TEST_FILES_SHARING_API_USER1); + $this->shareManager->deleteShare($share); + + $config->setSystemValue('share_folder', $oldShareFolder); + } + + /** + * if a folder gets renamed all children mount points should be renamed too + */ + function testRename() { + + $fileinfo = \OC\Files\Filesystem::getFileInfo($this->folder); + + $share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + $this->folder, + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL + ); + + $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); + + // make sure that the shared folder exists + $this->assertTrue(\OC\Files\Filesystem::file_exists($this->folder)); + + \OC\Files\Filesystem::mkdir('oldTarget'); + \OC\Files\Filesystem::mkdir('oldTarget/subfolder'); + \OC\Files\Filesystem::mkdir('newTarget'); + + \OC\Files\Filesystem::rename($this->folder, 'oldTarget/subfolder/' . $this->folder); + + // re-login to make sure that the new mount points are initialized + $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); + + \OC\Files\Filesystem::rename('/oldTarget', '/newTarget/oldTarget'); + + // re-login to make sure that the new mount points are initialized + $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); + + $this->assertTrue(\OC\Files\Filesystem::file_exists('/newTarget/oldTarget/subfolder/' . $this->folder)); + + // cleanup + $this->shareManager->deleteShare($share); + } + +} diff --git a/apps/files_sharing/tests/WatcherTest.php b/apps/files_sharing/tests/WatcherTest.php new file mode 100644 index 00000000000..512381cf1dc --- /dev/null +++ b/apps/files_sharing/tests/WatcherTest.php @@ -0,0 +1,180 @@ + + * @author Joas Schilling + * @author Jörn Friedrich Dreyer + * @author Morris Jobke + * @author Robin Appelman + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OCA\Files_Sharing\Tests; + +/** + * Class WatcherTest + * + * @group DB + */ +class WatcherTest extends TestCase { + + /** @var \OC\Files\Storage\Storage */ + private $ownerStorage; + + /** @var \OC\Files\Cache\Cache */ + private $ownerCache; + + /** @var \OC\Files\Storage\Storage */ + private $sharedStorage; + + /** @var \OC\Files\Cache\Cache */ + private $sharedCache; + + /** @var \OCP\Share\IShare */ + private $_share; + + protected function setUp() { + parent::setUp(); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + // prepare user1's dir structure + $this->view->mkdir('container'); + $this->view->mkdir('container/shareddir'); + $this->view->mkdir('container/shareddir/subdir'); + + list($this->ownerStorage, $internalPath) = $this->view->resolvePath(''); + $this->ownerCache = $this->ownerStorage->getCache(); + $this->ownerStorage->getScanner()->scan(''); + + // share "shareddir" with user2 + $this->_share = $this->share( + \OCP\Share::SHARE_TYPE_USER, + 'container/shareddir', + self::TEST_FILES_SHARING_API_USER1, + self::TEST_FILES_SHARING_API_USER2, + \OCP\Constants::PERMISSION_ALL + ); + + // login as user2 + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + + // retrieve the shared storage + $secondView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2); + list($this->sharedStorage, $internalPath) = $secondView->resolvePath('files/shareddir'); + $this->sharedCache = $this->sharedStorage->getCache(); + } + + protected function tearDown() { + if ($this->sharedCache) { + $this->sharedCache->clear(); + } + + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + + if ($this->view) { + $this->shareManager->deleteShare($this->_share); + + $this->view->deleteAll('container'); + + $this->ownerCache->clear(); + } + + parent::tearDown(); + } + + /** + * Tests that writing a file using the shared storage will propagate the file + * size to the owner's parent folders. + */ + function testFolderSizePropagationToOwnerStorage() { + $initialSizes = self::getOwnerDirSizes('files/container/shareddir'); + + $textData = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $dataLen = strlen($textData); + $this->sharedCache->put('bar.txt', array('mtime' => 10, 'storage_mtime' => 10, 'size' => $dataLen, 'mimetype' => 'text/plain')); + $this->sharedStorage->file_put_contents('bar.txt', $textData); + $this->sharedCache->put('', array('mtime' => 10, 'storage_mtime' => 10, 'size' => '-1', 'mimetype' => 'httpd/unix-directory')); + + // run the propagation code + $this->sharedStorage->getWatcher()->checkUpdate(''); + $this->sharedStorage->getCache()->correctFolderSize(''); + + // the owner's parent dirs must have increase size + $newSizes = self::getOwnerDirSizes('files/container/shareddir'); + $this->assertEquals($initialSizes[''] + $dataLen, $newSizes['']); + $this->assertEquals($initialSizes['files'] + $dataLen, $newSizes['files']); + $this->assertEquals($initialSizes['files/container'] + $dataLen, $newSizes['files/container']); + $this->assertEquals($initialSizes['files/container/shareddir'] + $dataLen, $newSizes['files/container/shareddir']); + + // no more updates + $result = $this->sharedStorage->getWatcher()->checkUpdate(''); + + $this->assertFalse($result); + } + + /** + * Tests that writing a file using the shared storage will propagate the file + * size to the owner's parent folders. + */ + function testSubFolderSizePropagationToOwnerStorage() { + $initialSizes = self::getOwnerDirSizes('files/container/shareddir/subdir'); + + $textData = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $dataLen = strlen($textData); + $this->sharedCache->put('subdir/bar.txt', array('mtime' => 10, 'storage_mtime' => 10, 'size' => $dataLen, 'mimetype' => 'text/plain')); + $this->sharedStorage->file_put_contents('subdir/bar.txt', $textData); + $this->sharedCache->put('subdir', array('mtime' => 10, 'storage_mtime' => 10, 'size' => $dataLen, 'mimetype' => 'text/plain')); + + // run the propagation code + $this->sharedStorage->getWatcher()->checkUpdate('subdir'); + $this->sharedStorage->getCache()->correctFolderSize('subdir'); + + // the owner's parent dirs must have increase size + $newSizes = self::getOwnerDirSizes('files/container/shareddir/subdir'); + $this->assertEquals($initialSizes[''] + $dataLen, $newSizes['']); + $this->assertEquals($initialSizes['files'] + $dataLen, $newSizes['files']); + $this->assertEquals($initialSizes['files/container'] + $dataLen, $newSizes['files/container']); + $this->assertEquals($initialSizes['files/container/shareddir'] + $dataLen, $newSizes['files/container/shareddir']); + $this->assertEquals($initialSizes['files/container/shareddir/subdir'] + $dataLen, $newSizes['files/container/shareddir/subdir']); + + // no more updates + $result = $this->sharedStorage->getWatcher()->checkUpdate('subdir'); + + $this->assertFalse($result); + } + + /** + * Returns the sizes of the path and its parent dirs in a hash + * where the key is the path and the value is the size. + * @param string $path + */ + function getOwnerDirSizes($path) { + $result = array(); + + while ($path != '' && $path != '' && $path != '.') { + $cachedData = $this->ownerCache->get($path); + $result[$path] = $cachedData['size']; + $path = dirname($path); + } + $cachedData = $this->ownerCache->get(''); + $result[''] = $cachedData['size']; + return $result; + } +} diff --git a/apps/files_sharing/tests/activity.php b/apps/files_sharing/tests/activity.php deleted file mode 100644 index 40a1031f779..00000000000 --- a/apps/files_sharing/tests/activity.php +++ /dev/null @@ -1,80 +0,0 @@ - - * @author Joas Schilling - * @author Morris Jobke - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_sharing\Tests; - -/** - * Class Activity - * - * @group DB - * - * @package OCA\Files_sharing\Tests - */ -class Activity extends \OCA\Files_Sharing\Tests\TestCase { - - /** - * @var \OCA\Files_Sharing\Activity - */ - private $activity; - - protected function setUp() { - parent::setUp(); - $this->activity = new \OCA\Files_Sharing\Activity( - $this->getMockBuilder('OCP\L10N\IFactory') - ->disableOriginalConstructor() - ->getMock(), - $this->getMockBuilder('OCP\IURLGenerator') - ->disableOriginalConstructor() - ->getMock(), - $this->getMockBuilder('OCP\Activity\IManager') - ->disableOriginalConstructor() - ->getMock() - ); - } - - /** - * @dataProvider dataTestGetDefaultType - */ - public function testGetDefaultTypes($method, $expectedResult) { - $result = $this->activity->getDefaultTypes($method); - - if (is_array($expectedResult)) { - $this->assertSame(count($expectedResult), count($result)); - foreach ($expectedResult as $key => $expected) { - $this->assertSame($expected, $result[$key]); - } - } else { - $this->assertSame($expectedResult, $result); - } - - } - - public function dataTestGetDefaultType() { - return array( - array('email', array(\OCA\Files_Sharing\Activity::TYPE_SHARED, \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE)), - array('stream', array(\OCA\Files_Sharing\Activity::TYPE_SHARED, \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::TYPE_PUBLIC_LINKS)), - ); - } - -} diff --git a/apps/files_sharing/tests/api.php b/apps/files_sharing/tests/api.php deleted file mode 100644 index 3ded1bfc5d4..00000000000 --- a/apps/files_sharing/tests/api.php +++ /dev/null @@ -1,1599 +0,0 @@ - - * @author Joas Schilling - * @author Morris Jobke - * @author Robin Appelman - * @author Robin McCorkell - * @author Roeland Jago Douma - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -use OCA\Files\Share; -use OCA\Files_sharing\Tests\TestCase; - -/** - * Class Test_Files_Sharing_Api - * - * @group DB - */ -class Test_Files_Sharing_Api extends TestCase { - - const TEST_FOLDER_NAME = '/folder_share_api_test'; - - private static $tempStorage; - - /** @var \OCP\Files\Folder */ - private $userFolder; - - protected function setUp() { - parent::setUp(); - - \OC::$server->getAppConfig()->setValue('core', 'shareapi_exclude_groups', 'no'); - \OC::$server->getAppConfig()->setValue('core', 'shareapi_expire_after_n_days', '7'); - - $this->folder = self::TEST_FOLDER_NAME; - $this->subfolder = '/subfolder_share_api_test'; - $this->subsubfolder = '/subsubfolder_share_api_test'; - - $this->filename = '/share-api-test.txt'; - - // save file with content - $this->view->file_put_contents($this->filename, $this->data); - $this->view->mkdir($this->folder); - $this->view->mkdir($this->folder . $this->subfolder); - $this->view->mkdir($this->folder . $this->subfolder . $this->subsubfolder); - $this->view->file_put_contents($this->folder.$this->filename, $this->data); - $this->view->file_put_contents($this->folder . $this->subfolder . $this->filename, $this->data); - - $this->userFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1); - } - - protected function tearDown() { - if($this->view instanceof \OC\Files\View) { - $this->view->unlink($this->filename); - $this->view->deleteAll($this->folder); - } - - self::$tempStorage = null; - - parent::tearDown(); - } - - /** - * @param array $data - * @return \OCP\IRequest - */ - private function createRequest(array $data) { - $request = $this->getMock('\OCP\IRequest'); - $request->method('getParam') - ->will($this->returnCallback(function($param, $default = null) use ($data) { - if (isset($data[$param])) { - return $data[$param]; - } - return $default; - })); - return $request; - } - - /** - * @param \OCP\IRequest $request - * @param string $userId The userId of the caller - * @return \OCA\Files_Sharing\API\Share20OCS - */ - private function createOCS($request, $userId) { - $currentUser = \OC::$server->getUserManager()->get($userId); - - $l = $this->getMock('\OCP\IL10N'); - $l->method('t') - ->will($this->returnCallback(function($text, $parameters = []) { - return vsprintf($text, $parameters); - })); - - return new \OCA\Files_Sharing\API\Share20OCS( - $this->shareManager, - \OC::$server->getGroupManager(), - \OC::$server->getUserManager(), - $request, - \OC::$server->getRootFolder(), - \OC::$server->getURLGenerator(), - $currentUser, - $l - ); - } - - /** - * @medium - */ - function testCreateShareUserFile() { - // simulate a post request - $data['path'] = $this->filename; - $data['shareWith'] = \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2; - $data['shareType'] = \OCP\Share::SHARE_TYPE_USER; - - $request = $this->createRequest($data); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - $this->assertEquals(19, $data['permissions']); - $this->assertEmpty($data['expiration']); - - $this->shareManager->getShareById('ocinternal:'.$data['id']); - - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->deleteShare($data['id']); - $this->assertTrue($result->succeeded()); - } - - function testCreateShareUserFolder() { - // simulate a post request - $data['path'] = $this->folder; - $data['shareWith'] = \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2; - $data['shareType'] = \OCP\Share::SHARE_TYPE_USER; - - $request = $this->createRequest($data); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - $this->assertEquals(31, $data['permissions']); - $this->assertEmpty($data['expiration']); - - $this->shareManager->getShareById('ocinternal:'.$data['id']); - - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->deleteShare($data['id']); - $this->assertTrue($result->succeeded()); - } - - - function testCreateShareGroupFile() { - // simulate a post request - $data['path'] = $this->filename; - $data['shareWith'] = \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_GROUP1; - $data['shareType'] = \OCP\Share::SHARE_TYPE_GROUP; - - $request = $this->createRequest($data); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - $this->assertEquals(19, $data['permissions']); - $this->assertEmpty($data['expiration']); - - $this->shareManager->getShareById('ocinternal:'.$data['id']); - - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->deleteShare($data['id']); - $this->assertTrue($result->succeeded()); - } - - function testCreateShareGroupFolder() { - // simulate a post request - $data['path'] = $this->folder; - $data['shareWith'] = \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_GROUP1; - $data['shareType'] = \OCP\Share::SHARE_TYPE_GROUP; - - $request = $this->createRequest($data); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - $this->assertEquals(31, $data['permissions']); - $this->assertEmpty($data['expiration']); - - $this->shareManager->getShareById('ocinternal:'.$data['id']); - - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->deleteShare($data['id']); - $this->assertTrue($result->succeeded()); - } - - public function testCreateShareLink() { - // simulate a post request - $data['path'] = $this->folder; - $data['shareType'] = \OCP\Share::SHARE_TYPE_LINK; - - $request = $this->createRequest($data); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - - // check if API call was successful - $this->assertTrue($result->succeeded()); - - $data = $result->getData(); - $this->assertEquals(1, $data['permissions']); - $this->assertEmpty($data['expiration']); - $this->assertTrue(is_string($data['token'])); - - // check for correct link - $url = \OC::$server->getURLGenerator()->getAbsoluteURL('/index.php/s/' . $data['token']); - $this->assertEquals($url, $data['url']); - - $this->shareManager->getShareById('ocinternal:'.$data['id']); - - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->deleteShare($data['id']); - $this->assertTrue($result->succeeded()); - } - - public function testCreateShareLinkPublicUpload() { - // simulate a post request - $data['path'] = $this->folder; - $data['shareType'] = \OCP\Share::SHARE_TYPE_LINK; - $data['publicUpload'] = 'true'; - - $request = $this->createRequest($data); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - - // check if API call was successful - $this->assertTrue($result->succeeded()); - - $data = $result->getData(); - $this->assertEquals(7, $data['permissions']); - $this->assertEmpty($data['expiration']); - $this->assertTrue(is_string($data['token'])); - - // check for correct link - $url = \OC::$server->getURLGenerator()->getAbsoluteURL('/index.php/s/' . $data['token']); - $this->assertEquals($url, $data['url']); - - $this->shareManager->getShareById('ocinternal:'.$data['id']); - - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->deleteShare($data['id']); - $this->assertTrue($result->succeeded()); - } - - function testEnfoceLinkPassword() { - - $appConfig = \OC::$server->getAppConfig(); - $appConfig->setValue('core', 'shareapi_enforce_links_password', 'yes'); - - // don't allow to share link without a password - $data['path'] = $this->folder; - $data['shareType'] = \OCP\Share::SHARE_TYPE_LINK; - - $request = $this->createRequest($data); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - $this->assertFalse($result->succeeded()); - - // don't allow to share link without a empty password - $data = []; - $data['path'] = $this->folder; - $data['shareType'] = \OCP\Share::SHARE_TYPE_LINK; - $data['password'] = ''; - - $request = $this->createRequest($data); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - $this->assertFalse($result->succeeded()); - - // share with password should succeed - $data = []; - $data['path'] = $this->folder; - $data['shareType'] = \OCP\Share::SHARE_TYPE_LINK; - $data['password'] = 'foo'; - - $request = $this->createRequest($data); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - $this->assertTrue($result->succeeded()); - - $data = $result->getData(); - - // setting new password should succeed - $data2 = [ - 'password' => 'bar', - ]; - $request = $this->createRequest($data2); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->updateShare($data['id']); - $this->assertTrue($result->succeeded()); - - // removing password should fail - $data2 = [ - 'password' => '', - ]; - $request = $this->createRequest($data2); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->updateShare($data['id']); - $this->assertFalse($result->succeeded()); - - // cleanup - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->deleteShare($data['id']); - $this->assertTrue($result->succeeded()); - - $appConfig->setValue('core', 'shareapi_enforce_links_password', 'no'); - } - - /** - * @medium - */ - function testSharePermissions() { - // sharing file to a user should work if shareapi_exclude_groups is set - // to no - \OC::$server->getAppConfig()->setValue('core', 'shareapi_exclude_groups', 'no'); - $post['path'] = $this->filename; - $post['shareWith'] = \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2; - $post['shareType'] = \OCP\Share::SHARE_TYPE_USER; - - $request = $this->createRequest($post); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - - $this->shareManager->getShareById('ocinternal:'.$data['id']); - - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->deleteShare($data['id']); - $this->assertTrue($result->succeeded()); - - // exclude groups, but not the group the user belongs to. Sharing should still work - \OC::$server->getAppConfig()->setValue('core', 'shareapi_exclude_groups', 'yes'); - \OC::$server->getAppConfig()->setValue('core', 'shareapi_exclude_groups_list', 'admin,group1,group2'); - - $post = []; - $post['path'] = $this->filename; - $post['shareWith'] = \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2; - $post['shareType'] = \OCP\Share::SHARE_TYPE_USER; - - $request = $this->createRequest($post); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - - $this->shareManager->getShareById('ocinternal:' . $data['id']); - - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->deleteShare($data['id']); - $this->assertTrue($result->succeeded()); - - // now we exclude the group the user belongs to ('group'), sharing should fail now - \OC::$server->getAppConfig()->setValue('core', 'shareapi_exclude_groups_list', 'admin,group'); - - $post = []; - $post['path'] = $this->filename; - $post['shareWith'] = \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2; - $post['shareType'] = \OCP\Share::SHARE_TYPE_USER; - - $request = $this->createRequest($post); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - - // cleanup - \OC::$server->getAppConfig()->setValue('core', 'shareapi_exclude_groups', 'no'); - \OC::$server->getAppConfig()->setValue('core', 'shareapi_exclude_groups_list', ''); - } - - - /** - * @medium - */ - function testGetAllShares() { - $node = $this->userFolder->get($this->filename); - - $share = $this->shareManager->newShare(); - $share->setNode($node) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(19); - - $share = $this->shareManager->createShare($share); - - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->getShares(); - - $this->assertTrue($result->succeeded()); - $this->assertTrue(count($result->getData()) === 1); - - $this->shareManager->deleteShare($share); - } - - function testGetAllSharesWithMe() { - $node1 = $this->userFolder->get($this->filename); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(19); - $share1 = $this->shareManager->createShare($share1); - - $node2 = $this->userFolder->get($this->folder); - $share2 = $this->shareManager->newShare(); - $share2->setNode($node2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(31); - $share2 = $this->shareManager->createShare($share2); - - $request = $this->createRequest(['shared_with_me' => 'true']); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); - $result = $ocs->getShares(); - - $this->assertTrue($result->succeeded()); - $this->assertTrue(count($result->getData()) === 2); - - $this->shareManager->deleteShare($share1); - $this->shareManager->deleteShare($share2); - } - - /** - * @medium - */ - function testPublicLinkUrl() { - // simulate a post request - $post['path'] = $this->folder; - $post['shareType'] = \OCP\Share::SHARE_TYPE_LINK; - - $request = $this->createRequest($post); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - $this->assertTrue($result->succeeded()); - - $data = $result->getData(); - - // check if we have a token - $this->assertTrue(is_string($data['token'])); - $id = $data['id']; - - // check for correct link - $url = \OC::$server->getURLGenerator()->getAbsoluteURL('/index.php/s/' . $data['token']); - $this->assertEquals($url, $data['url']); - - // check for link in getall shares - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->getShares(); - $this->assertTrue($result->succeeded()); - - $data = $result->getData(); - $this->assertEquals($url, current($data)['url']); - - // check for path - $request = $this->createRequest(['path' => $this->folder]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->getShares(); - $this->assertTrue($result->succeeded()); - - $data = $result->getData(); - $this->assertEquals($url, current($data)['url']); - - // check in share id - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->getShare($id); - $this->assertTrue($result->succeeded()); - - $data = $result->getData(); - $this->assertEquals($url, current($data)['url']); - - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->deleteShare($id); - $this->assertTrue($result->succeeded()); - } - - /** - * @medium - * @depends testCreateShareUserFile - * @depends testCreateShareLink - */ - function testGetShareFromSource() { - $node = $this->userFolder->get($this->filename); - $share = $this->shareManager->newShare(); - $share->setNode($node) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(19); - $share1 = $this->shareManager->createShare($share); - - $share = $this->shareManager->newShare(); - $share->setNode($node) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPermissions(1); - $share2 = $this->shareManager->createShare($share); - - $request = $this->createRequest(['path' => $this->filename]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->getShares(); - $this->assertTrue($result->succeeded()); - - // test should return one share created from testCreateShare() - $this->assertTrue(count($result->getData()) === 2); - - $this->shareManager->deleteShare($share1); - $this->shareManager->deleteShare($share2); - } - - /** - * @medium - * @depends testCreateShareUserFile - * @depends testCreateShareLink - */ - function testGetShareFromSourceWithReshares() { - $node = $this->userFolder->get($this->filename); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(19); - $share1 = $this->shareManager->createShare($share1); - - $share2 = $this->shareManager->newShare(); - $share2->setNode($node) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER3) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(19); - $share2 = $this->shareManager->createShare($share2); - - $request = $this->createRequest(['path' => $this->filename]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->getShares(); - $this->assertTrue($result->succeeded()); - - // test should return one share - $this->assertTrue(count($result->getData()) === 1); - - // now also ask for the reshares - $request = $this->createRequest(['path' => $this->filename, 'reshares' => 'true']); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->getShares(); - $this->assertTrue($result->succeeded()); - - $this->assertTrue($result->succeeded()); - - // now we should get two shares, the initial share and the reshare - $this->assertCount(2, $result->getData()); - - $this->shareManager->deleteShare($share1); - $this->shareManager->deleteShare($share2); - } - - /** - * @medium - * @depends testCreateShareUserFile - */ - function testGetShareFromId() { - $node = $this->userFolder->get($this->filename); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(19); - $share1 = $this->shareManager->createShare($share1); - - // call getShare() with share ID - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->getShare($share1->getId()); - $this->assertTrue($result->succeeded()); - - // test should return one share created from testCreateShare() - $this->assertEquals(1, count($result->getData())); - - $this->shareManager->deleteShare($share1); - } - - /** - * @medium - */ - function testGetShareFromFolder() { - $node1 = $this->userFolder->get($this->filename); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(19); - $share1 = $this->shareManager->createShare($share1); - - $node2 = $this->userFolder->get($this->folder.'/'.$this->filename); - $share2 = $this->shareManager->newShare(); - $share2->setNode($node2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPermissions(1); - $share2 = $this->shareManager->createShare($share2); - - - $request = $this->createRequest(['path' => $this->folder, 'subfiles' => 'true']); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->getShares(); - $this->assertTrue($result->succeeded()); - - // test should return one share within $this->folder - $this->assertTrue(count($result->getData()) === 1); - - $this->shareManager->deleteShare($share1); - $this->shareManager->deleteShare($share2); - } - - function testGetShareFromFolderWithFile() { - $node1 = $this->userFolder->get($this->filename); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(19); - $share1 = $this->shareManager->createShare($share1); - - $request = $this->createRequest(['path' => $this->filename, 'subfiles' => 'true']); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->getShares(); - - $this->assertFalse($result->succeeded()); - $this->assertEquals(400, $result->getStatusCode()); - $this->assertEquals('Not a directory', $result->getMeta()['message']); - - $this->shareManager->deleteShare($share1); - } - - /** - * share a folder, than reshare a file within the shared folder and check if we construct the correct path - * @medium - */ - function testGetShareFromFolderReshares() { - $node1 = $this->userFolder->get($this->folder); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(31); - $share1 = $this->shareManager->createShare($share1); - - $node2 = $this->userFolder->get($this->folder.'/'.$this->filename); - $share2 = $this->shareManager->newShare(); - $share2->setNode($node2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPermissions(1); - $share2 = $this->shareManager->createShare($share2); - - $node3 = $this->userFolder->get($this->folder.'/'.$this->subfolder.'/'.$this->filename); - $share3 = $this->shareManager->newShare(); - $share3->setNode($node3) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPermissions(1); - $share3 = $this->shareManager->createShare($share3); - - $testValues=array( - array('query' => $this->folder, - 'expectedResult' => $this->folder . $this->filename), - array('query' => $this->folder . $this->subfolder, - 'expectedResult' => $this->folder . $this->subfolder . $this->filename), - ); - foreach ($testValues as $value) { - - $request = $this->createRequest(['path' => $value['query'], 'subfiles' => 'true']); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); - $result = $ocs->getShares(); - $this->assertTrue($result->succeeded()); - - // test should return one share within $this->folder - $data = $result->getData(); - - $this->assertEquals($value['expectedResult'], $data[0]['path']); - } - - // cleanup - $this->shareManager->deleteShare($share1); - $this->shareManager->deleteShare($share2); - $this->shareManager->deleteShare($share3); - } - - /** - * reshare a sub folder and check if we get the correct path - * @medium - */ - function testGetShareFromSubFolderReShares() { - $node1 = $this->userFolder->get($this->folder . $this->subfolder); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(31); - $share1 = $this->shareManager->createShare($share1); - - $node2 = \OC::$server->getRootFolder()->getUserFolder(self::TEST_FILES_SHARING_API_USER2)->get($this->subfolder); - $share2 = $this->shareManager->newShare(); - $share2->setNode($node2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPermissions(1); - $share2 = $this->shareManager->createShare($share2); - - $request = $this->createRequest(['path' => '/', 'subfiles' => 'true']); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); - $result = $ocs->getShares(); - $this->assertTrue($result->succeeded()); - - // test should return one share within $this->folder - $data = $result->getData(); - - // we should get exactly one result - $this->assertCount(1, $data); - - $expectedPath = $this->folder . $this->subfolder; - $this->assertEquals($expectedPath, $data[0]['path']); - - $this->shareManager->deleteShare($share2); - $this->shareManager->deleteShare($share1); - } - - /** - * test re-re-share of folder if the path gets constructed correctly - * @medium - */ - function testGetShareFromFolderReReShares() { - $node1 = $this->userFolder->get($this->folder . $this->subfolder); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(31); - $share1 = $this->shareManager->createShare($share1); - - $node2 = $this->userFolder->get($this->folder . $this->subfolder . $this->subsubfolder); - $share2 = $this->shareManager->newShare(); - $share2->setNode($node2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER3) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(31); - $share2 = $this->shareManager->createShare($share2); - - $share3 = $this->shareManager->newShare(); - $share3->setNode($node2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER3) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPermissions(1); - $share3 = $this->shareManager->createShare($share3); - - $request = $this->createRequest(['path' => '/', 'subfiles' => 'true']); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER3); - $result = $ocs->getShares(); - $this->assertTrue($result->succeeded()); - - // test should return one share within $this->folder - $data = $result->getData(); - - // we should get exactly one result - $this->assertCount(1, $data); - - $expectedPath = $this->folder . $this->subfolder . $this->subsubfolder; - $this->assertEquals($expectedPath, $data[0]['path']); - - $this->shareManager->deleteShare($share1); - $this->shareManager->deleteShare($share2); - $this->shareManager->deleteShare($share3); - } - - /** - * test multiple shared folder if the path gets constructed correctly - * @medium - */ - function testGetShareMultipleSharedFolder() { - $node1 = $this->userFolder->get($this->folder . $this->subfolder); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(31); - $share1 = $this->shareManager->createShare($share1); - - $node2 = $this->userFolder->get($this->folder); - $share2 = $this->shareManager->newShare(); - $share2->setNode($node2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(31); - $share2 = $this->shareManager->createShare($share2); - - $share3 = $this->shareManager->newShare(); - $share3->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPermissions(1); - $share3 = $this->shareManager->createShare($share3); - - $request = $this->createRequest(['path' => $this->subfolder]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); - $result1 = $ocs->getShares(); - $this->assertTrue($result1->succeeded()); - - // test should return one share within $this->folder - $data1 = $result1->getData(); - $this->assertCount(1, $data1); - $s1 = reset($data1); - - $request = $this->createRequest(['path' => $this->folder.$this->subfolder]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); - $result2 = $ocs->getShares(); - $this->assertTrue($result2->succeeded()); - - // test should return one share within $this->folder - $data2 = $result2->getData(); - $this->assertCount(1, $data2); - $s2 = reset($data2); - - $this->assertEquals($this->folder.$this->subfolder, $s1['path']); - $this->assertEquals($this->folder.$this->subfolder, $s2['path']); - - $this->shareManager->deleteShare($share1); - $this->shareManager->deleteShare($share2); - $this->shareManager->deleteShare($share3); - } - - /** - * test re-re-share of folder if the path gets constructed correctly - * @medium - */ - function testGetShareFromFileReReShares() { - $node1 = $this->userFolder->get($this->folder . $this->subfolder); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(31); - $share1 = $this->shareManager->createShare($share1); - - $user2Folder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER2); - $node2 = $user2Folder->get($this->subfolder . $this->filename); - $share2 = $this->shareManager->newShare(); - $share2->setNode($node2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER3) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(19); - $share2 = $this->shareManager->createShare($share2); - - $user3Folder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER3); - $node3 = $user3Folder->get($this->filename); - $share3 = $this->shareManager->newShare(); - $share3->setNode($node3) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER3) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPermissions(1); - $share3 = $this->shareManager->createShare($share3); - - $request = $this->createRequest(['path' => '/', 'subfiles' => 'true']); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER3); - $result = $ocs->getShares(); - $this->assertTrue($result->succeeded()); - - // test should return one share within $this->folder - $data = $result->getData(); - - // we should get exactly one result - $this->assertCount(1, $data); - - $expectedPath = $this->folder.$this->subfolder.$this->filename; - $this->assertEquals($expectedPath, $data[0]['path']); - - $this->shareManager->deleteShare($share1); - $this->shareManager->deleteShare($share2); - $this->shareManager->deleteShare($share3); - } - - /** - * @medium - */ - function testGetShareFromUnknownId() { - $request = $this->createRequest(['path' => '/', 'subfiles' => 'true']); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER3); - $result = $ocs->getShare(0); - $this->assertFalse($result->succeeded()); - - $this->assertEquals(404, $result->getStatusCode()); - $meta = $result->getMeta(); - $this->assertEquals('Wrong share ID, share doesn\'t exist', $meta['message']); - } - - /** - * @medium - * @depends testCreateShareUserFile - * @depends testCreateShareLink - */ - function testUpdateShare() { - $node1 = $this->userFolder->get($this->filename); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(19); - $share1 = $this->shareManager->createShare($share1); - - $share2 = $this->shareManager->newShare(); - $share2->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPermissions(1); - $share2 = $this->shareManager->createShare($share2); - - // update permissions - $params = array(); - $params['permissions'] = 1; - - $request = $this->createRequest(['permissions' => 1]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->updateShare($share1->getId()); - $this->assertTrue($result->succeeded()); - - $meta = $result->getMeta(); - $this->assertTrue($result->succeeded(), $meta['message']); - - $share1 = $this->shareManager->getShareById('ocinternal:' . $share1->getId()); - $this->assertEquals(1, $share1->getPermissions()); - - // update password for link share - $this->assertNull($share2->getPassword()); - - $request = $this->createRequest(['password' => 'foo']); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->updateShare($share2->getId()); - $this->assertTrue($result->succeeded()); - - $share2 = $this->shareManager->getShareById('ocinternal:' . $share2->getId()); - $this->assertNotNull($share2->getPassword()); - - $request = $this->createRequest(['password' => '']); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->updateShare($share2->getId()); - $this->assertTrue($result->succeeded()); - - $share2 = $this->shareManager->getShareById('ocinternal:' . $share2->getId()); - $this->assertNull($share2->getPassword()); - - $this->shareManager->deleteShare($share1); - $this->shareManager->deleteShare($share2); - } - - /** - * @medium - * @depends testCreateShareUserFile - */ - public function testUpdateShareInvalidPermissions() { - $node1 = $this->userFolder->get($this->filename); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(19); - $share1 = $this->shareManager->createShare($share1); - - $request = $this->createRequest(['permissions' => \OCP\Constants::PERMISSION_ALL]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->updateShare($share1->getId()); - - //Updating should fail with 400 - $this->assertFalse($result->succeeded()); - $this->assertEquals(400, $result->getStatusCode()); - - //Permissions should not have changed! - $share1 = $this->shareManager->getShareById('ocinternal:' . $share1->getId()); - $this->assertEquals(19, $share1->getPermissions()); - - $this->shareManager->deleteShare($share1); - } - - /** - * @medium - */ - function testUpdateShareUpload() { - $node1 = $this->userFolder->get($this->folder); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPermissions(1); - $share1 = $this->shareManager->createShare($share1); - - // update public upload - $request = $this->createRequest(['publicUpload' => 'true']); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->updateShare($share1->getId()); - $this->assertTrue($result->succeeded()); - - $share1 = $this->shareManager->getShareById($share1->getFullId()); - $this->assertEquals(7, $share1->getPermissions()); - - // cleanup - $this->shareManager->deleteShare($share1); - } - - /** - * @medium - */ - function testUpdateShareExpireDate() { - $node1 = $this->userFolder->get($this->folder); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPermissions(1); - $share1 = $this->shareManager->createShare($share1); - - $config = \OC::$server->getConfig(); - - // enforce expire date, by default 7 days after the file was shared - $config->setAppValue('core', 'shareapi_default_expire_date', 'yes'); - $config->setAppValue('core', 'shareapi_enforce_expire_date', 'yes'); - - $dateWithinRange = new \DateTime(); - $dateWithinRange->setTime(0,0,0); - $dateWithinRange->add(new \DateInterval('P5D')); - $dateOutOfRange = new \DateTime(); - $dateOutOfRange->setTime(0,0,0); - $dateOutOfRange->add(new \DateInterval('P8D')); - - // update expire date to a valid value - $request = $this->createRequest(['expireDate' => $dateWithinRange->format('Y-m-d')]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->updateShare($share1->getId()); - $this->assertTrue($result->succeeded()); - - $share1 = $this->shareManager->getShareById($share1->getFullId()); - - // date should be changed - $this->assertEquals($dateWithinRange, $share1->getExpirationDate()); - - // update expire date to a value out of range - $request = $this->createRequest(['expireDate' => $dateOutOfRange->format('Y-m-d')]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->updateShare($share1->getId()); - $this->assertFalse($result->succeeded()); - - $share1 = $this->shareManager->getShareById($share1->getFullId()); - - // date shouldn't be changed - $this->assertEquals($dateWithinRange, $share1->getExpirationDate()); - - // Try to remove expire date - $request = $this->createRequest(['expireDate' => '']); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->updateShare($share1->getId()); - $this->assertFalse($result->succeeded()); - - $share1 = $this->shareManager->getShareById($share1->getFullId()); - - - // date shouldn't be changed - $this->assertEquals($dateWithinRange, $share1->getExpirationDate()); - // cleanup - $config->setAppValue('core', 'shareapi_default_expire_date', 'no'); - $config->setAppValue('core', 'shareapi_enforce_expire_date', 'no'); - $this->shareManager->deleteShare($share1); - } - - /** - * @medium - * @depends testCreateShareUserFile - */ - function testDeleteShare() { - $node1 = $this->userFolder->get($this->filename); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(19); - $share1 = $this->shareManager->createShare($share1); - - $share2 = $this->shareManager->newShare(); - $share2->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPermissions(1); - $share2 = $this->shareManager->createShare($share1); - - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->deleteShare($share1->getId()); - $this->assertTrue($result->succeeded()); - - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->deleteShare($share2->getId()); - $this->assertTrue($result->succeeded()); - - $this->assertEmpty($this->shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER2, \OCP\Share::SHARE_TYPE_USER)); - $this->assertEmpty($this->shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER2, \OCP\Share::SHARE_TYPE_LINK)); - } - - /** - * test unshare of a reshared file - */ - function testDeleteReshare() { - $node1 = $this->userFolder->get($this->folder); - $share1 = $this->shareManager->newShare(); - $share1->setNode($node1) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setPermissions(31); - $share1 = $this->shareManager->createShare($share1); - - $user2folder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER2); - $node2 = $user2folder->get($this->folder.'/'.$this->filename); - $share2 = $this->shareManager->newShare(); - $share2->setNode($node2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPermissions(1); - $share2 = $this->shareManager->createShare($share2); - - // test if we can unshare the link again - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); - $result = $ocs->deleteShare($share2->getId()); - $this->assertTrue($result->succeeded()); - - $this->shareManager->deleteShare($share1); - } - - /** - * share a folder which contains a share mount point, should be forbidden - */ - public function testShareFolderWithAMountPoint() { - // user 1 shares a folder with user2 - \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1); - - $fileInfo = $this->view->getFileInfo($this->folder); - - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL - ); - - // user2 shares a file from the folder as link - \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2); - - $view = new \OC\Files\View('/' . \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2 . '/files'); - $view->mkdir("localDir"); - - // move mount point to the folder "localDir" - $result = $view->rename($this->folder, 'localDir/'.$this->folder); - $this->assertTrue($result !== false); - - // try to share "localDir" - $fileInfo2 = $view->getFileInfo('localDir'); - - $this->assertTrue($fileInfo2 instanceof \OC\Files\FileInfo); - - $pass = true; - try { - $this->share( - \OCP\Share::SHARE_TYPE_USER, - 'localDir', - self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3, - \OCP\Constants::PERMISSION_ALL - ); - } catch (\Exception $e) { - $pass = false; - } - - $this->assertFalse($pass); - - //cleanup - - $result = $view->rename('localDir/' . $this->folder, $this->folder); - $this->assertTrue($result !== false); - $view->unlink('localDir'); - - \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1); - - $this->shareManager->deleteShare($share); - } - - /** - * Post init mount points hook for mounting simulated ext storage - */ - public static function initTestMountPointsHook($data) { - if ($data['user'] === \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1) { - \OC\Files\Filesystem::mount(self::$tempStorage, array(), '/' . \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1 . '/files' . self::TEST_FOLDER_NAME); - } - } - - /** - * Tests mounting a folder that is an external storage mount point. - */ - public function testShareStorageMountPoint() { - self::$tempStorage = new \OC\Files\Storage\Temporary(array()); - self::$tempStorage->file_put_contents('test.txt', 'abcdef'); - self::$tempStorage->getScanner()->scan(''); - - // needed because the sharing code sometimes switches the user internally and mounts the user's - // storages. In our case the temp storage isn't mounted automatically, so doing it in the post hook - // (similar to how ext storage works) - OCP\Util::connectHook('OC_Filesystem', 'post_initMountPoints', '\Test_Files_Sharing_Api', 'initTestMountPointsHook'); - - // logging in will auto-mount the temp storage for user1 as well - \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1); - - $fileInfo = $this->view->getFileInfo($this->folder); - - // user 1 shares the mount point folder with user2 - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL - ); - - // user2: check that mount point name appears correctly - \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2); - - $view = new \OC\Files\View('/' . \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2 . '/files'); - - $this->assertTrue($view->file_exists($this->folder)); - $this->assertTrue($view->file_exists($this->folder . '/test.txt')); - - \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1); - - $this->shareManager->deleteShare($share); - - \OC_Hook::clear('OC_Filesystem', 'post_initMountPoints', '\Test_Files_Sharing_Api', 'initTestMountPointsHook'); - } - /** - * @expectedException \Exception - */ - public function testShareNonExisting() { - \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1); - - $id = PHP_INT_MAX - 1; - \OCP\Share::shareItem('file', $id, \OCP\Share::SHARE_TYPE_LINK, \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2, 31); - } - - /** - * @expectedException \Exception - */ - public function testShareNotOwner() { - \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2); - \OC\Files\Filesystem::file_put_contents('foo.txt', 'bar'); - $info = \OC\Files\Filesystem::getFileInfo('foo.txt'); - - \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1); - - \OCP\Share::shareItem('file', $info->getId(), \OCP\Share::SHARE_TYPE_LINK, \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2, 31); - } - - public function testDefaultExpireDate() { - \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1); - - // TODO drop this once all code paths use the DI version - otherwise - // the cache inside this config object is out of date because - // OC_Appconfig is used and bypasses this cache which lead to integrity - // constraint violations - $config = \OC::$server->getConfig(); - $config->deleteAppValue('core', 'shareapi_default_expire_date'); - $config->deleteAppValue('core', 'shareapi_enforce_expire_date'); - $config->deleteAppValue('core', 'shareapi_expire_after_n_days'); - - $config->setAppValue('core', 'shareapi_default_expire_date', 'yes'); - $config->setAppValue('core', 'shareapi_enforce_expire_date', 'yes'); - $config->setAppValue('core', 'shareapi_expire_after_n_days', '2'); - - // default expire date is set to 2 days - // the time when the share was created is set to 3 days in the past - // user defined expire date is set to +2 days from now on - // -> link should be already expired by the default expire date but the user - // share should still exists. - $now = time(); - $dateFormat = 'Y-m-d H:i:s'; - $shareCreated = $now - 3 * 24 * 60 * 60; - $expireDate = date($dateFormat, $now + 2 * 24 * 60 * 60); - - $info = OC\Files\Filesystem::getFileInfo($this->filename); - $this->assertTrue($info instanceof \OC\Files\FileInfo); - - $result = \OCP\Share::shareItem('file', $info->getId(), \OCP\Share::SHARE_TYPE_LINK, null, \OCP\Constants::PERMISSION_READ); - $this->assertTrue(is_string($result)); - - $result = \OCP\Share::shareItem('file', $info->getId(), \OCP\Share::SHARE_TYPE_USER, \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2, 31); - $this->assertTrue($result); - - $result = \OCP\Share::setExpirationDate('file', $info->getId() , $expireDate, $now); - $this->assertTrue($result); - - //manipulate stime so that both shares are older then the default expire date - $statement = "UPDATE `*PREFIX*share` SET `stime` = ? WHERE `share_type` = ?"; - $query = \OCP\DB::prepare($statement); - $result = $query->execute(array($shareCreated, \OCP\Share::SHARE_TYPE_LINK)); - $this->assertSame(1, $result); - $query = \OCP\DB::prepare($statement); - $result = $query->execute(array($shareCreated, \OCP\Share::SHARE_TYPE_USER)); - $this->assertSame(1, $result); - - // now the link share should expire because of enforced default expire date - // the user share should still exist - $result = \OCP\Share::getItemShared('file', $info->getId()); - $this->assertTrue(is_array($result)); - $this->assertSame(1, count($result)); - $share = reset($result); - $this->assertSame(\OCP\Share::SHARE_TYPE_USER, $share['share_type']); - - //cleanup - $result = \OCP\Share::unshare('file', $info->getId(), \OCP\Share::SHARE_TYPE_USER, \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2); - $this->assertTrue($result); - $config->setAppValue('core', 'shareapi_default_expire_date', 'no'); - $config->setAppValue('core', 'shareapi_enforce_expire_date', 'no'); - - } - - public function datesProvider() { - $date = new \DateTime(); - $date->add(new \DateInterval('P5D')); - - return [ - [$date->format('Y-m-d'), true], - ['abc', false], - [$date->format('Y-m-d') . 'xyz', false], - ]; - } - - /** - * Make sure only ISO 8601 dates are accepted - * - * @dataProvider datesProvider - */ - public function testPublicLinkExpireDate($date, $valid) { - $request = $this->createRequest([ - 'path' => $this->folder, - 'shareType' => \OCP\Share::SHARE_TYPE_LINK, - 'expireDate' => $date, - ]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - - if ($valid === false) { - $this->assertFalse($result->succeeded()); - $this->assertEquals(404, $result->getStatusCode()); - $this->assertEquals('Invalid date, date format must be YYYY-MM-DD', $result->getMeta()['message']); - return; - } - - $this->assertTrue($result->succeeded()); - - $data = $result->getData(); - $this->assertTrue(is_string($data['token'])); - $this->assertEquals($date, substr($data['expiration'], 0, 10)); - - // check for correct link - $url = \OC::$server->getURLGenerator()->getAbsoluteURL('/index.php/s/' . $data['token']); - $this->assertEquals($url, $data['url']); - - $share = $this->shareManager->getShareById('ocinternal:'.$data['id']); - - $this->assertEquals($date, $share->getExpirationDate()->format('Y-m-d')); - - $this->shareManager->deleteShare($share); - } - - public function testCreatePublicLinkExpireDateValid() { - $config = \OC::$server->getConfig(); - - // enforce expire date, by default 7 days after the file was shared - $config->setAppValue('core', 'shareapi_default_expire_date', 'yes'); - $config->setAppValue('core', 'shareapi_enforce_expire_date', 'yes'); - - $date = new \DateTime(); - $date->add(new \DateInterval('P5D')); - - $request = $this->createRequest([ - 'path' => $this->folder, - 'shareType' => \OCP\Share::SHARE_TYPE_LINK, - 'expireDate' => $date->format('Y-m-d'), - ]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - $this->assertTrue($result->succeeded()); - - $data = $result->getData(); - $this->assertTrue(is_string($data['token'])); - $this->assertEquals($date->format('Y-m-d') . ' 00:00:00', $data['expiration']); - - // check for correct link - $url = \OC::$server->getURLGenerator()->getAbsoluteURL('/index.php/s/' . $data['token']); - $this->assertEquals($url, $data['url']); - - $share = $this->shareManager->getShareById('ocinternal:'.$data['id']); - $date->setTime(0,0,0); - $this->assertEquals($date, $share->getExpirationDate()); - - $this->shareManager->deleteShare($share); - - $config->setAppValue('core', 'shareapi_default_expire_date', 'no'); - $config->setAppValue('core', 'shareapi_enforce_expire_date', 'no'); - } - - public function testCreatePublicLinkExpireDateInvalidFuture() { - $config = \OC::$server->getConfig(); - - // enforce expire date, by default 7 days after the file was shared - $config->setAppValue('core', 'shareapi_default_expire_date', 'yes'); - $config->setAppValue('core', 'shareapi_enforce_expire_date', 'yes'); - - $date = new \DateTime(); - $date->add(new \DateInterval('P8D')); - - $request = $this->createRequest([ - 'path' => $this->folder, - 'shareType' => \OCP\Share::SHARE_TYPE_LINK, - 'expireDate' => $date->format('Y-m-d'), - ]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - $this->assertFalse($result->succeeded()); - $this->assertEquals(404, $result->getStatusCode()); - $this->assertEquals('Cannot set expiration date more than 7 days in the future', $result->getMeta()['message']); - - $config->setAppValue('core', 'shareapi_default_expire_date', 'no'); - $config->setAppValue('core', 'shareapi_enforce_expire_date', 'no'); - } - - public function testCreatePublicLinkExpireDateInvalidPast() { - $config = \OC::$server->getConfig(); - - $date = new \DateTime(); - $date->sub(new \DateInterval('P8D')); - - $request = $this->createRequest([ - 'path' => $this->folder, - 'shareType' => \OCP\Share::SHARE_TYPE_LINK, - 'expireDate' => $date->format('Y-m-d'), - ]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - $this->assertFalse($result->succeeded()); - $this->assertEquals(404, $result->getStatusCode()); - $this->assertEquals('Expiration date is in the past', $result->getMeta()['message']); - - $config->setAppValue('core', 'shareapi_default_expire_date', 'no'); - $config->setAppValue('core', 'shareapi_enforce_expire_date', 'no'); - } - - /** - * test for no invisible shares - * See: https://github.com/owncloud/core/issues/22295 - */ - public function testInvisibleSharesUser() { - // simulate a post request - $request = $this->createRequest([ - 'path' => $this->folder, - 'shareWith' => self::TEST_FILES_SHARING_API_USER2, - 'shareType' => \OCP\Share::SHARE_TYPE_USER - ]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - - $topId = $data['id']; - - $request = $this->createRequest([ - 'path' => $this->folder . $this->subfolder, - 'shareType' => \OCP\Share::SHARE_TYPE_LINK, - ]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); - $result = $ocs->createShare(); - $this->assertTrue($result->succeeded()); - - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->deleteShare($topId); - $this->assertTrue($result->succeeded()); - - $request = $this->createRequest([ - 'reshares' => 'true', - ]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->getShares(); - $this->assertTrue($result->succeeded()); - - $this->assertEmpty($result->getData()); - } - - /** - * test for no invisible shares - * See: https://github.com/owncloud/core/issues/22295 - */ - public function testInvisibleSharesGroup() { - // simulate a post request - $request = $this->createRequest([ - 'path' => $this->folder, - 'shareWith' => self::TEST_FILES_SHARING_API_GROUP1, - 'shareType' => \OCP\Share::SHARE_TYPE_GROUP - ]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->createShare(); - $this->assertTrue($result->succeeded()); - $data = $result->getData(); - - $topId = $data['id']; - - $request = $this->createRequest([ - 'path' => $this->folder . $this->subfolder, - 'shareType' => \OCP\Share::SHARE_TYPE_LINK, - ]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); - $result = $ocs->createShare(); - $this->assertTrue($result->succeeded()); - - $request = $this->createRequest([]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->deleteShare($topId); - $this->assertTrue($result->succeeded()); - - $request = $this->createRequest([ - 'reshares' => 'true', - ]); - $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); - $result = $ocs->getShares(); - $this->assertTrue($result->succeeded()); - - $this->assertEmpty($result->getData()); - } -} diff --git a/apps/files_sharing/tests/api/share20ocstest.php b/apps/files_sharing/tests/api/share20ocstest.php deleted file mode 100644 index 96ce34f963c..00000000000 --- a/apps/files_sharing/tests/api/share20ocstest.php +++ /dev/null @@ -1,2089 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -namespace OCA\Files_Sharing\Tests\API; - -use OCP\IL10N; -use OCA\Files_Sharing\API\Share20OCS; -use OCP\Files\NotFoundException; -use OCP\IGroupManager; -use OCP\IUserManager; -use OCP\IRequest; -use OCP\IURLGenerator; -use OCP\IUser; -use OCP\Files\IRootFolder; -use OCP\Lock\LockedException; - -/** - * Class Share20OCSTest - * - * @package OCA\Files_Sharing\Tests\API - * @group DB - */ -class Share20OCSTest extends \Test\TestCase { - - /** @var \OC\Share20\Manager | \PHPUnit_Framework_MockObject_MockObject */ - private $shareManager; - - /** @var IGroupManager | \PHPUnit_Framework_MockObject_MockObject */ - private $groupManager; - - /** @var IUserManager | \PHPUnit_Framework_MockObject_MockObject */ - private $userManager; - - /** @var IRequest | \PHPUnit_Framework_MockObject_MockObject */ - private $request; - - /** @var IRootFolder | \PHPUnit_Framework_MockObject_MockObject */ - private $rootFolder; - - /** @var IURLGenerator */ - private $urlGenerator; - - /** @var IUser */ - private $currentUser; - - /** @var Share20OCS */ - private $ocs; - - /** @var IL10N */ - private $l; - - protected function setUp() { - $this->shareManager = $this->getMockBuilder('OCP\Share\IManager') - ->disableOriginalConstructor() - ->getMock(); - $this->shareManager - ->expects($this->any()) - ->method('shareApiEnabled') - ->willReturn(true); - $this->groupManager = $this->getMock('OCP\IGroupManager'); - $this->userManager = $this->getMock('OCP\IUserManager'); - $this->request = $this->getMock('OCP\IRequest'); - $this->rootFolder = $this->getMock('OCP\Files\IRootFolder'); - $this->urlGenerator = $this->getMock('OCP\IURLGenerator'); - $this->currentUser = $this->getMock('OCP\IUser'); - $this->currentUser->method('getUID')->willReturn('currentUser'); - - $this->userManager->expects($this->any())->method('userExists')->willReturn(true); - - $this->l = $this->getMock('\OCP\IL10N'); - $this->l->method('t') - ->will($this->returnCallback(function($text, $parameters = []) { - return vsprintf($text, $parameters); - })); - - $this->ocs = new Share20OCS( - $this->shareManager, - $this->groupManager, - $this->userManager, - $this->request, - $this->rootFolder, - $this->urlGenerator, - $this->currentUser, - $this->l - ); - } - - private function mockFormatShare() { - return $this->getMockBuilder('OCA\Files_Sharing\API\Share20OCS') - ->setConstructorArgs([ - $this->shareManager, - $this->groupManager, - $this->userManager, - $this->request, - $this->rootFolder, - $this->urlGenerator, - $this->currentUser, - $this->l, - ])->setMethods(['formatShare']) - ->getMock(); - } - - private function newShare() { - return \OC::$server->getShareManager()->newShare(); - } - - public function testDeleteShareShareNotFound() { - $this->shareManager - ->expects($this->exactly(2)) - ->method('getShareById') - ->will($this->returnCallback(function($id) { - if ($id === 'ocinternal:42' || $id === 'ocFederatedSharing:42') { - throw new \OCP\Share\Exceptions\ShareNotFound(); - } else { - throw new \Exception(); - } - })); - - $this->shareManager->method('outgoingServer2ServerSharesAllowed')->willReturn(true); - - $expected = new \OC_OCS_Result(null, 404, 'Wrong share ID, share doesn\'t exist'); - $this->assertEquals($expected, $this->ocs->deleteShare(42)); - } - - public function testDeleteShare() { - $node = $this->getMock('\OCP\Files\File'); - - $share = $this->newShare(); - $share->setSharedBy($this->currentUser->getUID()) - ->setNode($node); - $this->shareManager - ->expects($this->once()) - ->method('getShareById') - ->with('ocinternal:42') - ->willReturn($share); - $this->shareManager - ->expects($this->once()) - ->method('deleteShare') - ->with($share); - - $node->expects($this->once()) - ->method('lock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - $node->expects($this->once()) - ->method('unlock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - $expected = new \OC_OCS_Result(); - $this->assertEquals($expected, $this->ocs->deleteShare(42)); - } - - public function testDeleteShareLocked() { - $node = $this->getMock('\OCP\Files\File'); - - $share = $this->newShare(); - $share->setSharedBy($this->currentUser->getUID()) - ->setNode($node); - $this->shareManager - ->expects($this->once()) - ->method('getShareById') - ->with('ocinternal:42') - ->willReturn($share); - $this->shareManager - ->expects($this->never()) - ->method('deleteShare') - ->with($share); - - $node->expects($this->once()) - ->method('lock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED) - ->will($this->throwException(new LockedException('mypath'))); - $node->expects($this->never()) - ->method('unlock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - $expected = new \OC_OCS_Result(null, 404, 'could not delete share'); - $this->assertEquals($expected, $this->ocs->deleteShare(42)); - } - - /* - * FIXME: Enable once we have a federated Share Provider - - public function testGetGetShareNotExists() { - $this->shareManager - ->expects($this->once()) - ->method('getShareById') - ->with('ocinternal:42') - ->will($this->throwException(new \OC\Share20\Exception\ShareNotFound())); - - $expected = new \OC_OCS_Result(null, 404, 'wrong share ID, share doesn\'t exist.'); - $this->assertEquals($expected, $this->ocs->getShare(42)); - } - */ - - public function createShare($id, $shareType, $sharedWith, $sharedBy, $shareOwner, $path, $permissions, - $shareTime, $expiration, $parent, $target, $mail_send, $token=null, - $password=null) { - $share = $this->getMock('\OCP\Share\IShare'); - $share->method('getId')->willReturn($id); - $share->method('getShareType')->willReturn($shareType); - $share->method('getSharedWith')->willReturn($sharedWith); - $share->method('getSharedBy')->willReturn($sharedBy); - $share->method('getShareOwner')->willReturn($shareOwner); - $share->method('getNode')->willReturn($path); - $share->method('getPermissions')->willReturn($permissions); - $time = new \DateTime(); - $time->setTimestamp($shareTime); - $share->method('getShareTime')->willReturn($time); - $share->method('getExpirationDate')->willReturn($expiration); - $share->method('getTarget')->willReturn($target); - $share->method('getMailSend')->willReturn($mail_send); - $share->method('getToken')->willReturn($token); - $share->method('getPassword')->willReturn($password); - - if ($shareType === \OCP\Share::SHARE_TYPE_USER || - $shareType === \OCP\Share::SHARE_TYPE_GROUP || - $shareType === \OCP\Share::SHARE_TYPE_LINK) { - $share->method('getFullId')->willReturn('ocinternal:'.$id); - } - - return $share; - } - - public function dataGetShare() { - $data = []; - - $cache = $this->getMockBuilder('OC\Files\Cache\Cache') - ->disableOriginalConstructor() - ->getMock(); - $cache->method('getNumericStorageId')->willReturn(101); - - $storage = $this->getMockBuilder('OC\Files\Storage\Storage') - ->disableOriginalConstructor() - ->getMock(); - $storage->method('getId')->willReturn('STORAGE'); - $storage->method('getCache')->willReturn($cache); - - $parentFolder = $this->getMock('OCP\Files\Folder'); - $parentFolder->method('getId')->willReturn(3); - - $file = $this->getMock('OCP\Files\File'); - $file->method('getId')->willReturn(1); - $file->method('getPath')->willReturn('file'); - $file->method('getStorage')->willReturn($storage); - $file->method('getParent')->willReturn($parentFolder); - $file->method('getMimeType')->willReturn('myMimeType'); - - $folder = $this->getMock('OCP\Files\Folder'); - $folder->method('getId')->willReturn(2); - $folder->method('getPath')->willReturn('folder'); - $folder->method('getStorage')->willReturn($storage); - $folder->method('getParent')->willReturn($parentFolder); - $folder->method('getMimeType')->willReturn('myFolderMimeType'); - - // File shared with user - $share = $this->createShare( - 100, - \OCP\Share::SHARE_TYPE_USER, - 'userId', - 'initiatorId', - 'ownerId', - $file, - 4, - 5, - null, - 6, - 'target', - 0 - ); - $expected = [ - 'id' => 100, - 'share_type' => \OCP\Share::SHARE_TYPE_USER, - 'share_with' => 'userId', - 'share_with_displayname' => 'userDisplay', - 'uid_owner' => 'initiatorId', - 'displayname_owner' => 'initiatorDisplay', - 'item_type' => 'file', - 'item_source' => 1, - 'file_source' => 1, - 'file_target' => 'target', - 'file_parent' => 3, - 'token' => null, - 'expiration' => null, - 'permissions' => 4, - 'stime' => 5, - 'parent' => null, - 'storage_id' => 'STORAGE', - 'path' => 'file', - 'storage' => 101, - 'mail_send' => 0, - 'uid_file_owner' => 'ownerId', - 'displayname_file_owner' => 'ownerDisplay', - 'mimetype' => 'myMimeType', - ]; - $data[] = [$share, $expected]; - - // Folder shared with group - $share = $this->createShare( - 101, - \OCP\Share::SHARE_TYPE_GROUP, - 'groupId', - 'initiatorId', - 'ownerId', - $folder, - 4, - 5, - null, - 6, - 'target', - 0 - ); - $expected = [ - 'id' => 101, - 'share_type' => \OCP\Share::SHARE_TYPE_GROUP, - 'share_with' => 'groupId', - 'share_with_displayname' => 'groupId', - 'uid_owner' => 'initiatorId', - 'displayname_owner' => 'initiatorDisplay', - 'item_type' => 'folder', - 'item_source' => 2, - 'file_source' => 2, - 'file_target' => 'target', - 'file_parent' => 3, - 'token' => null, - 'expiration' => null, - 'permissions' => 4, - 'stime' => 5, - 'parent' => null, - 'storage_id' => 'STORAGE', - 'path' => 'folder', - 'storage' => 101, - 'mail_send' => 0, - 'uid_file_owner' => 'ownerId', - 'displayname_file_owner' => 'ownerDisplay', - 'mimetype' => 'myFolderMimeType', - ]; - $data[] = [$share, $expected]; - - // File shared by link with Expire - $expire = \DateTime::createFromFormat('Y-m-d h:i:s', '2000-01-02 01:02:03'); - $share = $this->createShare( - 101, - \OCP\Share::SHARE_TYPE_LINK, - null, - 'initiatorId', - 'ownerId', - $folder, - 4, - 5, - $expire, - 6, - 'target', - 0, - 'token', - 'password' - ); - $expected = [ - 'id' => 101, - 'share_type' => \OCP\Share::SHARE_TYPE_LINK, - 'share_with' => 'password', - 'share_with_displayname' => 'password', - 'uid_owner' => 'initiatorId', - 'displayname_owner' => 'initiatorDisplay', - 'item_type' => 'folder', - 'item_source' => 2, - 'file_source' => 2, - 'file_target' => 'target', - 'file_parent' => 3, - 'token' => 'token', - 'expiration' => '2000-01-02 00:00:00', - 'permissions' => 4, - 'stime' => 5, - 'parent' => null, - 'storage_id' => 'STORAGE', - 'path' => 'folder', - 'storage' => 101, - 'mail_send' => 0, - 'url' => 'url', - 'uid_file_owner' => 'ownerId', - 'displayname_file_owner' => 'ownerDisplay', - 'mimetype' => 'myFolderMimeType', - ]; - $data[] = [$share, $expected]; - - return $data; - } - - /** - * @dataProvider dataGetShare - */ - public function testGetShare(\OCP\Share\IShare $share, array $result) { - $ocs = $this->getMockBuilder('OCA\Files_Sharing\API\Share20OCS') - ->setConstructorArgs([ - $this->shareManager, - $this->groupManager, - $this->userManager, - $this->request, - $this->rootFolder, - $this->urlGenerator, - $this->currentUser, - $this->l, - ])->setMethods(['canAccessShare']) - ->getMock(); - - $ocs->method('canAccessShare')->willReturn(true); - - $this->shareManager - ->expects($this->once()) - ->method('getShareById') - ->with($share->getFullId()) - ->willReturn($share); - - $userFolder = $this->getMock('OCP\Files\Folder'); - $userFolder - ->method('getRelativePath') - ->will($this->returnArgument(0)); - - $this->rootFolder->method('getUserFolder') - ->with($share->getShareOwner()) - ->willReturn($userFolder); - - $this->urlGenerator - ->method('linkToRouteAbsolute') - ->willReturn('url'); - - $initiator = $this->getMock('OCP\IUser'); - $initiator->method('getUID')->willReturn('initiatorId'); - $initiator->method('getDisplayName')->willReturn('initiatorDisplay'); - - $owner = $this->getMock('OCP\IUser'); - $owner->method('getUID')->willReturn('ownerId'); - $owner->method('getDisplayName')->willReturn('ownerDisplay'); - - $user = $this->getMock('OCP\IUser'); - $user->method('getUID')->willReturn('userId'); - $user->method('getDisplayName')->willReturn('userDisplay'); - - $group = $this->getMock('OCP\IGroup'); - $group->method('getGID')->willReturn('groupId'); - - $this->userManager->method('get')->will($this->returnValueMap([ - ['userId', $user], - ['initiatorId', $initiator], - ['ownerId', $owner], - ])); - $this->groupManager->method('get')->will($this->returnValueMap([ - ['group', $group], - ])); - - $expected = new \OC_OCS_Result([$result]); - $this->assertEquals($expected->getData(), $ocs->getShare($share->getId())->getData()); - } - - public function testGetShareInvalidNode() { - $share = \OC::$server->getShareManager()->newShare(); - $share->setSharedBy('initiator') - ->setSharedWith('recipient') - ->setShareOwner('owner'); - - $this->shareManager - ->expects($this->once()) - ->method('getShareById') - ->with('ocinternal:42') - ->willReturn($share); - - $expected = new \OC_OCS_Result(null, 404, 'Wrong share ID, share doesn\'t exist'); - $this->assertEquals($expected->getMeta(), $this->ocs->getShare(42)->getMeta()); - } - - public function testCanAccessShare() { - $share = $this->getMock('OCP\Share\IShare'); - $share->method('getShareOwner')->willReturn($this->currentUser->getUID()); - $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); - - $share = $this->getMock('OCP\Share\IShare'); - $share->method('getSharedBy')->willReturn($this->currentUser->getUID()); - $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); - - $share = $this->getMock('OCP\Share\IShare'); - $share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_USER); - $share->method('getSharedWith')->willReturn($this->currentUser->getUID()); - $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); - - $share = $this->getMock('OCP\Share\IShare'); - $share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_USER); - $share->method('getSharedWith')->willReturn($this->getMock('OCP\IUser')); - $this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); - - $share = $this->getMock('OCP\Share\IShare'); - $share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_GROUP); - $share->method('getSharedWith')->willReturn('group'); - - $group = $this->getMock('OCP\IGroup'); - $group->method('inGroup')->with($this->currentUser)->willReturn(true); - $group2 = $this->getMock('OCP\IGroup'); - $group2->method('inGroup')->with($this->currentUser)->willReturn(false); - - - $this->groupManager->method('get')->will($this->returnValueMap([ - ['group', $group], - ['group2', $group2], - ])); - $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); - - $share = $this->getMock('OCP\Share\IShare'); - $share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_GROUP); - $share->method('getSharedWith')->willReturn('group2'); - - $this->groupManager->method('get')->with('group2')->willReturn($group); - $this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); - - $share = $this->getMock('OCP\Share\IShare'); - $share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_LINK); - $this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share])); - } - - public function testCreateShareNoPath() { - $expected = new \OC_OCS_Result(null, 404, 'Please specify a file or folder path'); - - $result = $this->ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testCreateShareInvalidPath() { - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'invalid-path'], - ])); - - $userFolder = $this->getMock('\OCP\Files\Folder'); - $this->rootFolder->expects($this->once()) - ->method('getUserFolder') - ->with('currentUser') - ->willReturn($userFolder); - - $userFolder->expects($this->once()) - ->method('get') - ->with('invalid-path') - ->will($this->throwException(new \OCP\Files\NotFoundException())); - - $expected = new \OC_OCS_Result(null, 404, 'Wrong path, file/folder doesn\'t exist'); - - $result = $this->ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testCreateShareInvalidPermissions() { - $share = $this->newShare(); - $this->shareManager->method('newShare')->willReturn($share); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'valid-path'], - ['permissions', null, 32], - ])); - - $userFolder = $this->getMock('\OCP\Files\Folder'); - $this->rootFolder->expects($this->once()) - ->method('getUserFolder') - ->with('currentUser') - ->willReturn($userFolder); - - $path = $this->getMock('\OCP\Files\File'); - $userFolder->expects($this->once()) - ->method('get') - ->with('valid-path') - ->willReturn($path); - - $path->expects($this->once()) - ->method('lock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - $expected = new \OC_OCS_Result(null, 404, 'invalid permissions'); - - $result = $this->ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testCreateShareUserNoShareWith() { - $share = $this->newShare(); - $this->shareManager->method('newShare')->willReturn($share); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'valid-path'], - ['permissions', null, \OCP\Constants::PERMISSION_ALL], - ['shareType', $this->any(), \OCP\Share::SHARE_TYPE_USER], - ])); - - $userFolder = $this->getMock('\OCP\Files\Folder'); - $this->rootFolder->expects($this->once()) - ->method('getUserFolder') - ->with('currentUser') - ->willReturn($userFolder); - - $path = $this->getMock('\OCP\Files\File'); - $storage = $this->getMock('OCP\Files\Storage'); - $storage->method('instanceOfStorage') - ->with('OCA\Files_Sharing\External\Storage') - ->willReturn(false); - $path->method('getStorage')->willReturn($storage); - $userFolder->expects($this->once()) - ->method('get') - ->with('valid-path') - ->willReturn($path); - - $path->expects($this->once()) - ->method('lock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - $expected = new \OC_OCS_Result(null, 404, 'Please specify a valid user'); - - $result = $this->ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testCreateShareUserNoValidShareWith() { - $share = $this->newShare(); - $this->shareManager->method('newShare')->willReturn($share); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'valid-path'], - ['permissions', null, \OCP\Constants::PERMISSION_ALL], - ['shareType', $this->any(), \OCP\Share::SHARE_TYPE_USER], - ['shareWith', $this->any(), 'invalidUser'], - ])); - - $userFolder = $this->getMock('\OCP\Files\Folder'); - $this->rootFolder->expects($this->once()) - ->method('getUserFolder') - ->with('currentUser') - ->willReturn($userFolder); - - $path = $this->getMock('\OCP\Files\File'); - $storage = $this->getMock('OCP\Files\Storage'); - $storage->method('instanceOfStorage') - ->with('OCA\Files_Sharing\External\Storage') - ->willReturn(false); - $path->method('getStorage')->willReturn($storage); - $userFolder->expects($this->once()) - ->method('get') - ->with('valid-path') - ->willReturn($path); - - $expected = new \OC_OCS_Result(null, 404, 'Please specify a valid user'); - - $path->expects($this->once()) - ->method('lock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - $result = $this->ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testCreateShareUser() { - $share = $this->newShare(); - $this->shareManager->method('newShare')->willReturn($share); - - $ocs = $this->getMockBuilder('OCA\Files_Sharing\API\Share20OCS') - ->setConstructorArgs([ - $this->shareManager, - $this->groupManager, - $this->userManager, - $this->request, - $this->rootFolder, - $this->urlGenerator, - $this->currentUser, - $this->l, - ])->setMethods(['formatShare']) - ->getMock(); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'valid-path'], - ['permissions', null, \OCP\Constants::PERMISSION_ALL], - ['shareType', $this->any(), \OCP\Share::SHARE_TYPE_USER], - ['shareWith', null, 'validUser'], - ])); - - $userFolder = $this->getMock('\OCP\Files\Folder'); - $this->rootFolder->expects($this->once()) - ->method('getUserFolder') - ->with('currentUser') - ->willReturn($userFolder); - - $path = $this->getMock('\OCP\Files\File'); - $storage = $this->getMock('OCP\Files\Storage'); - $storage->method('instanceOfStorage') - ->with('OCA\Files_Sharing\External\Storage') - ->willReturn(false); - $path->method('getStorage')->willReturn($storage); - $userFolder->expects($this->once()) - ->method('get') - ->with('valid-path') - ->willReturn($path); - - $this->userManager->method('userExists')->with('validUser')->willReturn(true); - - $path->expects($this->once()) - ->method('lock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - $path->expects($this->once()) - ->method('unlock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - $this->shareManager->method('createShare') - ->with($this->callback(function (\OCP\Share\IShare $share) use ($path) { - return $share->getNode() === $path && - $share->getPermissions() === ( - \OCP\Constants::PERMISSION_ALL & - ~\OCP\Constants::PERMISSION_DELETE & - ~\OCP\Constants::PERMISSION_CREATE - ) && - $share->getShareType() === \OCP\Share::SHARE_TYPE_USER && - $share->getSharedWith() === 'validUser' && - $share->getSharedBy() === 'currentUser'; - })) - ->will($this->returnArgument(0)); - - $expected = new \OC_OCS_Result(); - $result = $ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testCreateShareGroupNoValidShareWith() { - $share = $this->newShare(); - $this->shareManager->method('newShare')->willReturn($share); - $this->shareManager->method('createShare')->will($this->returnArgument(0)); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'valid-path'], - ['permissions', null, \OCP\Constants::PERMISSION_ALL], - ['shareType', $this->any(), \OCP\Share::SHARE_TYPE_GROUP], - ['shareWith', $this->any(), 'invalidGroup'], - ])); - - $userFolder = $this->getMock('\OCP\Files\Folder'); - $this->rootFolder->expects($this->once()) - ->method('getUserFolder') - ->with('currentUser') - ->willReturn($userFolder); - - $path = $this->getMock('\OCP\Files\File'); - $storage = $this->getMock('OCP\Files\Storage'); - $storage->method('instanceOfStorage') - ->with('OCA\Files_Sharing\External\Storage') - ->willReturn(false); - $path->method('getStorage')->willReturn($storage); - $userFolder->expects($this->once()) - ->method('get') - ->with('valid-path') - ->willReturn($path); - - $expected = new \OC_OCS_Result(null, 404, 'Please specify a valid user'); - - $path->expects($this->once()) - ->method('lock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - $result = $this->ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testCreateShareGroup() { - $share = $this->newShare(); - $this->shareManager->method('newShare')->willReturn($share); - - $ocs = $this->getMockBuilder('OCA\Files_Sharing\API\Share20OCS') - ->setConstructorArgs([ - $this->shareManager, - $this->groupManager, - $this->userManager, - $this->request, - $this->rootFolder, - $this->urlGenerator, - $this->currentUser, - $this->l, - ])->setMethods(['formatShare']) - ->getMock(); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'valid-path'], - ['permissions', null, \OCP\Constants::PERMISSION_ALL], - ['shareType', '-1', \OCP\Share::SHARE_TYPE_GROUP], - ['shareWith', null, 'validGroup'], - ])); - - $userFolder = $this->getMock('\OCP\Files\Folder'); - $this->rootFolder->expects($this->once()) - ->method('getUserFolder') - ->with('currentUser') - ->willReturn($userFolder); - - $path = $this->getMock('\OCP\Files\Folder'); - $storage = $this->getMock('OCP\Files\Storage'); - $storage->method('instanceOfStorage') - ->with('OCA\Files_Sharing\External\Storage') - ->willReturn(false); - $path->method('getStorage')->willReturn($storage); - $userFolder->expects($this->once()) - ->method('get') - ->with('valid-path') - ->willReturn($path); - - $this->groupManager->method('groupExists')->with('validGroup')->willReturn(true); - - $this->shareManager->expects($this->once()) - ->method('allowGroupSharing') - ->willReturn(true); - - $path->expects($this->once()) - ->method('lock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - $path->expects($this->once()) - ->method('unlock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - $this->shareManager->method('createShare') - ->with($this->callback(function (\OCP\Share\IShare $share) use ($path) { - return $share->getNode() === $path && - $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && - $share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP && - $share->getSharedWith() === 'validGroup' && - $share->getSharedBy() === 'currentUser'; - })) - ->will($this->returnArgument(0)); - - $expected = new \OC_OCS_Result(); - $result = $ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testCreateShareGroupNotAllowed() { - $share = $this->newShare(); - $this->shareManager->method('newShare')->willReturn($share); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'valid-path'], - ['permissions', null, \OCP\Constants::PERMISSION_ALL], - ['shareType', '-1', \OCP\Share::SHARE_TYPE_GROUP], - ['shareWith', null, 'validGroup'], - ])); - - $userFolder = $this->getMock('\OCP\Files\Folder'); - $this->rootFolder->expects($this->once()) - ->method('getUserFolder') - ->with('currentUser') - ->willReturn($userFolder); - - $path = $this->getMock('\OCP\Files\Folder'); - $storage = $this->getMock('OCP\Files\Storage'); - $storage->method('instanceOfStorage') - ->with('OCA\Files_Sharing\External\Storage') - ->willReturn(false); - $path->method('getStorage')->willReturn($storage); - $userFolder->expects($this->once()) - ->method('get') - ->with('valid-path') - ->willReturn($path); - - $this->groupManager->method('groupExists')->with('validGroup')->willReturn(true); - - $this->shareManager->expects($this->once()) - ->method('allowGroupSharing') - ->willReturn(false); - - $expected = new \OC_OCS_Result(null, 404, 'Group sharing is disabled by the administrator'); - - $result = $this->ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testCreateShareLinkNoLinksAllowed() { - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'valid-path'], - ['shareType', '-1', \OCP\Share::SHARE_TYPE_LINK], - ])); - - $path = $this->getMock('\OCP\Files\Folder'); - $storage = $this->getMock('OCP\Files\Storage'); - $storage->method('instanceOfStorage') - ->with('OCA\Files_Sharing\External\Storage') - ->willReturn(false); - $path->method('getStorage')->willReturn($storage); - $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); - $this->rootFolder->method('get')->with('valid-path')->willReturn($path); - - $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); - - $expected = new \OC_OCS_Result(null, 404, 'Public link sharing is disabled by the administrator'); - $result = $this->ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testCreateShareLinkNoPublicUpload() { - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'valid-path'], - ['shareType', '-1', \OCP\Share::SHARE_TYPE_LINK], - ['publicUpload', null, 'true'], - ])); - - $path = $this->getMock('\OCP\Files\Folder'); - $storage = $this->getMock('OCP\Files\Storage'); - $storage->method('instanceOfStorage') - ->with('OCA\Files_Sharing\External\Storage') - ->willReturn(false); - $path->method('getStorage')->willReturn($storage); - $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); - $this->rootFolder->method('get')->with('valid-path')->willReturn($path); - - $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); - $this->shareManager->method('shareApiAllowLinks')->willReturn(true); - - $expected = new \OC_OCS_Result(null, 403, 'Public upload disabled by the administrator'); - $result = $this->ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testCreateShareLinkPublicUploadFile() { - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'valid-path'], - ['shareType', '-1', \OCP\Share::SHARE_TYPE_LINK], - ['publicUpload', null, 'true'], - ])); - - $path = $this->getMock('\OCP\Files\File'); - $storage = $this->getMock('OCP\Files\Storage'); - $storage->method('instanceOfStorage') - ->with('OCA\Files_Sharing\External\Storage') - ->willReturn(false); - $path->method('getStorage')->willReturn($storage); - $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); - $this->rootFolder->method('get')->with('valid-path')->willReturn($path); - - $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); - $this->shareManager->method('shareApiAllowLinks')->willReturn(true); - $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); - - $expected = new \OC_OCS_Result(null, 404, 'Public upload is only possible for publicly shared folders'); - $result = $this->ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testCreateShareLinkPublicUploadFolder() { - $ocs = $this->mockFormatShare(); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'valid-path'], - ['shareType', '-1', \OCP\Share::SHARE_TYPE_LINK], - ['publicUpload', null, 'true'], - ['expireDate', '', ''], - ['password', '', ''], - ])); - - $path = $this->getMock('\OCP\Files\Folder'); - $storage = $this->getMock('OCP\Files\Storage'); - $storage->method('instanceOfStorage') - ->with('OCA\Files_Sharing\External\Storage') - ->willReturn(false); - $path->method('getStorage')->willReturn($storage); - $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); - $this->rootFolder->method('get')->with('valid-path')->willReturn($path); - - $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); - $this->shareManager->method('shareApiAllowLinks')->willReturn(true); - $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); - - $this->shareManager->expects($this->once())->method('createShare')->with( - $this->callback(function (\OCP\Share\IShare $share) use ($path) { - return $share->getNode() === $path && - $share->getShareType() === \OCP\Share::SHARE_TYPE_LINK && - $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE && - $share->getSharedBy() === 'currentUser' && - $share->getPassword() === null && - $share->getExpirationDate() === null; - }) - )->will($this->returnArgument(0)); - - $expected = new \OC_OCS_Result(null); - $result = $ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testCreateShareLinkPassword() { - $ocs = $this->mockFormatShare(); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'valid-path'], - ['shareType', '-1', \OCP\Share::SHARE_TYPE_LINK], - ['publicUpload', null, 'false'], - ['expireDate', '', ''], - ['password', '', 'password'], - ])); - - $path = $this->getMock('\OCP\Files\Folder'); - $storage = $this->getMock('OCP\Files\Storage'); - $storage->method('instanceOfStorage') - ->with('OCA\Files_Sharing\External\Storage') - ->willReturn(false); - $path->method('getStorage')->willReturn($storage); - $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); - $this->rootFolder->method('get')->with('valid-path')->willReturn($path); - - $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); - $this->shareManager->method('shareApiAllowLinks')->willReturn(true); - $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); - - $this->shareManager->expects($this->once())->method('createShare')->with( - $this->callback(function (\OCP\Share\IShare $share) use ($path) { - return $share->getNode() === $path && - $share->getShareType() === \OCP\Share::SHARE_TYPE_LINK && - $share->getPermissions() === \OCP\Constants::PERMISSION_READ && - $share->getSharedBy() === 'currentUser' && - $share->getPassword() === 'password' && - $share->getExpirationDate() === null; - }) - )->will($this->returnArgument(0)); - - $expected = new \OC_OCS_Result(null); - $result = $ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testCreateShareValidExpireDate() { - $ocs = $this->mockFormatShare(); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'valid-path'], - ['shareType', '-1', \OCP\Share::SHARE_TYPE_LINK], - ['publicUpload', null, 'false'], - ['expireDate', '', '2000-01-01'], - ['password', '', ''], - ])); - - $path = $this->getMock('\OCP\Files\Folder'); - $storage = $this->getMock('OCP\Files\Storage'); - $storage->method('instanceOfStorage') - ->with('OCA\Files_Sharing\External\Storage') - ->willReturn(false); - $path->method('getStorage')->willReturn($storage); - $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); - $this->rootFolder->method('get')->with('valid-path')->willReturn($path); - - $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); - $this->shareManager->method('shareApiAllowLinks')->willReturn(true); - $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); - - $this->shareManager->expects($this->once())->method('createShare')->with( - $this->callback(function (\OCP\Share\IShare $share) use ($path) { - $date = new \DateTime('2000-01-01'); - $date->setTime(0,0,0); - - return $share->getNode() === $path && - $share->getShareType() === \OCP\Share::SHARE_TYPE_LINK && - $share->getPermissions() === \OCP\Constants::PERMISSION_READ && - $share->getSharedBy() === 'currentUser' && - $share->getPassword() === null && - $share->getExpirationDate() == $date; - }) - )->will($this->returnArgument(0)); - - $expected = new \OC_OCS_Result(null); - $result = $ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testCreateShareInvalidExpireDate() { - $ocs = $this->mockFormatShare(); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'valid-path'], - ['shareType', '-1', \OCP\Share::SHARE_TYPE_LINK], - ['publicUpload', null, 'false'], - ['expireDate', '', 'a1b2d3'], - ['password', '', ''], - ])); - - $path = $this->getMock('\OCP\Files\Folder'); - $storage = $this->getMock('OCP\Files\Storage'); - $storage->method('instanceOfStorage') - ->with('OCA\Files_Sharing\External\Storage') - ->willReturn(false); - $path->method('getStorage')->willReturn($storage); - $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); - $this->rootFolder->method('get')->with('valid-path')->willReturn($path); - - $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); - $this->shareManager->method('shareApiAllowLinks')->willReturn(true); - $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); - - $expected = new \OC_OCS_Result(null, 404, 'Invalid date, date format must be YYYY-MM-DD'); - $result = $ocs->createShare(); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - /** - * Test for https://github.com/owncloud/core/issues/22587 - * TODO: Remove once proper solution is in place - */ - public function testCreateReshareOfFederatedMountNoDeletePermissions() { - $share = \OC::$server->getShareManager()->newShare(); - $this->shareManager->method('newShare')->willReturn($share); - - $ocs = $this->getMockBuilder('OCA\Files_Sharing\API\Share20OCS') - ->setConstructorArgs([ - $this->shareManager, - $this->groupManager, - $this->userManager, - $this->request, - $this->rootFolder, - $this->urlGenerator, - $this->currentUser, - $this->l, - ])->setMethods(['formatShare']) - ->getMock(); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['path', null, 'valid-path'], - ['permissions', null, \OCP\Constants::PERMISSION_ALL], - ['shareType', $this->any(), \OCP\Share::SHARE_TYPE_USER], - ['shareWith', null, 'validUser'], - ])); - - $userFolder = $this->getMock('\OCP\Files\Folder'); - $this->rootFolder->expects($this->once()) - ->method('getUserFolder') - ->with('currentUser') - ->willReturn($userFolder); - - $path = $this->getMock('\OCP\Files\Folder'); - $storage = $this->getMock('OCP\Files\Storage'); - $storage->method('instanceOfStorage') - ->with('OCA\Files_Sharing\External\Storage') - ->willReturn(true); - $path->method('getStorage')->willReturn($storage); - $path->method('getPermissions')->willReturn(\OCP\Constants::PERMISSION_READ); - $userFolder->expects($this->once()) - ->method('get') - ->with('valid-path') - ->willReturn($path); - - $this->userManager->method('userExists')->with('validUser')->willReturn(true); - - $this->shareManager - ->expects($this->once()) - ->method('createShare') - ->with($this->callback(function (\OCP\Share\IShare $share) { - return $share->getPermissions() === \OCP\Constants::PERMISSION_READ; - })) - ->will($this->returnArgument(0)); - - $ocs->createShare(); - } - - public function testUpdateShareCantAccess() { - $node = $this->getMock('\OCP\Files\Folder'); - $share = $this->newShare(); - $share->setNode($node); - - $node->expects($this->once()) - ->method('lock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); - - $expected = new \OC_OCS_Result(null, 404, 'Wrong share ID, share doesn\'t exist'); - $result = $this->ocs->updateShare(42); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testUpdateNoParametersLink() { - $node = $this->getMock('\OCP\Files\Folder'); - $share = $this->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setSharedBy($this->currentUser->getUID()) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setNode($node); - - $node->expects($this->once()) - ->method('lock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); - - $expected = new \OC_OCS_Result(null, 400, 'Wrong or no update parameter given'); - $result = $this->ocs->updateShare(42); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testUpdateNoParametersOther() { - $node = $this->getMock('\OCP\Files\Folder'); - $share = $this->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setSharedBy($this->currentUser->getUID()) - ->setShareType(\OCP\Share::SHARE_TYPE_GROUP) - ->setNode($node); - - $node->expects($this->once()) - ->method('lock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); - - $expected = new \OC_OCS_Result(null, 400, 'Wrong or no update parameter given'); - $result = $this->ocs->updateShare(42); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testUpdateLinkShareClear() { - $ocs = $this->mockFormatShare(); - - $node = $this->getMock('\OCP\Files\Folder'); - $share = $this->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setSharedBy($this->currentUser->getUID()) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPassword('password') - ->setExpirationDate(new \DateTime()) - ->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setNode($node); - - $node->expects($this->once()) - ->method('lock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - $node->expects($this->once()) - ->method('unlock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['publicUpload', null, 'false'], - ['expireDate', null, ''], - ['password', null, ''], - ])); - - $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); - - $this->shareManager->expects($this->once())->method('updateShare')->with( - $this->callback(function (\OCP\Share\IShare $share) { - return $share->getPermissions() === \OCP\Constants::PERMISSION_READ && - $share->getPassword() === null && - $share->getExpirationDate() === null; - }) - )->will($this->returnArgument(0)); - - $expected = new \OC_OCS_Result(null); - $result = $ocs->updateShare(42); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testUpdateLinkShareSet() { - $ocs = $this->mockFormatShare(); - - $folder = $this->getMock('\OCP\Files\Folder'); - - $share = \OC::$server->getShareManager()->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setSharedBy($this->currentUser->getUID()) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setNode($folder); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['publicUpload', null, 'true'], - ['expireDate', null, '2000-01-01'], - ['password', null, 'password'], - ])); - - $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); - $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); - - $this->shareManager->expects($this->once())->method('updateShare')->with( - $this->callback(function (\OCP\Share\IShare $share) { - $date = new \DateTime('2000-01-01'); - $date->setTime(0,0,0); - - return $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE && \OCP\Constants::PERMISSION_DELETE && - $share->getPassword() === 'password' && - $share->getExpirationDate() == $date; - }) - )->will($this->returnArgument(0)); - - $expected = new \OC_OCS_Result(null); - $result = $ocs->updateShare(42); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testUpdateLinkShareInvalidDate() { - $ocs = $this->mockFormatShare(); - - $folder = $this->getMock('\OCP\Files\Folder'); - - $share = \OC::$server->getShareManager()->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setSharedBy($this->currentUser->getUID()) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setNode($folder); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['publicUpload', null, 'true'], - ['expireDate', null, '2000-01-a'], - ['password', null, 'password'], - ])); - - $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); - $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); - - $expected = new \OC_OCS_Result(null, 400, 'Invalid date. Format must be YYYY-MM-DD'); - $result = $ocs->updateShare(42); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testUpdateLinkSharePublicUploadNotAllowed() { - $ocs = $this->mockFormatShare(); - - $folder = $this->getMock('\OCP\Files\Folder'); - - $share = \OC::$server->getShareManager()->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setSharedBy($this->currentUser->getUID()) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setNode($folder); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['publicUpload', null, 'true'], - ['expireDate', '', null], - ['password', '', 'password'], - ])); - - $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); - $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(false); - - $expected = new \OC_OCS_Result(null, 403, 'Public upload disabled by the administrator'); - $result = $ocs->updateShare(42); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testUpdateLinkSharePublicUploadOnFile() { - $ocs = $this->mockFormatShare(); - - $file = $this->getMock('\OCP\Files\File'); - - $share = \OC::$server->getShareManager()->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setSharedBy($this->currentUser->getUID()) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setNode($file); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['publicUpload', null, 'true'], - ['expireDate', '', ''], - ['password', '', 'password'], - ])); - - $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); - $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); - - $expected = new \OC_OCS_Result(null, 400, 'Public upload is only possible for publicly shared folders'); - $result = $ocs->updateShare(42); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testUpdateLinkSharePasswordDoesNotChangeOther() { - $ocs = $this->mockFormatShare(); - - $date = new \DateTime('2000-01-01'); - $date->setTime(0,0,0); - - $node = $this->getMock('\OCP\Files\File'); - $share = $this->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setSharedBy($this->currentUser->getUID()) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPassword('password') - ->setExpirationDate($date) - ->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setNode($node); - - $node->expects($this->once()) - ->method('lock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - $node->expects($this->once()) - ->method('unlock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['password', null, 'newpassword'], - ])); - - $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); - - $this->shareManager->expects($this->once())->method('updateShare')->with( - $this->callback(function (\OCP\Share\IShare $share) use ($date) { - return $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && - $share->getPassword() === 'newpassword' && - $share->getExpirationDate() === $date; - }) - )->will($this->returnArgument(0)); - - $expected = new \OC_OCS_Result(null); - $result = $ocs->updateShare(42); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testUpdateLinkShareExpireDateDoesNotChangeOther() { - $ocs = $this->mockFormatShare(); - - $node = $this->getMock('\OCP\Files\File'); - $share = $this->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setSharedBy($this->currentUser->getUID()) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPassword('password') - ->setExpirationDate(new \DateTime()) - ->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setNode($node); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['expireDate', null, '2010-12-23'], - ])); - - $node->expects($this->once()) - ->method('lock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - $node->expects($this->once()) - ->method('unlock') - ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED); - - $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); - - $this->shareManager->expects($this->once())->method('updateShare')->with( - $this->callback(function (\OCP\Share\IShare $share) { - $date = new \DateTime('2010-12-23'); - $date->setTime(0,0,0); - - return $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && - $share->getPassword() === 'password' && - $share->getExpirationDate() == $date; - }) - )->will($this->returnArgument(0)); - - $expected = new \OC_OCS_Result(null); - $result = $ocs->updateShare(42); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testUpdateLinkSharePublicUploadDoesNotChangeOther() { - $ocs = $this->mockFormatShare(); - - $date = new \DateTime('2000-01-01'); - - $folder = $this->getMock('\OCP\Files\Folder'); - - $share = \OC::$server->getShareManager()->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setSharedBy($this->currentUser->getUID()) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPassword('password') - ->setExpirationDate($date) - ->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setNode($folder); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['publicUpload', null, 'true'], - ])); - - $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); - $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); - - $this->shareManager->expects($this->once())->method('updateShare')->with( - $this->callback(function (\OCP\Share\IShare $share) use ($date) { - return $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE && - $share->getPassword() === 'password' && - $share->getExpirationDate() === $date; - }) - )->will($this->returnArgument(0)); - - $expected = new \OC_OCS_Result(null); - $result = $ocs->updateShare(42); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testUpdateLinkSharePermissions() { - $ocs = $this->mockFormatShare(); - - $date = new \DateTime('2000-01-01'); - - $folder = $this->getMock('\OCP\Files\Folder'); - - $share = \OC::$server->getShareManager()->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setSharedBy($this->currentUser->getUID()) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPassword('password') - ->setExpirationDate($date) - ->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setNode($folder); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['permissions', null, '7'], - ])); - - $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); - $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); - - $this->shareManager->expects($this->once())->method('updateShare')->with( - $this->callback(function (\OCP\Share\IShare $share) use ($date) { - return $share->getPermissions() === \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE && - $share->getPassword() === 'password' && - $share->getExpirationDate() === $date; - }) - )->will($this->returnArgument(0)); - - $this->shareManager->method('getSharedWith')->willReturn([]); - - $expected = new \OC_OCS_Result(null); - $result = $ocs->updateShare(42); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testUpdateLinkShareInvalidPermissions() { - $ocs = $this->mockFormatShare(); - - $date = new \DateTime('2000-01-01'); - - $folder = $this->getMock('\OCP\Files\Folder'); - - $share = \OC::$server->getShareManager()->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setSharedBy($this->currentUser->getUID()) - ->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setPassword('password') - ->setExpirationDate($date) - ->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setNode($folder); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['permissions', null, '31'], - ])); - - $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); - $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); - - $expected = new \OC_OCS_Result(null, 400, 'Can\'t change permissions for public share links'); - $result = $ocs->updateShare(42); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function testUpdateOtherPermissions() { - $ocs = $this->mockFormatShare(); - - $file = $this->getMock('\OCP\Files\File'); - - $share = \OC::$server->getShareManager()->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_ALL) - ->setSharedBy($this->currentUser->getUID()) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setNode($file); - - $this->request - ->method('getParam') - ->will($this->returnValueMap([ - ['permissions', null, '31'], - ])); - - $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); - $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); - - $this->shareManager->expects($this->once())->method('updateShare')->with( - $this->callback(function (\OCP\Share\IShare $share) { - return $share->getPermissions() === \OCP\Constants::PERMISSION_ALL; - }) - )->will($this->returnArgument(0)); - - $this->shareManager->method('getSharedWith')->willReturn([]); - - $expected = new \OC_OCS_Result(null); - $result = $ocs->updateShare(42); - - $this->assertEquals($expected->getMeta(), $result->getMeta()); - $this->assertEquals($expected->getData(), $result->getData()); - } - - public function dataFormatShare() { - $file = $this->getMock('\OCP\Files\File'); - $folder = $this->getMock('\OCP\Files\Folder'); - $parent = $this->getMock('\OCP\Files\Folder'); - - $file->method('getMimeType')->willReturn('myMimeType'); - $folder->method('getMimeType')->willReturn('myFolderMimeType'); - - $file->method('getPath')->willReturn('file'); - $folder->method('getPath')->willReturn('folder'); - - $parent->method('getId')->willReturn(1); - $folder->method('getId')->willReturn(2); - $file->method('getId')->willReturn(3); - - $file->method('getParent')->willReturn($parent); - $folder->method('getParent')->willReturn($parent); - - $cache = $this->getMock('OCP\Files\Cache\ICache'); - $cache->method('getNumericStorageId')->willReturn(100); - $storage = $this->getMock('\OCP\Files\Storage'); - $storage->method('getId')->willReturn('storageId'); - $storage->method('getCache')->willReturn($cache); - - $file->method('getStorage')->willReturn($storage); - $folder->method('getStorage')->willReturn($storage); - - $owner = $this->getMock('\OCP\IUser'); - $owner->method('getDisplayName')->willReturn('ownerDN'); - $initiator = $this->getMock('\OCP\IUser'); - $initiator->method('getDisplayName')->willReturn('initiatorDN'); - $recipient = $this->getMock('\OCP\IUser'); - $recipient->method('getDisplayName')->willReturn('recipientDN'); - - $result = []; - - $share = \OC::$server->getShareManager()->newShare(); - $share->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedWith('recipient') - ->setSharedBy('initiator') - ->setShareOwner('owner') - ->setPermissions(\OCP\Constants::PERMISSION_READ) - ->setNode($file) - ->setShareTime(new \DateTime('2000-01-01T00:01:02')) - ->setTarget('myTarget') - ->setId(42); - - /* User backend down */ - $result[] = [ - [ - 'id' => 42, - 'share_type' => \OCP\Share::SHARE_TYPE_USER, - 'uid_owner' => 'initiator', - 'displayname_owner' => 'initiator', - 'permissions' => 1, - 'stime' => 946684862, - 'parent' => null, - 'expiration' => null, - 'token' => null, - 'uid_file_owner' => 'owner', - 'displayname_file_owner' => 'owner', - 'path' => 'file', - 'item_type' => 'file', - 'storage_id' => 'storageId', - 'storage' => 100, - 'item_source' => 3, - 'file_source' => 3, - 'file_parent' => 1, - 'file_target' => 'myTarget', - 'share_with' => 'recipient', - 'share_with_displayname' => 'recipient', - 'mail_send' => 0, - 'mimetype' => 'myMimeType', - ], $share, [], false - ]; - - /* User backend up */ - $result[] = [ - [ - 'id' => 42, - 'share_type' => \OCP\Share::SHARE_TYPE_USER, - 'uid_owner' => 'initiator', - 'displayname_owner' => 'initiatorDN', - 'permissions' => 1, - 'stime' => 946684862, - 'parent' => null, - 'expiration' => null, - 'token' => null, - 'uid_file_owner' => 'owner', - 'displayname_file_owner' => 'ownerDN', - 'path' => 'file', - 'item_type' => 'file', - 'storage_id' => 'storageId', - 'storage' => 100, - 'item_source' => 3, - 'file_source' => 3, - 'file_parent' => 1, - 'file_target' => 'myTarget', - 'share_with' => 'recipient', - 'share_with_displayname' => 'recipientDN', - 'mail_send' => 0, - 'mimetype' => 'myMimeType', - ], $share, [ - ['owner', $owner], - ['initiator', $initiator], - ['recipient', $recipient], - ], false - ]; - - $share = \OC::$server->getShareManager()->newShare(); - $share->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedWith('recipient') - ->setSharedBy('initiator') - ->setShareOwner('owner') - ->setPermissions(\OCP\Constants::PERMISSION_READ) - ->setNode($file) - ->setShareTime(new \DateTime('2000-01-01T00:01:02')) - ->setTarget('myTarget') - ->setId(42); - - /* User backend down */ - $result[] = [ - [ - 'id' => 42, - 'share_type' => \OCP\Share::SHARE_TYPE_USER, - 'uid_owner' => 'initiator', - 'displayname_owner' => 'initiator', - 'permissions' => 1, - 'stime' => 946684862, - 'parent' => null, - 'expiration' => null, - 'token' => null, - 'uid_file_owner' => 'owner', - 'displayname_file_owner' => 'owner', - 'path' => 'file', - 'item_type' => 'file', - 'storage_id' => 'storageId', - 'storage' => 100, - 'item_source' => 3, - 'file_source' => 3, - 'file_parent' => 1, - 'file_target' => 'myTarget', - 'share_with' => 'recipient', - 'share_with_displayname' => 'recipient', - 'mail_send' => 0, - 'mimetype' => 'myMimeType', - ], $share, [], false - ]; - - $share = \OC::$server->getShareManager()->newShare(); - $share->setShareType(\OCP\Share::SHARE_TYPE_GROUP) - ->setSharedWith('recipient') - ->setSharedBy('initiator') - ->setShareOwner('owner') - ->setPermissions(\OCP\Constants::PERMISSION_READ) - ->setNode($file) - ->setShareTime(new \DateTime('2000-01-01T00:01:02')) - ->setTarget('myTarget') - ->setId(42); - - $result[] = [ - [ - 'id' => 42, - 'share_type' => \OCP\Share::SHARE_TYPE_GROUP, - 'uid_owner' => 'initiator', - 'displayname_owner' => 'initiator', - 'permissions' => 1, - 'stime' => 946684862, - 'parent' => null, - 'expiration' => null, - 'token' => null, - 'uid_file_owner' => 'owner', - 'displayname_file_owner' => 'owner', - 'path' => 'file', - 'item_type' => 'file', - 'storage_id' => 'storageId', - 'storage' => 100, - 'item_source' => 3, - 'file_source' => 3, - 'file_parent' => 1, - 'file_target' => 'myTarget', - 'share_with' => 'recipient', - 'share_with_displayname' => 'recipient', - 'mail_send' => 0, - 'mimetype' => 'myMimeType', - ], $share, [], false - ]; - - $share = \OC::$server->getShareManager()->newShare(); - $share->setShareType(\OCP\Share::SHARE_TYPE_LINK) - ->setSharedBy('initiator') - ->setShareOwner('owner') - ->setPermissions(\OCP\Constants::PERMISSION_READ) - ->setNode($file) - ->setShareTime(new \DateTime('2000-01-01T00:01:02')) - ->setTarget('myTarget') - ->setPassword('mypassword') - ->setExpirationDate(new \DateTime('2001-01-02T00:00:00')) - ->setToken('myToken') - ->setId(42); - - $result[] = [ - [ - 'id' => 42, - 'share_type' => \OCP\Share::SHARE_TYPE_LINK, - 'uid_owner' => 'initiator', - 'displayname_owner' => 'initiator', - 'permissions' => 1, - 'stime' => 946684862, - 'parent' => null, - 'expiration' => '2001-01-02 00:00:00', - 'token' => 'myToken', - 'uid_file_owner' => 'owner', - 'displayname_file_owner' => 'owner', - 'path' => 'file', - 'item_type' => 'file', - 'storage_id' => 'storageId', - 'storage' => 100, - 'item_source' => 3, - 'file_source' => 3, - 'file_parent' => 1, - 'file_target' => 'myTarget', - 'share_with' => 'mypassword', - 'share_with_displayname' => 'mypassword', - 'mail_send' => 0, - 'url' => 'myLink', - 'mimetype' => 'myMimeType', - ], $share, [], false - ]; - - $share = \OC::$server->getShareManager()->newShare(); - $share->setShareType(\OCP\Share::SHARE_TYPE_REMOTE) - ->setSharedBy('initiator') - ->setSharedWith('user@server.com') - ->setShareOwner('owner') - ->setPermissions(\OCP\Constants::PERMISSION_READ) - ->setNode($folder) - ->setShareTime(new \DateTime('2000-01-01T00:01:02')) - ->setTarget('myTarget') - ->setId(42); - - $result[] = [ - [ - 'id' => 42, - 'share_type' => \OCP\Share::SHARE_TYPE_REMOTE, - 'uid_owner' => 'initiator', - 'displayname_owner' => 'initiator', - 'permissions' => 1, - 'stime' => 946684862, - 'parent' => null, - 'expiration' => null, - 'token' => null, - 'uid_file_owner' => 'owner', - 'displayname_file_owner' => 'owner', - 'path' => 'folder', - 'item_type' => 'folder', - 'storage_id' => 'storageId', - 'storage' => 100, - 'item_source' => 2, - 'file_source' => 2, - 'file_parent' => 1, - 'file_target' => 'myTarget', - 'share_with' => 'user@server.com', - 'share_with_displayname' => 'user@server.com', - 'mail_send' => 0, - 'mimetype' => 'myFolderMimeType', - ], $share, [], false - ]; - - $share = \OC::$server->getShareManager()->newShare(); - $share->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedBy('initiator') - ->setSharedWith('recipient') - ->setShareOwner('owner') - ->setPermissions(\OCP\Constants::PERMISSION_READ) - ->setShareTime(new \DateTime('2000-01-01T00:01:02')) - ->setTarget('myTarget') - ->setId(42); - - $result[] = [ - [], $share, [], true - ]; - - - - return $result; - } - - /** - * @dataProvider dataFormatShare - * - * @param array $expects - * @param \OCP\Share\IShare $share - * @param array $users - * @param $exception - */ - public function testFormatShare(array $expects, \OCP\Share\IShare $share, array $users, $exception) { - $this->userManager->method('get')->will($this->returnValueMap($users)); - $this->urlGenerator->method('linkToRouteAbsolute') - ->with('files_sharing.sharecontroller.showShare', ['token' => 'myToken']) - ->willReturn('myLink'); - - - $this->rootFolder->method('getUserFolder')->with($share->getShareOwner())->will($this->returnSelf()); - $this->rootFolder->method('getRelativePath')->will($this->returnArgument(0)); - - try { - $result = $this->invokePrivate($this->ocs, 'formatShare', [$share]); - $this->assertFalse($exception); - $this->assertEquals($expects, $result); - } catch (NotFoundException $e) { - $this->assertTrue($exception); - } - } - - /** - * @return Share20OCS - */ - public function getOcsDisabledAPI() { - $shareManager = $this->getMockBuilder('OCP\Share\IManager') - ->disableOriginalConstructor() - ->getMock(); - $shareManager - ->expects($this->any()) - ->method('shareApiEnabled') - ->willReturn(false); - - return new Share20OCS( - $shareManager, - $this->groupManager, - $this->userManager, - $this->request, - $this->rootFolder, - $this->urlGenerator, - $this->currentUser, - $this->l - ); - } - - public function testGetShareApiDisabled() { - $ocs = $this->getOcsDisabledAPI(); - - $expected = new \OC_OCS_Result(null, 404, 'Share API is disabled'); - $result = $ocs->getShare('my:id'); - - $this->assertEquals($expected, $result); - } - - public function testDeleteShareApiDisabled() { - $ocs = $this->getOcsDisabledAPI(); - - $expected = new \OC_OCS_Result(null, 404, 'Share API is disabled'); - $result = $ocs->deleteShare('my:id'); - - $this->assertEquals($expected, $result); - } - - - public function testCreateShareApiDisabled() { - $ocs = $this->getOcsDisabledAPI(); - - $expected = new \OC_OCS_Result(null, 404, 'Share API is disabled'); - $result = $ocs->createShare(); - - $this->assertEquals($expected, $result); - } - - public function testGetSharesApiDisabled() { - $ocs = $this->getOcsDisabledAPI(); - - $expected = new \OC_OCS_Result(); - $result = $ocs->getShares(); - - $this->assertEquals($expected, $result); - } - - public function testUpdateShareApiDisabled() { - $ocs = $this->getOcsDisabledAPI(); - - $expected = new \OC_OCS_Result(null, 404, 'Share API is disabled'); - $result = $ocs->updateShare('my:id'); - - $this->assertEquals($expected, $result); - } -} diff --git a/apps/files_sharing/tests/api/shareestest.php b/apps/files_sharing/tests/api/shareestest.php deleted file mode 100644 index cda41f55183..00000000000 --- a/apps/files_sharing/tests/api/shareestest.php +++ /dev/null @@ -1,1553 +0,0 @@ - - * @author Joas Schilling - * @author Roeland Jago Douma - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\Tests\API; - -use OCA\Files_Sharing\API\Sharees; -use OCA\Files_sharing\Tests\TestCase; -use OCP\AppFramework\Http; -use OCP\Share; - -/** - * Class ShareesTest - * - * @group DB - * - * @package OCA\Files_Sharing\Tests\API - */ -class ShareesTest extends TestCase { - /** @var Sharees */ - 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 */ - protected $request; - - /** @var \OCP\Share\IManager|\PHPUnit_Framework_MockObject_MockObject */ - protected $shareManager; - - protected function setUp() { - parent::setUp(); - - $this->userManager = $this->getMockBuilder('OCP\IUserManager') - ->disableOriginalConstructor() - ->getMock(); - - $this->groupManager = $this->getMockBuilder('OCP\IGroupManager') - ->disableOriginalConstructor() - ->getMock(); - - $this->contactsManager = $this->getMockBuilder('OCP\Contacts\IManager') - ->disableOriginalConstructor() - ->getMock(); - - $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->sharees = new Sharees( - $this->groupManager, - $this->userManager, - $this->contactsManager, - $this->getMockBuilder('OCP\IConfig')->disableOriginalConstructor()->getMock(), - $this->session, - $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(), - $this->request, - $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(), - $this->shareManager - ); - } - - /** - * @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) { - $group = $this->getMockBuilder('OCP\IGroup') - ->disableOriginalConstructor() - ->getMock(); - - $group->expects($this->any()) - ->method('getGID') - ->willReturn($gid); - - 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], - [ - 'test', false, true, - [$this->getGroupMock('test1')], - [], - [], - [['label' => 'test1', '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')); - } - - public function dataGetRemote() { - return [ - ['test', [], true, [], [], true], - ['test', [], false, [], [], true], - [ - 'test@remote', - [], - true, - [ - ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']], - ], - [], - true, - ], - [ - 'test@remote', - [], - false, - [ - ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']], - ], - [], - true, - ], - [ - 'test', - [ - [ - 'FN' => 'User3 @ Localhost', - ], - [ - 'FN' => 'User2 @ Localhost', - 'CLOUD' => [ - ], - ], - [ - 'FN' => 'User @ Localhost', - 'CLOUD' => [ - 'username@localhost', - ], - ], - ], - true, - [], - [ - ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']], - ], - true, - ], - [ - 'test', - [ - [ - 'FN' => 'User3 @ Localhost', - ], - [ - 'FN' => 'User2 @ Localhost', - 'CLOUD' => [ - ], - ], - [ - 'FN' => 'User @ Localhost', - 'CLOUD' => [ - 'username@localhost', - ], - ], - ], - false, - [], - [], - true, - ], - [ - 'test@remote', - [ - [ - 'FN' => 'User3 @ Localhost', - ], - [ - 'FN' => 'User2 @ Localhost', - 'CLOUD' => [ - ], - ], - [ - 'FN' => 'User @ Localhost', - 'CLOUD' => [ - 'username@localhost', - ], - ], - ], - true, - [ - ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']], - ], - [ - ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']], - ], - true, - ], - [ - 'test@remote', - [ - [ - 'FN' => 'User3 @ Localhost', - ], - [ - 'FN' => 'User2 @ Localhost', - 'CLOUD' => [ - ], - ], - [ - 'FN' => 'User @ Localhost', - 'CLOUD' => [ - 'username@localhost', - ], - ], - ], - false, - [ - ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']], - ], - [], - true, - ], - [ - 'username@localhost', - [ - [ - 'FN' => 'User3 @ Localhost', - ], - [ - 'FN' => 'User2 @ Localhost', - 'CLOUD' => [ - ], - ], - [ - 'FN' => 'User @ Localhost', - 'CLOUD' => [ - 'username@localhost', - ], - ], - ], - true, - [ - ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']], - ], - [], - true, - ], - [ - 'username@localhost', - [ - [ - 'FN' => 'User3 @ Localhost', - ], - [ - 'FN' => 'User2 @ Localhost', - 'CLOUD' => [ - ], - ], - [ - 'FN' => 'User @ Localhost', - 'CLOUD' => [ - 'username@localhost', - ], - ], - ], - false, - [ - ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost', 'server' => 'localhost']], - ], - [], - true, - ], - ]; - } - - /** - * @dataProvider dataGetRemote - * - * @param string $searchTerm - * @param array $contacts - * @param bool $shareeEnumeration - * @param array $exactExpected - * @param array $expected - * @param bool $reachedEnd - */ - public function testGetRemote($searchTerm, $contacts, $shareeEnumeration, $exactExpected, $expected, $reachedEnd) { - $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]); - $this->contactsManager->expects($this->any()) - ->method('search') - ->with($searchTerm, ['CLOUD', 'FN']) - ->willReturn($contacts); - - $this->invokePrivate($this->sharees, 'getRemote', [$searchTerm]); - $result = $this->invokePrivate($this->sharees, 'result'); - - $this->assertEquals($exactExpected, $result['exact']['remotes']); - $this->assertEquals($expected, $result['remotes']); - $this->assertCount((int) $reachedEnd, $this->invokePrivate($this->sharees, 'reachedEndFor')); - } - - public function dataSearch() { - $allTypes = [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE]; - - return [ - [[], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], - - // Test itemType - [[ - 'search' => '', - ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], - [[ - 'search' => 'foobar', - ], '', 'yes', true, 'foobar', null, $allTypes, 1, 200, false, true, true], - [[ - 'search' => 0, - ], '', 'yes', true, '0', null, $allTypes, 1, 200, false, true, true], - - // Test itemType - [[ - 'itemType' => '', - ], '', 'yes', true, '', '', $allTypes, 1, 200, false, true, true], - [[ - 'itemType' => 'folder', - ], '', 'yes', true, '', 'folder', $allTypes, 1, 200, false, true, true], - [[ - 'itemType' => 0, - ], '', 'yes', true, '', '0', $allTypes, 1, 200, false, true, true], - - // Test shareType - [[ - ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], - [[ - 'shareType' => 0, - ], '', 'yes', true, '', null, [0], 1, 200, false, true, true], - [[ - 'shareType' => '0', - ], '', 'yes', true, '', null, [0], 1, 200, false, true, true], - [[ - 'shareType' => 1, - ], '', 'yes', true, '', null, [1], 1, 200, false, true, true], - [[ - 'shareType' => 12, - ], '', 'yes', true, '', null, [], 1, 200, false, true, true], - [[ - 'shareType' => 'foobar', - ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], - [[ - 'shareType' => [0, 1, 2], - ], '', 'yes', true, '', null, [0, 1], 1, 200, false, true, true], - [[ - 'shareType' => [0, 1], - ], '', 'yes', true, '', null, [0, 1], 1, 200, false, true, true], - [[ - 'shareType' => $allTypes, - ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], - [[ - 'shareType' => $allTypes, - ], '', 'yes', false, '', null, [0, 1], 1, 200, false, true, true], - [[ - 'shareType' => $allTypes, - ], '', 'yes', true, '', null, [0, 6], 1, 200, false, true, false], - [[ - 'shareType' => $allTypes, - ], '', 'yes', false, '', null, [0], 1, 200, false, true, false], - - // Test pagination - [[ - 'page' => 1, - ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], - [[ - 'page' => 10, - ], '', 'yes', true, '', null, $allTypes, 10, 200, false, true, true], - - // Test perPage - [[ - 'perPage' => 1, - ], '', 'yes', true, '', null, $allTypes, 1, 1, false, true, true], - [[ - 'perPage' => 10, - ], '', 'yes', true, '', null, $allTypes, 1, 10, false, true, true], - - // Test $shareWithGroupOnly setting - [[], 'no', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], - [[], 'yes', 'yes', true, '', null, $allTypes, 1, 200, true, true, true], - - // Test $shareeEnumeration setting - [[], 'no', 'yes', true, '', null, $allTypes, 1, 200, false, true, true], - [[], 'no', 'no', true, '', null, $allTypes, 1, 200, false, false, true], - - // Test keep case for search - [[ - 'search' => 'foo@example.com/ownCloud', - ], '', 'yes', true, 'foo@example.com/ownCloud', null, $allTypes, 1, 200, false, true, true], - ]; - } - - /** - * @dataProvider dataSearch - * - * @param array $getData - * @param string $apiSetting - * @param string $enumSetting - * @param bool $remoteSharingEnabled - * @param string $search - * @param string $itemType - * @param array $shareTypes - * @param int $page - * @param int $perPage - * @param bool $shareWithGroupOnly - * @param bool $shareeEnumeration - * @param bool $allowGroupSharing - */ - public function testSearch($getData, $apiSetting, $enumSetting, $remoteSharingEnabled, $search, $itemType, $shareTypes, $page, $perPage, $shareWithGroupOnly, $shareeEnumeration, $allowGroupSharing) { - $oldGet = $_GET; - $_GET = $getData; - - $config = $this->getMockBuilder('OCP\IConfig') - ->disableOriginalConstructor() - ->getMock(); - $config->expects($this->exactly(2)) - ->method('getAppValue') - ->with('core', $this->anything(), $this->anything()) - ->willReturnMap([ - ['core', 'shareapi_only_share_with_group_members', 'no', $apiSetting], - ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', $enumSetting], - ]); - - $this->shareManager->expects($this->once()) - ->method('allowGroupSharing') - ->willReturn($allowGroupSharing); - - $sharees = $this->getMockBuilder('\OCA\Files_Sharing\API\Sharees') - ->setConstructorArgs([ - $this->groupManager, - $this->userManager, - $this->contactsManager, - $config, - $this->session, - $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(), - $this->getMockBuilder('OCP\IRequest')->disableOriginalConstructor()->getMock(), - $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(), - $this->shareManager - ]) - ->setMethods(array('searchSharees', 'isRemoteSharingAllowed')) - ->getMock(); - $sharees->expects($this->once()) - ->method('searchSharees') - ->with($search, $itemType, $shareTypes, $page, $perPage) - ->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($shareTypes, $ishareTypes); - $this->assertSame($page, $ipage); - $this->assertSame($perPage, $iperPage); - return new \OC_OCS_Result([]); - }); - $sharees->expects($this->any()) - ->method('isRemoteSharingAllowed') - ->with($itemType) - ->willReturn($remoteSharingEnabled); - - /** @var \PHPUnit_Framework_MockObject_MockObject|\OCA\Files_Sharing\API\Sharees $sharees */ - $this->assertInstanceOf('\OC_OCS_Result', $sharees->search()); - - $this->assertSame($shareWithGroupOnly, $this->invokePrivate($sharees, 'shareWithGroupOnly')); - $this->assertSame($shareeEnumeration, $this->invokePrivate($sharees, 'shareeEnumeration')); - - $_GET = $oldGet; - } - - public function dataSearchInvalid() { - return [ - // Test invalid pagination - [[ - 'page' => 0, - ], 'Invalid page'], - [[ - 'page' => '0', - ], 'Invalid page'], - [[ - 'page' => -1, - ], 'Invalid page'], - - // Test invalid perPage - [[ - 'perPage' => 0, - ], 'Invalid perPage argument'], - [[ - 'perPage' => '0', - ], 'Invalid perPage argument'], - [[ - 'perPage' => -1, - ], 'Invalid perPage argument'], - ]; - } - - /** - * @dataProvider dataSearchInvalid - * - * @param array $getData - * @param string $message - */ - public function testSearchInvalid($getData, $message) { - $oldGet = $_GET; - $_GET = $getData; - - $config = $this->getMockBuilder('OCP\IConfig') - ->disableOriginalConstructor() - ->getMock(); - $config->expects($this->never()) - ->method('getAppValue'); - - $sharees = $this->getMockBuilder('\OCA\Files_Sharing\API\Sharees') - ->setConstructorArgs([ - $this->groupManager, - $this->userManager, - $this->contactsManager, - $config, - $this->session, - $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(), - $this->getMockBuilder('OCP\IRequest')->disableOriginalConstructor()->getMock(), - $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(), - $this->shareManager - ]) - ->setMethods(array('searchSharees', 'isRemoteSharingAllowed')) - ->getMock(); - $sharees->expects($this->never()) - ->method('searchSharees'); - $sharees->expects($this->never()) - ->method('isRemoteSharingAllowed'); - - /** @var \PHPUnit_Framework_MockObject_MockObject|\OCA\Files_Sharing\API\Sharees $sharees */ - $ocs = $sharees->search(); - $this->assertInstanceOf('\OC_OCS_Result', $ocs); - - $this->assertOCSError($ocs, $message); - - $_GET = $oldGet; - } - - public function dataIsRemoteSharingAllowed() { - return [ - ['file', true], - ['folder', true], - ['', false], - ['contacts', false], - ]; - } - - /** - * @dataProvider dataIsRemoteSharingAllowed - * - * @param string $itemType - * @param bool $expected - */ - public function testIsRemoteSharingAllowed($itemType, $expected) { - $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, [], [], [], - [ - 'exact' => ['users' => [], 'groups' => [], 'remotes' => []], - 'users' => [], - 'groups' => [], - 'remotes' => [], - ], false], - ['test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE], 1, 2, false, [], [], [], - [ - 'exact' => ['users' => [], 'groups' => [], 'remotes' => []], - 'users' => [], - 'groups' => [], - 'remotes' => [], - ], 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']], - ], [ - ['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']], - ], - [ - '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', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_REMOTE], 1, 2, false, [ - ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']], - ], null, [ - ['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']], - ], - [ - 'exact' => ['users' => [], 'groups' => [], 'remotes' => []], - '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']], - ], - ], 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' => []], - 'users' => [ - ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']], - ], - 'groups' => [], - 'remotes' => [], - ], 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' => []], - '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' => [], - ], 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\API\Sharees $sharees */ - $sharees = $this->getMockBuilder('\OCA\Files_Sharing\API\Sharees') - ->setConstructorArgs([ - $this->groupManager, - $this->userManager, - $this->contactsManager, - $this->getMockBuilder('OCP\IConfig')->disableOriginalConstructor()->getMock(), - $this->session, - $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(), - $this->getMockBuilder('OCP\IRequest')->disableOriginalConstructor()->getMock(), - $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock(), - $this->shareManager - ]) - ->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) - ->willReturnCallback(function() use ($sharees, $mockedRemotesResult) { - $result = $this->invokePrivate($sharees, 'result'); - $result['remotes'] = $mockedRemotesResult; - $this->invokePrivate($sharees, 'result', [$result]); - }); - - /** @var \OC_OCS_Result $ocs */ - $ocs = $this->invokePrivate($sharees, 'searchSharees', [$searchTerm, $itemType, $shareTypes, $page, $perPage, $shareWithGroupOnly]); - $this->assertInstanceOf('\OC_OCS_Result', $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']); - } - } - - public function testSearchShareesNoItemType() { - /** @var \OC_OCS_Result $ocs */ - $ocs = $this->invokePrivate($this->sharees, 'searchSharees', ['', null, [], [], 0, 0, false]); - $this->assertInstanceOf('\OC_OCS_Result', $ocs); - - $this->assertOCSError($ocs, 'Missing itemType'); - } - - public function dataGetPaginationLink() { - return [ - [1, '/ocs/v1.php', ['perPage' => 2], '; rel="next"'], - [10, '/ocs/v2.php', ['perPage' => 2], '; rel="next"'], - ]; - } - - /** - * @dataProvider dataGetPaginationLink - * - * @param int $page - * @param string $scriptName - * @param array $params - * @param array $expected - */ - public function testGetPaginationLink($page, $scriptName, $params, $expected) { - $this->request->expects($this->once()) - ->method('getScriptName') - ->willReturn($scriptName); - - $this->assertEquals($expected, $this->invokePrivate($this->sharees, 'getPaginationLink', [$page, $params])); - } - - public function dataIsV2() { - return [ - ['/ocs/v1.php', false], - ['/ocs/v2.php', true], - ]; - } - - /** - * @dataProvider dataIsV2 - * - * @param string $scriptName - * @param bool $expected - */ - public function testIsV2($scriptName, $expected) { - $this->request->expects($this->once()) - ->method('getScriptName') - ->willReturn($scriptName); - - $this->assertEquals($expected, $this->invokePrivate($this->sharees, 'isV2')); - } - - /** - * @param \OC_OCS_Result $ocs - * @param string $message - */ - protected function assertOCSError(\OC_OCS_Result $ocs, $message) { - $this->assertSame(Http::STATUS_BAD_REQUEST, $ocs->getStatusCode(), 'Expected status code 400'); - $this->assertSame([], $ocs->getData(), 'Expected that no data is send'); - - $meta = $ocs->getMeta(); - $this->assertNotEmpty($meta); - $this->assertArrayHasKey('message', $meta); - $this->assertSame($message, $meta['message']); - } - - /** - * @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/apps/files_sharing/tests/backend.php b/apps/files_sharing/tests/backend.php deleted file mode 100644 index e5e6ceb6315..00000000000 --- a/apps/files_sharing/tests/backend.php +++ /dev/null @@ -1,111 +0,0 @@ - - * @author Joas Schilling - * @author Morris Jobke - * @author Robin Appelman - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -use OCA\Files\Share; -use OCA\Files_sharing\Tests\TestCase; - -/** - * Class Test_Files_Sharing - * - * @group DB - */ -class Test_Files_Sharing_Backend extends TestCase { - - const TEST_FOLDER_NAME = '/folder_share_api_test'; - - public $folder; - public $subfolder; - public $subsubfolder; - - protected function setUp() { - parent::setUp(); - - $this->folder = self::TEST_FOLDER_NAME; - $this->subfolder = '/subfolder_share_backend_test'; - $this->subsubfolder = '/subsubfolder_share_backend_test'; - - $this->filename = '/share-backend-test.txt'; - - // save file with content - $this->view->file_put_contents($this->filename, $this->data); - $this->view->mkdir($this->folder); - $this->view->mkdir($this->folder . $this->subfolder); - $this->view->mkdir($this->folder . $this->subfolder . $this->subsubfolder); - $this->view->file_put_contents($this->folder.$this->filename, $this->data); - $this->view->file_put_contents($this->folder . $this->subfolder . $this->filename, $this->data); - $this->view->file_put_contents($this->folder . $this->subfolder . $this->subsubfolder . $this->filename, $this->data); - } - - protected function tearDown() { - if ($this->view) { - $this->view->unlink($this->filename); - $this->view->deleteAll($this->folder); - } - - parent::tearDown(); - } - - function testGetParents() { - - $fileinfo1 = $this->view->getFileInfo($this->folder); - $fileinfo2 = $this->view->getFileInfo($this->folder . $this->subfolder . $this->subsubfolder); - $fileinfo3 = $this->view->getFileInfo($this->folder . $this->subfolder . $this->subsubfolder . $this->filename); - - $this->assertTrue(\OCP\Share::shareItem('folder', $fileinfo1['fileid'], \OCP\Share::SHARE_TYPE_USER, - self::TEST_FILES_SHARING_API_USER2, 31)); - $this->assertTrue(\OCP\Share::shareItem('folder', $fileinfo2['fileid'], \OCP\Share::SHARE_TYPE_USER, - self::TEST_FILES_SHARING_API_USER3, 31)); - - $backend = new \OC_Share_Backend_Folder(); - - $result = $backend->getParents($fileinfo3['fileid']); - $this->assertSame(2, count($result)); - - $count1 = 0; - $count2 = 0; - foreach($result as $r) { - if ($r['path'] === 'files' . $this->folder) { - $this->assertSame(ltrim($this->folder, '/'), $r['collection']['path']); - $count1++; - } elseif ($r['path'] === 'files' . $this->folder . $this->subfolder . $this->subsubfolder) { - $this->assertSame(ltrim($this->subsubfolder, '/'), $r['collection']['path']); - $count2++; - } else { - $this->assertTrue(false, 'unexpected result'); - } - } - - $this->assertSame(1, $count1); - $this->assertSame(1, $count2); - - $result1 = $backend->getParents($fileinfo3['fileid'], self::TEST_FILES_SHARING_API_USER3); - $this->assertSame(1, count($result1)); - $elemet = reset($result1); - $this->assertSame('files' . $this->folder . $this->subfolder . $this->subsubfolder ,$elemet['path']); - $this->assertSame(ltrim($this->subsubfolder, '/') ,$elemet['collection']['path']); - - } - -} diff --git a/apps/files_sharing/tests/cache.php b/apps/files_sharing/tests/cache.php deleted file mode 100644 index dd727c1c6f2..00000000000 --- a/apps/files_sharing/tests/cache.php +++ /dev/null @@ -1,525 +0,0 @@ - - * @author Joas Schilling - * @author Jörn Friedrich Dreyer - * @author Morris Jobke - * @author Robin Appelman - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -use OCA\Files_sharing\Tests\TestCase; - - -/** - * Class Test_Files_Sharing_Cache - * - * @group DB - */ -class Test_Files_Sharing_Cache extends TestCase { - - /** - * @var OC\Files\View - */ - public $user2View; - - /** @var \OC\Files\Cache\Cache */ - protected $ownerCache; - - /** @var \OC\Files\Cache\Cache */ - protected $sharedCache; - - /** @var \OC\Files\Storage\Storage */ - protected $ownerStorage; - - /** @var \OC\Files\Storage\Storage */ - protected $sharedStorage; - - /** @var \OCP\Share\IManager */ - protected $shareManager; - - protected function setUp() { - parent::setUp(); - - $this->shareManager = \OC::$server->getShareManager(); - - \OC_User::setDisplayName(self::TEST_FILES_SHARING_API_USER1, 'User One'); - \OC_User::setDisplayName(self::TEST_FILES_SHARING_API_USER2, 'User Two'); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - - $this->user2View = new \OC\Files\View('/'. self::TEST_FILES_SHARING_API_USER2 . '/files'); - - // prepare user1's dir structure - $this->view->mkdir('container'); - $this->view->mkdir('container/shareddir'); - $this->view->mkdir('container/shareddir/subdir'); - $this->view->mkdir('container/shareddir/emptydir'); - - $textData = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - $this->view->file_put_contents('container/not shared.txt', $textData); - $this->view->file_put_contents('container/shared single file.txt', $textData); - $this->view->file_put_contents('container/shareddir/bar.txt', $textData); - $this->view->file_put_contents('container/shareddir/subdir/another.txt', $textData); - $this->view->file_put_contents('container/shareddir/subdir/another too.txt', $textData); - $this->view->file_put_contents('container/shareddir/subdir/not a text file.xml', ''); - - list($this->ownerStorage,) = $this->view->resolvePath(''); - $this->ownerCache = $this->ownerStorage->getCache(); - $this->ownerStorage->getScanner()->scan(''); - - // share "shareddir" with user2 - $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1); - - $node = $rootFolder->get('container/shareddir'); - $share = $this->shareManager->newShare(); - $share->setNode($node) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); - $this->shareManager->createShare($share); - - $node = $rootFolder->get('container/shared single file.txt'); - $share = $this->shareManager->newShare(); - $share->setNode($node) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setPermissions(\OCP\Constants::PERMISSION_ALL & ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE)); - $this->shareManager->createShare($share); - - // login as user2 - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - - // retrieve the shared storage - $secondView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2); - list($this->sharedStorage,) = $secondView->resolvePath('files/shareddir'); - $this->sharedCache = $this->sharedStorage->getCache(); - } - - protected function tearDown() { - if($this->sharedCache) { - $this->sharedCache->clear(); - } - - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - - $shares = $this->shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER1, \OCP\Share::SHARE_TYPE_USER); - foreach ($shares as $share) { - $this->shareManager->deleteShare($share); - } - - $this->view->deleteAll('container'); - - $this->ownerCache->clear(); - - parent::tearDown(); - } - - function searchDataProvider() { - return array( - array('%another%', - array( - array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'), - array('name' => 'another.txt', 'path' => 'subdir/another.txt'), - ) - ), - array('%Another%', - array( - array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'), - array('name' => 'another.txt', 'path' => 'subdir/another.txt'), - ) - ), - array('%dir%', - array( - array('name' => 'emptydir', 'path' => 'emptydir'), - array('name' => 'subdir', 'path' => 'subdir'), - array('name' => 'shareddir', 'path' => ''), - ) - ), - array('%Dir%', - array( - array('name' => 'emptydir', 'path' => 'emptydir'), - array('name' => 'subdir', 'path' => 'subdir'), - array('name' => 'shareddir', 'path' => ''), - ) - ), - array('%txt%', - array( - array('name' => 'bar.txt', 'path' => 'bar.txt'), - array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'), - array('name' => 'another.txt', 'path' => 'subdir/another.txt'), - ) - ), - array('%Txt%', - array( - array('name' => 'bar.txt', 'path' => 'bar.txt'), - array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'), - array('name' => 'another.txt', 'path' => 'subdir/another.txt'), - ) - ), - array('%', - array( - array('name' => 'bar.txt', 'path' => 'bar.txt'), - array('name' => 'emptydir', 'path' => 'emptydir'), - array('name' => 'subdir', 'path' => 'subdir'), - array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'), - array('name' => 'another.txt', 'path' => 'subdir/another.txt'), - array('name' => 'not a text file.xml', 'path' => 'subdir/not a text file.xml'), - array('name' => 'shareddir', 'path' => ''), - ) - ), - array('%nonexistent%', - array( - ) - ), - ); - } - - /** - * we cannot use a dataProvider because that would cause the stray hook detection to remove the hooks - * that were added in setUpBeforeClass. - */ - function testSearch() { - foreach ($this->searchDataProvider() as $data) { - list($pattern, $expectedFiles) = $data; - - $results = $this->sharedStorage->getCache()->search($pattern); - - $this->verifyFiles($expectedFiles, $results); - } - - } - /** - * Test searching by mime type - */ - function testSearchByMime() { - $results = $this->sharedStorage->getCache()->searchByMime('text'); - $check = array( - array( - 'name' => 'bar.txt', - 'path' => 'bar.txt' - ), - array( - 'name' => 'another too.txt', - 'path' => 'subdir/another too.txt' - ), - array( - 'name' => 'another.txt', - 'path' => 'subdir/another.txt' - ), - ); - $this->verifyFiles($check, $results); - } - - /** - * Test searching by tag - */ - function testSearchByTag() { - $userId = \OC::$server->getUserSession()->getUser()->getUId(); - $id1 = $this->sharedCache->get('bar.txt')['fileid']; - $id2 = $this->sharedCache->get('subdir/another too.txt')['fileid']; - $id3 = $this->sharedCache->get('subdir/not a text file.xml')['fileid']; - $id4 = $this->sharedCache->get('subdir/another.txt')['fileid']; - $tagManager = \OC::$server->getTagManager()->load('files', null, null, $userId); - $tagManager->tagAs($id1, 'tag1'); - $tagManager->tagAs($id1, 'tag2'); - $tagManager->tagAs($id2, 'tag1'); - $tagManager->tagAs($id3, 'tag1'); - $tagManager->tagAs($id4, 'tag2'); - $results = $this->sharedStorage->getCache()->searchByTag('tag1', $userId); - $check = array( - array( - 'name' => 'bar.txt', - 'path' => 'bar.txt' - ), - array( - 'name' => 'another too.txt', - 'path' => 'subdir/another too.txt' - ), - array( - 'name' => 'not a text file.xml', - 'path' => 'subdir/not a text file.xml' - ), - ); - $this->verifyFiles($check, $results); - $tagManager->delete(array('tag1', 'tag2')); - } - - /** - * Test searching by tag for multiple sections of the tree - */ - function testSearchByTagTree() { - $userId = \OC::$server->getUserSession()->getUser()->getUId(); - $this->sharedStorage->mkdir('subdir/emptydir'); - $this->sharedStorage->mkdir('subdir/emptydir2'); - $this->ownerStorage->getScanner()->scan(''); - $allIds = array( - $this->sharedCache->get('')['fileid'], - $this->sharedCache->get('bar.txt')['fileid'], - $this->sharedCache->get('subdir/another too.txt')['fileid'], - $this->sharedCache->get('subdir/not a text file.xml')['fileid'], - $this->sharedCache->get('subdir/another.txt')['fileid'], - $this->sharedCache->get('subdir/emptydir')['fileid'], - $this->sharedCache->get('subdir/emptydir2')['fileid'], - ); - $tagManager = \OC::$server->getTagManager()->load('files', null, null, $userId); - foreach ($allIds as $id) { - $tagManager->tagAs($id, 'tag1'); - } - $results = $this->sharedStorage->getCache()->searchByTag('tag1', $userId); - $check = array( - array( - 'name' => 'shareddir', - 'path' => '' - ), - array( - 'name' => 'bar.txt', - 'path' => 'bar.txt' - ), - array( - 'name' => 'another.txt', - 'path' => 'subdir/another.txt' - ), - array( - 'name' => 'another too.txt', - 'path' => 'subdir/another too.txt' - ), - array( - 'name' => 'emptydir', - 'path' => 'subdir/emptydir' - ), - array( - 'name' => 'emptydir2', - 'path' => 'subdir/emptydir2' - ), - array( - 'name' => 'not a text file.xml', - 'path' => 'subdir/not a text file.xml' - ), - ); - $this->verifyFiles($check, $results); - $tagManager->delete(array('tag1')); - } - - function testGetFolderContentsInRoot() { - $results = $this->user2View->getDirectoryContent('/'); - - // we should get the shared items "shareddir" and "shared single file.txt" - // additional root will always contain the example file "welcome.txt", - // so this will be part of the result - $this->verifyFiles( - array( - array( - 'name' => 'welcome.txt', - 'path' => 'files/welcome.txt', - 'mimetype' => 'text/plain', - ), - array( - 'name' => 'shareddir', - 'path' => 'files/shareddir', - 'mimetype' => 'httpd/unix-directory', - 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, - 'displayname_owner' => 'User One', - ), - array( - 'name' => 'shared single file.txt', - 'path' => 'files/shared single file.txt', - 'mimetype' => 'text/plain', - 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, - 'displayname_owner' => 'User One', - ), - ), - $results - ); - } - - function testGetFolderContentsInSubdir() { - $results = $this->user2View->getDirectoryContent('/shareddir'); - - $this->verifyFiles( - array( - array( - 'name' => 'bar.txt', - 'path' => 'bar.txt', - 'mimetype' => 'text/plain', - 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, - 'displayname_owner' => 'User One', - ), - array( - 'name' => 'emptydir', - 'path' => 'emptydir', - 'mimetype' => 'httpd/unix-directory', - 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, - 'displayname_owner' => 'User One', - ), - array( - 'name' => 'subdir', - 'path' => 'subdir', - 'mimetype' => 'httpd/unix-directory', - 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, - 'displayname_owner' => 'User One', - ), - ), - $results - ); - } - - function testGetFolderContentsWhenSubSubdirShared() { - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - - $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1); - $node = $rootFolder->get('container/shareddir/subdir'); - $share = $this->shareManager->newShare(); - $share->setNode($node) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER3) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); - $share = $this->shareManager->createShare($share); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER3); - - $thirdView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER3 . '/files'); - $results = $thirdView->getDirectoryContent('/subdir'); - - $this->verifyFiles( - array( - array( - 'name' => 'another too.txt', - 'path' => 'another too.txt', - 'mimetype' => 'text/plain', - 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, - 'displayname_owner' => 'User One', - ), - array( - 'name' => 'another.txt', - 'path' => 'another.txt', - 'mimetype' => 'text/plain', - 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, - 'displayname_owner' => 'User One', - ), - array( - 'name' => 'not a text file.xml', - 'path' => 'not a text file.xml', - 'mimetype' => 'application/xml', - 'uid_owner' => self::TEST_FILES_SHARING_API_USER1, - 'displayname_owner' => 'User One', - ), - ), - $results - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - - $this->shareManager->deleteShare($share); - } - - /** - * Check if 'results' contains the expected 'examples' only. - * - * @param array $examples array of example files - * @param array $results array of files - */ - private function verifyFiles($examples, $results) { - $this->assertEquals(count($examples), count($results)); - - foreach ($examples as $example) { - foreach ($results as $key => $result) { - if ($result['name'] === $example['name']) { - $this->verifyKeys($example, $result); - unset($results[$key]); - break; - } - } - } - $this->assertEquals(array(), $results); - } - - /** - * verify if each value from the result matches the expected result - * @param array $example array with the expected results - * @param array $result array with the results - */ - private function verifyKeys($example, $result) { - foreach ($example as $key => $value) { - $this->assertEquals($value, $result[$key]); - } - } - - public function testGetPathByIdDirectShare() { - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - \OC\Files\Filesystem::file_put_contents('test.txt', 'foo'); - $info = \OC\Files\Filesystem::getFileInfo('test.txt'); - - $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1); - $node = $rootFolder->get('test.txt'); - $share = $this->shareManager->newShare(); - $share->setNode($node) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setPermissions(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE); - $this->shareManager->createShare($share); - - \OC_Util::tearDownFS(); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $this->assertTrue(\OC\Files\Filesystem::file_exists('/test.txt')); - list($sharedStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/test.txt'); - /** - * @var \OC\Files\Storage\Shared $sharedStorage - */ - - $sharedCache = $sharedStorage->getCache(); - $this->assertEquals('', $sharedCache->getPathById($info->getId())); - } - - public function testGetPathByIdShareSubFolder() { - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - \OC\Files\Filesystem::mkdir('foo'); - \OC\Files\Filesystem::mkdir('foo/bar'); - \OC\Files\Filesystem::touch('foo/bar/test.txt'); - $folderInfo = \OC\Files\Filesystem::getFileInfo('foo'); - $fileInfo = \OC\Files\Filesystem::getFileInfo('foo/bar/test.txt'); - - $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1); - $node = $rootFolder->get('foo'); - $share = $this->shareManager->newShare(); - $share->setNode($node) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); - $this->shareManager->createShare($share); - \OC_Util::tearDownFS(); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $this->assertTrue(\OC\Files\Filesystem::file_exists('/foo')); - list($sharedStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/foo'); - /** - * @var \OC\Files\Storage\Shared $sharedStorage - */ - - $sharedCache = $sharedStorage->getCache(); - $this->assertEquals('', $sharedCache->getPathById($folderInfo->getId())); - $this->assertEquals('bar/test.txt', $sharedCache->getPathById($fileInfo->getId())); - } -} diff --git a/apps/files_sharing/tests/capabilities.php b/apps/files_sharing/tests/capabilities.php deleted file mode 100644 index 0e17811be03..00000000000 --- a/apps/files_sharing/tests/capabilities.php +++ /dev/null @@ -1,300 +0,0 @@ - - * @author Roeland Jago Douma - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -namespace OCA\Files_Sharing\Tests; - -use OCA\Files_Sharing\Capabilities; -use OCA\Files_Sharing\Tests\TestCase; - -/** - * Class FilesSharingCapabilitiesTest - * - * @group DB - */ -class FilesSharingCapabilitiesTest extends \Test\TestCase { - - /** - * Test for the general part in each return statement and assert. - * Strip of the general part on the way. - * - * @param string[] $data Capabilities - * @return string[] - */ - private function getFilesSharingPart(array $data) { - $this->assertArrayHasKey('files_sharing', $data); - return $data['files_sharing']; - } - - /** - * Create a mock config object and insert the values in $map tot the getAppValue - * function. Then obtain the capabilities and extract the first few - * levels in the array - * - * @param (string[])[] $map Map of arguments to return types for the getAppValue function in the mock - * @return string[] - */ - private function getResults(array $map) { - $stub = $this->getMockBuilder('\OCP\IConfig')->disableOriginalConstructor()->getMock(); - $stub->method('getAppValue')->will($this->returnValueMap($map)); - $cap = new Capabilities($stub); - $result = $this->getFilesSharingPart($cap->getCapabilities()); - return $result; - } - - public function testEnabledSharingAPI() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ]; - $result = $this->getResults($map); - $this->assertTrue($result['api_enabled']); - $this->assertContains('public', $result); - $this->assertContains('user', $result); - $this->assertContains('resharing', $result); - } - - public function testDisabledSharingAPI() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'no'], - ]; - $result = $this->getResults($map); - $this->assertFalse($result['api_enabled']); - $this->assertNotContains('public', $result); - $this->assertNotContains('user', $result); - $this->assertNotContains('resharing', $result); - } - - public function testNoLinkSharing() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_links', 'yes', 'no'], - ]; - $result = $this->getResults($map); - $this->assertInternalType('array', $result['public']); - $this->assertFalse($result['public']['enabled']); - } - - public function testOnlyLinkSharing() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_links', 'yes', 'yes'], - ]; - $result = $this->getResults($map); - $this->assertInternalType('array', $result['public']); - $this->assertTrue($result['public']['enabled']); - } - - public function testLinkPassword() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_links', 'yes', 'yes'], - ['core', 'shareapi_enforce_links_password', 'no', 'yes'], - ]; - $result = $this->getResults($map); - $this->assertArrayHasKey('password', $result['public']); - $this->assertArrayHasKey('enforced', $result['public']['password']); - $this->assertTrue($result['public']['password']['enforced']); - } - - public function testLinkNoPassword() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_links', 'yes', 'yes'], - ['core', 'shareapi_enforce_links_password', 'no', 'no'], - ]; - $result = $this->getResults($map); - $this->assertArrayHasKey('password', $result['public']); - $this->assertArrayHasKey('enforced', $result['public']['password']); - $this->assertFalse($result['public']['password']['enforced']); - } - - public function testLinkNoExpireDate() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_links', 'yes', 'yes'], - ['core', 'shareapi_default_expire_date', 'no', 'no'], - ]; - $result = $this->getResults($map); - $this->assertArrayHasKey('expire_date', $result['public']); - $this->assertInternalType('array', $result['public']['expire_date']); - $this->assertFalse($result['public']['expire_date']['enabled']); - } - - public function testLinkExpireDate() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_links', 'yes', 'yes'], - ['core', 'shareapi_default_expire_date', 'no', 'yes'], - ['core', 'shareapi_expire_after_n_days', '7', '7'], - ['core', 'shareapi_enforce_expire_date', 'no', 'no'], - ]; - $result = $this->getResults($map); - $this->assertArrayHasKey('expire_date', $result['public']); - $this->assertInternalType('array', $result['public']['expire_date']); - $this->assertTrue($result['public']['expire_date']['enabled']); - $this->assertArrayHasKey('days', $result['public']['expire_date']); - $this->assertFalse($result['public']['expire_date']['enforced']); - } - - public function testLinkExpireDateEnforced() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_links', 'yes', 'yes'], - ['core', 'shareapi_default_expire_date', 'no', 'yes'], - ['core', 'shareapi_enforce_expire_date', 'no', 'yes'], - ]; - $result = $this->getResults($map); - $this->assertArrayHasKey('expire_date', $result['public']); - $this->assertInternalType('array', $result['public']['expire_date']); - $this->assertTrue($result['public']['expire_date']['enforced']); - } - - public function testLinkSendMail() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_links', 'yes', 'yes'], - ['core', 'shareapi_allow_public_notification', 'no', 'yes'], - ]; - $result = $this->getResults($map); - $this->assertTrue($result['public']['send_mail']); - } - - public function testLinkNoSendMail() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_links', 'yes', 'yes'], - ['core', 'shareapi_allow_public_notification', 'no', 'no'], - ]; - $result = $this->getResults($map); - $this->assertFalse($result['public']['send_mail']); - } - - public function testUserSendMail() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_mail_notification', 'no', 'yes'], - ]; - $result = $this->getResults($map); - $this->assertTrue($result['user']['send_mail']); - } - - public function testUserNoSendMail() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_mail_notification', 'no', 'no'], - ]; - $result = $this->getResults($map); - $this->assertFalse($result['user']['send_mail']); - } - - public function testResharing() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_resharing', 'yes', 'yes'], - ]; - $result = $this->getResults($map); - $this->assertTrue($result['resharing']); - } - - public function testNoResharing() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_resharing', 'yes', 'no'], - ]; - $result = $this->getResults($map); - $this->assertFalse($result['resharing']); - } - - public function testLinkPublicUpload() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_links', 'yes', 'yes'], - ['core', 'shareapi_allow_public_upload', 'yes', 'yes'], - ]; - $result = $this->getResults($map); - $this->assertTrue($result['public']['upload']); - } - - public function testLinkNoPublicUpload() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_links', 'yes', 'yes'], - ['core', 'shareapi_allow_public_upload', 'yes', 'no'], - ]; - $result = $this->getResults($map); - $this->assertFalse($result['public']['upload']); - } - - public function testNoGroupSharing() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_group_sharing', 'yes', 'no'], - ]; - $result = $this->getResults($map); - $this->assertFalse($result['group_sharing']); - } - - public function testGroupSharing() { - $map = [ - ['core', 'shareapi_enabled', 'yes', 'yes'], - ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'], - ]; - $result = $this->getResults($map); - $this->assertTrue($result['group_sharing']); - } - - public function testFederatedSharingIncomming() { - $map = [ - ['files_sharing', 'incoming_server2server_share_enabled', 'yes', 'yes'], - ]; - $result = $this->getResults($map); - $this->assertArrayHasKey('federation', $result); - $this->assertTrue($result['federation']['incoming']); - } - - public function testFederatedSharingNoIncomming() { - $map = [ - ['files_sharing', 'incoming_server2server_share_enabled', 'yes', 'no'], - ]; - $result = $this->getResults($map); - $this->assertArrayHasKey('federation', $result); - $this->assertFalse($result['federation']['incoming']); - } - - public function testFederatedSharingOutgoing() { - $map = [ - ['files_sharing', 'outgoing_server2server_share_enabled', 'yes', 'yes'], - ]; - $result = $this->getResults($map); - $this->assertArrayHasKey('federation', $result); - $this->assertTrue($result['federation']['outgoing']); - } - - public function testFederatedSharingNoOutgoing() { - $map = [ - ['files_sharing', 'outgoing_server2server_share_enabled', 'yes', 'no'], - ]; - $result = $this->getResults($map); - $this->assertArrayHasKey('federation', $result); - $this->assertFalse($result['federation']['outgoing']); - } - -} diff --git a/apps/files_sharing/tests/controller/externalsharecontroller.php b/apps/files_sharing/tests/controller/externalsharecontroller.php deleted file mode 100644 index bd20bffb36c..00000000000 --- a/apps/files_sharing/tests/controller/externalsharecontroller.php +++ /dev/null @@ -1,152 +0,0 @@ - - * @author Roeland Jago Douma - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\Controllers; - -use OCP\AppFramework\Http\DataResponse; -use OCP\AppFramework\Http\JSONResponse; -use OCP\Http\Client\IClientService; -use OCP\IRequest; - -/** - * Class ExternalShareControllerTest - * - * @package OCA\Files_Sharing\Controllers - */ -class ExternalShareControllerTest extends \Test\TestCase { - /** @var IRequest */ - private $request; - /** @var \OCA\Files_Sharing\External\Manager */ - private $externalManager; - /** @var IClientService */ - private $clientService; - - public function setUp() { - $this->request = $this->getMockBuilder('\\OCP\\IRequest') - ->disableOriginalConstructor()->getMock(); - $this->externalManager = $this->getMockBuilder('\\OCA\\Files_Sharing\\External\\Manager') - ->disableOriginalConstructor()->getMock(); - $this->clientService = $this->getMockBuilder('\\OCP\Http\\Client\\IClientService') - ->disableOriginalConstructor()->getMock(); - } - - /** - * @return ExternalSharesController - */ - public function getExternalShareController() { - return new ExternalSharesController( - 'files_sharing', - $this->request, - $this->externalManager, - $this->clientService - ); - } - - public function testIndex() { - $this->externalManager - ->expects($this->once()) - ->method('getOpenShares') - ->will($this->returnValue(['MyDummyArray'])); - - $this->assertEquals(new JSONResponse(['MyDummyArray']), $this->getExternalShareController()->index()); - } - - public function testCreate() { - $this->externalManager - ->expects($this->once()) - ->method('acceptShare') - ->with(4); - - $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->create(4)); - } - - public function testDestroy() { - $this->externalManager - ->expects($this->once()) - ->method('declineShare') - ->with(4); - - $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->destroy(4)); - } - - public function testRemoteWithValidHttps() { - $client = $this->getMockBuilder('\\OCP\\Http\\Client\\IClient') - ->disableOriginalConstructor()->getMock(); - $response = $this->getMockBuilder('\\OCP\\Http\\Client\\IResponse') - ->disableOriginalConstructor()->getMock(); - $response - ->expects($this->exactly(2)) - ->method('getBody') - ->will($this->onConsecutiveCalls('Certainly not a JSON string', '{"installed":true,"maintenance":false,"version":"8.1.0.8","versionstring":"8.1.0","edition":""}')); - $client - ->expects($this->any()) - ->method('get') - ->will($this->returnValue($response)); - - $this->clientService - ->expects($this->exactly(2)) - ->method('newClient') - ->will($this->returnValue($client)); - - $this->assertEquals(new DataResponse('https'), $this->getExternalShareController()->testRemote('owncloud.org')); - } - - public function testRemoteWithWorkingHttp() { - $client = $this->getMockBuilder('\\OCP\\Http\\Client\\IClient') - ->disableOriginalConstructor()->getMock(); - $response = $this->getMockBuilder('\\OCP\\Http\\Client\\IResponse') - ->disableOriginalConstructor()->getMock(); - $client - ->method('get') - ->will($this->returnValue($response)); - $response - ->expects($this->exactly(5)) - ->method('getBody') - ->will($this->onConsecutiveCalls('Certainly not a JSON string', 'Certainly not a JSON string', 'Certainly not a JSON string', 'Certainly not a JSON string', '{"installed":true,"maintenance":false,"version":"8.1.0.8","versionstring":"8.1.0","edition":""}')); - $this->clientService - ->expects($this->exactly(5)) - ->method('newClient') - ->will($this->returnValue($client)); - - $this->assertEquals(new DataResponse('http'), $this->getExternalShareController()->testRemote('owncloud.org')); - } - - public function testRemoteWithInvalidRemote() { - $client = $this->getMockBuilder('\\OCP\\Http\\Client\\IClient') - ->disableOriginalConstructor()->getMock(); - $response = $this->getMockBuilder('\\OCP\\Http\\Client\\IResponse') - ->disableOriginalConstructor()->getMock(); - $client - ->method('get') - ->will($this->returnValue($response)); - $response - ->expects($this->exactly(6)) - ->method('getBody') - ->will($this->returnValue('Certainly not a JSON string')); - $this->clientService - ->expects($this->exactly(6)) - ->method('newClient') - ->will($this->returnValue($client)); - - $this->assertEquals(new DataResponse(false), $this->getExternalShareController()->testRemote('owncloud.org')); - } -} diff --git a/apps/files_sharing/tests/controller/sharecontroller.php b/apps/files_sharing/tests/controller/sharecontroller.php deleted file mode 100644 index f38ae10ca12..00000000000 --- a/apps/files_sharing/tests/controller/sharecontroller.php +++ /dev/null @@ -1,451 +0,0 @@ - - * @author Joas Schilling - * @author Lukas Reschke - * @author Morris Jobke - * @author Robin Appelman - * @author Roeland Jago Douma - * @author Thomas Müller - * @author Vincent Cloutier - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\Controllers; - -use OC\Files\Filesystem; -use OCA\FederatedFileSharing\FederatedShareProvider; -use OCP\Share\Exceptions\ShareNotFound; -use OCP\AppFramework\Http\NotFoundResponse; -use OCP\AppFramework\Http\RedirectResponse; -use OCP\AppFramework\Http\TemplateResponse; -use OCP\ISession; -use OCP\IUserManager; -use OCP\Security\ISecureRandom; -use OCP\IURLGenerator; - -/** - * @group DB - * - * @package OCA\Files_Sharing\Controllers - */ -class ShareControllerTest extends \Test\TestCase { - - /** @var string */ - private $user; - /** @var string */ - private $oldUser; - - /** @var string */ - private $appName = 'files_sharing'; - /** @var ShareController */ - private $shareController; - /** @var IURLGenerator | \PHPUnit_Framework_MockObject_MockObject */ - private $urlGenerator; - /** @var ISession | \PHPUnit_Framework_MockObject_MockObject */ - private $session; - /** @var \OCP\IPreview | \PHPUnit_Framework_MockObject_MockObject */ - private $previewManager; - /** @var \OCP\IConfig | \PHPUnit_Framework_MockObject_MockObject */ - private $config; - /** @var \OC\Share20\Manager | \PHPUnit_Framework_MockObject_MockObject */ - private $shareManager; - /** @var IUserManager | \PHPUnit_Framework_MockObject_MockObject */ - private $userManager; - /** @var FederatedShareProvider | \PHPUnit_Framework_MockObject_MockObject */ - private $federatedShareProvider; - - protected function setUp() { - $this->appName = 'files_sharing'; - - $this->shareManager = $this->getMockBuilder('\OC\Share20\Manager')->disableOriginalConstructor()->getMock(); - $this->urlGenerator = $this->getMock('\OCP\IURLGenerator'); - $this->session = $this->getMock('\OCP\ISession'); - $this->previewManager = $this->getMock('\OCP\IPreview'); - $this->config = $this->getMock('\OCP\IConfig'); - $this->userManager = $this->getMock('\OCP\IUserManager'); - $this->federatedShareProvider = $this->getMockBuilder('OCA\FederatedFileSharing\FederatedShareProvider') - ->disableOriginalConstructor()->getMock(); - $this->federatedShareProvider->expects($this->any()) - ->method('isOutgoingServer2serverShareEnabled')->willReturn(true); - $this->federatedShareProvider->expects($this->any()) - ->method('isIncomingServer2serverShareEnabled')->willReturn(true); - - $this->shareController = new \OCA\Files_Sharing\Controllers\ShareController( - $this->appName, - $this->getMock('\OCP\IRequest'), - $this->config, - $this->urlGenerator, - $this->userManager, - $this->getMock('\OCP\ILogger'), - $this->getMock('\OCP\Activity\IManager'), - $this->shareManager, - $this->session, - $this->previewManager, - $this->getMock('\OCP\Files\IRootFolder'), - $this->federatedShareProvider - ); - - - // Store current user - $this->oldUser = \OC_User::getUser(); - - // Create a dummy user - $this->user = \OC::$server->getSecureRandom()->generate(12, ISecureRandom::CHAR_LOWER); - - \OC::$server->getUserManager()->createUser($this->user, $this->user); - \OC_Util::tearDownFS(); - $this->loginAsUser($this->user); - } - - protected function tearDown() { - \OC_Util::tearDownFS(); - \OC_User::setUserId(''); - Filesystem::tearDown(); - $user = \OC::$server->getUserManager()->get($this->user); - if ($user !== null) { $user->delete(); } - \OC_User::setIncognitoMode(false); - - \OC::$server->getSession()->set('public_link_authenticated', ''); - - // Set old user - \OC_User::setUserId($this->oldUser); - \OC_Util::setupFS($this->oldUser); - } - - public function testShowAuthenticateNotAuthenticated() { - $share = \OC::$server->getShareManager()->newShare(); - - $this->shareManager - ->expects($this->once()) - ->method('getShareByToken') - ->with('token') - ->willReturn($share); - - $response = $this->shareController->showAuthenticate('token'); - $expectedResponse = new TemplateResponse($this->appName, 'authenticate', [], 'guest'); - $this->assertEquals($expectedResponse, $response); - } - - public function testShowAuthenticateAuthenticatedForDifferentShare() { - $share = \OC::$server->getShareManager()->newShare(); - $share->setId(1); - - $this->shareManager - ->expects($this->once()) - ->method('getShareByToken') - ->with('token') - ->willReturn($share); - - $this->session->method('exists')->with('public_link_authenticated')->willReturn(true); - $this->session->method('get')->with('public_link_authenticated')->willReturn('2'); - - $response = $this->shareController->showAuthenticate('token'); - $expectedResponse = new TemplateResponse($this->appName, 'authenticate', [], 'guest'); - $this->assertEquals($expectedResponse, $response); - } - - public function testShowAuthenticateCorrectShare() { - $share = \OC::$server->getShareManager()->newShare(); - $share->setId(1); - - $this->shareManager - ->expects($this->once()) - ->method('getShareByToken') - ->with('token') - ->willReturn($share); - - $this->session->method('exists')->with('public_link_authenticated')->willReturn(true); - $this->session->method('get')->with('public_link_authenticated')->willReturn('1'); - - $this->urlGenerator->expects($this->once()) - ->method('linkToRoute') - ->with('files_sharing.sharecontroller.showShare', ['token' => 'token']) - ->willReturn('redirect'); - - $response = $this->shareController->showAuthenticate('token'); - $expectedResponse = new RedirectResponse('redirect'); - $this->assertEquals($expectedResponse, $response); - } - - public function testAuthenticateInvalidToken() { - $this->shareManager - ->expects($this->once()) - ->method('getShareByToken') - ->with('token') - ->will($this->throwException(new \OCP\Share\Exceptions\ShareNotFound())); - - $response = $this->shareController->authenticate('token'); - $expectedResponse = new NotFoundResponse(); - $this->assertEquals($expectedResponse, $response); - } - - public function testAuthenticateValidPassword() { - $share = \OC::$server->getShareManager()->newShare(); - $share->setId(42); - - $this->shareManager - ->expects($this->once()) - ->method('getShareByToken') - ->with('token') - ->willReturn($share); - - $this->shareManager - ->expects($this->once()) - ->method('checkPassword') - ->with($share, 'validpassword') - ->willReturn(true); - - $this->session - ->expects($this->once()) - ->method('set') - ->with('public_link_authenticated', '42'); - - $this->urlGenerator->expects($this->once()) - ->method('linkToRoute') - ->with('files_sharing.sharecontroller.showShare', ['token'=>'token']) - ->willReturn('redirect'); - - $response = $this->shareController->authenticate('token', 'validpassword'); - $expectedResponse = new RedirectResponse('redirect'); - $this->assertEquals($expectedResponse, $response); - } - - public function testAuthenticateInvalidPassword() { - $share = \OC::$server->getShareManager()->newShare(); - $share->setNodeId(100) - ->setNodeType('file') - ->setToken('token') - ->setSharedBy('initiator') - ->setId(42); - - $this->shareManager - ->expects($this->once()) - ->method('getShareByToken') - ->with('token') - ->willReturn($share); - - $this->shareManager - ->expects($this->once()) - ->method('checkPassword') - ->with($share, 'invalidpassword') - ->willReturn(false); - - $this->session - ->expects($this->never()) - ->method('set'); - - $hookListner = $this->getMockBuilder('Dummy')->setMethods(['access'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'share_link_access', $hookListner, 'access'); - - $hookListner->expects($this->once()) - ->method('access') - ->with($this->callback(function(array $data) { - return $data['itemType'] === 'file' && - $data['itemSource'] === 100 && - $data['uidOwner'] === 'initiator' && - $data['token'] === 'token' && - $data['errorCode'] === 403 && - $data['errorMessage'] === 'Wrong password'; - })); - - $response = $this->shareController->authenticate('token', 'invalidpassword'); - $expectedResponse = new TemplateResponse($this->appName, 'authenticate', array('wrongpw' => true), 'guest'); - $this->assertEquals($expectedResponse, $response); - } - - public function testShowShareInvalidToken() { - $this->shareManager - ->expects($this->once()) - ->method('getShareByToken') - ->with('invalidtoken') - ->will($this->throwException(new ShareNotFound())); - - // Test without a not existing token - $response = $this->shareController->showShare('invalidtoken'); - $expectedResponse = new NotFoundResponse(); - $this->assertEquals($expectedResponse, $response); - } - - public function testShowShareNotAuthenticated() { - $share = \OC::$server->getShareManager()->newShare(); - $share->setPassword('password'); - - $this->shareManager - ->expects($this->once()) - ->method('getShareByToken') - ->with('validtoken') - ->willReturn($share); - - $this->urlGenerator->expects($this->once()) - ->method('linkToRoute') - ->with('files_sharing.sharecontroller.authenticate', ['token' => 'validtoken']) - ->willReturn('redirect'); - - // Test without a not existing token - $response = $this->shareController->showShare('validtoken'); - $expectedResponse = new RedirectResponse('redirect'); - $this->assertEquals($expectedResponse, $response); - } - - - public function testShowShare() { - $owner = $this->getMock('OCP\IUser'); - $owner->method('getDisplayName')->willReturn('ownerDisplay'); - $owner->method('getUID')->willReturn('ownerUID'); - - $file = $this->getMock('OCP\Files\File'); - $file->method('getName')->willReturn('file1.txt'); - $file->method('getMimetype')->willReturn('text/plain'); - $file->method('getSize')->willReturn(33); - $file->method('isReadable')->willReturn(true); - $file->method('isShareable')->willReturn(true); - - $share = \OC::$server->getShareManager()->newShare(); - $share->setId(42); - $share->setPassword('password') - ->setShareOwner('ownerUID') - ->setNode($file) - ->setTarget('/file1.txt'); - - $this->session->method('exists')->with('public_link_authenticated')->willReturn(true); - $this->session->method('get')->with('public_link_authenticated')->willReturn('42'); - - $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true); - - $this->config->method('getSystemValue') - ->willReturnMap( - [ - ['max_filesize_animated_gifs_public_sharing', 10, 10], - ['enable_previews', true, true], - ['preview_max_x', 1024, 1024], - ['preview_max_y', 1024, 1024], - ] - ); - $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10); - $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true); - - $this->shareManager - ->expects($this->once()) - ->method('getShareByToken') - ->with('token') - ->willReturn($share); - - $this->userManager->method('get')->with('ownerUID')->willReturn($owner); - - $response = $this->shareController->showShare('token'); - $sharedTmplParams = array( - 'displayName' => 'ownerDisplay', - 'owner' => 'ownerUID', - 'filename' => 'file1.txt', - 'directory_path' => '/file1.txt', - 'mimetype' => 'text/plain', - 'dirToken' => 'token', - 'sharingToken' => 'token', - 'server2serversharing' => true, - 'protected' => 'true', - 'dir' => '', - 'downloadURL' => null, - 'fileSize' => '33 B', - 'nonHumanFileSize' => 33, - 'maxSizeAnimateGif' => 10, - 'previewSupported' => true, - 'previewEnabled' => true, - 'previewMaxX' => 1024, - 'previewMaxY' => 1024, - ); - - $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy(); - $csp->addAllowedFrameDomain('\'self\''); - $expectedResponse = new TemplateResponse($this->appName, 'public', $sharedTmplParams, 'base'); - $expectedResponse->setContentSecurityPolicy($csp); - - $this->assertEquals($expectedResponse, $response); - } - - /** - * @expectedException \OCP\Files\NotFoundException - */ - public function testShowShareInvalid() { - $owner = $this->getMock('OCP\IUser'); - $owner->method('getDisplayName')->willReturn('ownerDisplay'); - $owner->method('getUID')->willReturn('ownerUID'); - - $file = $this->getMock('OCP\Files\File'); - $file->method('getName')->willReturn('file1.txt'); - $file->method('getMimetype')->willReturn('text/plain'); - $file->method('getSize')->willReturn(33); - $file->method('isShareable')->willReturn(false); - $file->method('isReadable')->willReturn(true); - - $share = \OC::$server->getShareManager()->newShare(); - $share->setId(42); - $share->setPassword('password') - ->setShareOwner('ownerUID') - ->setNode($file) - ->setTarget('/file1.txt'); - - $this->session->method('exists')->with('public_link_authenticated')->willReturn(true); - $this->session->method('get')->with('public_link_authenticated')->willReturn('42'); - - $this->previewManager->method('isMimeSupported')->with('text/plain')->willReturn(true); - - $this->config->method('getSystemValue') - ->willReturnMap( - [ - ['max_filesize_animated_gifs_public_sharing', 10, 10], - ['enable_previews', true, true], - ] - ); - $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10); - $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true); - - $this->shareManager - ->expects($this->once()) - ->method('getShareByToken') - ->with('token') - ->willReturn($share); - - $this->userManager->method('get')->with('ownerUID')->willReturn($owner); - - $this->shareController->showShare('token'); - } - - - public function testDownloadShare() { - $share = $this->getMock('\OCP\Share\IShare'); - $share->method('getPassword')->willReturn('password'); - - $this->shareManager - ->expects($this->once()) - ->method('getShareByToken') - ->with('validtoken') - ->willReturn($share); - - $this->urlGenerator->expects($this->once()) - ->method('linkToRoute') - ->with('files_sharing.sharecontroller.authenticate', ['token' => 'validtoken']) - ->willReturn('redirect'); - - // Test with a password protected share and no authentication - $response = $this->shareController->downloadShare('validtoken'); - $expectedResponse = new RedirectResponse('redirect'); - $this->assertEquals($expectedResponse, $response); - } - -} diff --git a/apps/files_sharing/tests/deleteorphanedsharesjobtest.php b/apps/files_sharing/tests/deleteorphanedsharesjobtest.php deleted file mode 100644 index c9aea60d255..00000000000 --- a/apps/files_sharing/tests/deleteorphanedsharesjobtest.php +++ /dev/null @@ -1,171 +0,0 @@ - - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace Test\BackgroundJob; - -use OCA\Files_sharing\Lib\DeleteOrphanedSharesJob; - -/** - * Class DeleteOrphanedSharesJobTest - * - * @group DB - * - * @package Test\BackgroundJob - */ -class DeleteOrphanedSharesJobTest extends \Test\TestCase { - - /** - * @var bool - */ - private static $trashBinStatus; - - /** - * @var DeleteOrphanedSharesJob - */ - private $job; - - /** - * @var \OCP\IDBConnection - */ - private $connection; - - /** - * @var string - */ - private $user1; - - /** - * @var string - */ - private $user2; - - public static function setUpBeforeClass() { - $appManager = \OC::$server->getAppManager(); - self::$trashBinStatus = $appManager->isEnabledForUser('files_trashbin'); - $appManager->disableApp('files_trashbin'); - - // just in case... - \OC\Files\Filesystem::getLoader()->removeStorageWrapper('oc_trashbin'); - } - - public static function tearDownAfterClass() { - if (self::$trashBinStatus) { - \OC::$server->getAppManager()->enableApp('files_trashbin'); - } - } - - protected function setup() { - parent::setUp(); - - $this->connection = \OC::$server->getDatabaseConnection(); - // clear occasional leftover shares from other tests - $this->connection->executeUpdate('DELETE FROM `*PREFIX*share`'); - - $this->user1 = $this->getUniqueID('user1_'); - $this->user2 = $this->getUniqueID('user2_'); - - $userManager = \OC::$server->getUserManager(); - $userManager->createUser($this->user1, 'pass'); - $userManager->createUser($this->user2, 'pass'); - - \OC::registerShareHooks(); - - $this->job = new DeleteOrphanedSharesJob(); - } - - protected function tearDown() { - $this->connection->executeUpdate('DELETE FROM `*PREFIX*share`'); - - $userManager = \OC::$server->getUserManager(); - $user1 = $userManager->get($this->user1); - if($user1) { - $user1->delete(); - } - $user2 = $userManager->get($this->user2); - if($user2) { - $user2->delete(); - } - - $this->logout(); - - parent::tearDown(); - } - - private function getShares() { - $shares = []; - $result = $this->connection->executeQuery('SELECT * FROM `*PREFIX*share`'); - while ($row = $result->fetch()) { - $shares[] = $row; - } - $result->closeCursor(); - return $shares; - } - - /** - * Test clearing orphaned shares - */ - public function testClearShares() { - $this->loginAsUser($this->user1); - - $view = new \OC\Files\View('/' . $this->user1 . '/'); - $view->mkdir('files/test'); - $view->mkdir('files/test/sub'); - - $fileInfo = $view->getFileInfo('files/test/sub'); - $fileId = $fileInfo->getId(); - - $this->assertTrue( - \OCP\Share::shareItem('folder', $fileId, \OCP\Share::SHARE_TYPE_USER, $this->user2, \OCP\Constants::PERMISSION_READ), - 'Failed asserting that user 1 successfully shared "test/sub" with user 2.' - ); - - $this->assertCount(1, $this->getShares()); - - $this->job->run([]); - - $this->assertCount(1, $this->getShares(), 'Linked shares not deleted'); - - $view->unlink('files/test'); - - $this->job->run([]); - - $this->assertCount(0, $this->getShares(), 'Orphaned shares deleted'); - } - - public function testKeepNonFileShares() { - $this->loginAsUser($this->user1); - - \OCP\Share::registerBackend('test', 'Test\Share\Backend'); - - $this->assertTrue( - \OCP\Share::shareItem('test', 'test.txt', \OCP\Share::SHARE_TYPE_USER, $this->user2, \OCP\Constants::PERMISSION_READ), - 'Failed asserting that user 1 successfully shared something with user 2.' - ); - - $this->assertCount(1, $this->getShares()); - - $this->job->run([]); - - $this->assertCount(1, $this->getShares(), 'Non-file shares kept'); - } -} - diff --git a/apps/files_sharing/tests/encryptedsizepropagation.php b/apps/files_sharing/tests/encryptedsizepropagation.php deleted file mode 100644 index e341606abe4..00000000000 --- a/apps/files_sharing/tests/encryptedsizepropagation.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_sharing\Tests; - -use OC\Files\View; -use Test\Traits\EncryptionTrait; - -/** - * @group DB - */ -class EncryptedSizePropagation extends SizePropagation { - use EncryptionTrait; - - protected function setupUser($name, $password = '') { - $this->createUser($name, $password); - $tmpFolder = \OC::$server->getTempManager()->getTemporaryFolder(); - $this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]); - $this->setupForUser($name, $password); - $this->loginWithEncryption($name); - return new View('/' . $name . '/files'); - } -} diff --git a/apps/files_sharing/tests/etagpropagation.php b/apps/files_sharing/tests/etagpropagation.php deleted file mode 100644 index e7d5bb46258..00000000000 --- a/apps/files_sharing/tests/etagpropagation.php +++ /dev/null @@ -1,461 +0,0 @@ - - * @author Lukas Reschke - * @author Robin Appelman - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_sharing\Tests; - -use OC\Files\Filesystem; -use OC\Files\View; - -/** - * Class EtagPropagation - * - * @group DB - * - * @package OCA\Files_sharing\Tests - */ -class EtagPropagation extends PropagationTestCase { - - /** - * "user1" is the admin who shares a folder "sub1/sub2/folder" with "user2" and "user3" - * "user2" receives the folder and puts it in "sub1/sub2/folder" - * "user3" receives the folder and puts it in "sub1/sub2/folder" - * "user2" reshares the subdir "sub1/sub2/folder/inside" with "user4" - * "user4" puts the received "inside" folder into "sub1/sub2/inside" (this is to check if it propagates across multiple subfolders) - */ - protected function setUpShares() { - $this->fileIds[self::TEST_FILES_SHARING_API_USER1] = []; - $this->fileIds[self::TEST_FILES_SHARING_API_USER2] = []; - $this->fileIds[self::TEST_FILES_SHARING_API_USER3] = []; - $this->fileIds[self::TEST_FILES_SHARING_API_USER4] = []; - - $rootFolder = \OC::$server->getRootFolder(); - $shareManager = \OC::$server->getShareManager(); - - $this->rootView = new View(''); - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - $view1 = new View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files'); - $view1->mkdir('/sub1/sub2/folder/inside'); - $view1->mkdir('/directReshare'); - $view1->mkdir('/sub1/sub2/folder/other'); - $view1->file_put_contents('/foo.txt', 'foobar'); - $view1->file_put_contents('/sub1/sub2/folder/file.txt', 'foobar'); - $view1->file_put_contents('/sub1/sub2/folder/inside/file.txt', 'foobar'); - $folderInfo = $view1->getFileInfo('/sub1/sub2/folder'); - $this->assertInstanceOf('\OC\Files\FileInfo', $folderInfo); - $fileInfo = $view1->getFileInfo('/foo.txt'); - $this->assertInstanceOf('\OC\Files\FileInfo', $fileInfo); - - $node = $rootFolder->getUserFolder(self::TEST_FILES_SHARING_API_USER1) - ->get('/foo.txt'); - $share = $shareManager->newShare(); - $share->setNode($node) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setPermissions(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE); - $shareManager->createShare($share); - $node = $rootFolder->getUserFolder(self::TEST_FILES_SHARING_API_USER1) - ->get('/sub1/sub2/folder'); - $share = $shareManager->newShare(); - $share->setNode($node) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); - $shareManager->createShare($share); - $share = $shareManager->newShare(); - $share->setNode($node) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER3) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); - $shareManager->createShare($share); - - $folderInfo = $view1->getFileInfo('/directReshare'); - $this->assertInstanceOf('\OC\Files\FileInfo', $folderInfo); - - $node = $rootFolder->getUserFolder(self::TEST_FILES_SHARING_API_USER1) - ->get('/directReshare'); - $share = $shareManager->newShare(); - $share->setNode($node) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); - $shareManager->createShare($share); - - $this->fileIds[self::TEST_FILES_SHARING_API_USER1][''] = $view1->getFileInfo('')->getId(); - $this->fileIds[self::TEST_FILES_SHARING_API_USER1]['sub1'] = $view1->getFileInfo('sub1')->getId(); - $this->fileIds[self::TEST_FILES_SHARING_API_USER1]['sub1/sub2'] = $view1->getFileInfo('sub1/sub2')->getId(); - - /* - * User 2 - */ - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); - $view2 = new View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); - $view2->mkdir('/sub1/sub2'); - $view2->rename('/folder', '/sub1/sub2/folder'); - $insideInfo = $view2->getFileInfo('/sub1/sub2/folder/inside'); - $this->assertInstanceOf('\OC\Files\FileInfo', $insideInfo); - - $node = $rootFolder->getUserFolder(self::TEST_FILES_SHARING_API_USER2) - ->get('/sub1/sub2/folder/inside'); - $share = $shareManager->newShare(); - $share->setNode($node) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER4) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); - $shareManager->createShare($share); - - $folderInfo = $view2->getFileInfo('/directReshare'); - $this->assertInstanceOf('\OC\Files\FileInfo', $folderInfo); - - $node = $rootFolder->getUserFolder(self::TEST_FILES_SHARING_API_USER2) - ->get('/directReshare'); - $share = $shareManager->newShare(); - $share->setNode($node) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER4) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER2) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); - $shareManager->createShare($share); - - $this->fileIds[self::TEST_FILES_SHARING_API_USER2][''] = $view2->getFileInfo('')->getId(); - $this->fileIds[self::TEST_FILES_SHARING_API_USER2]['sub1'] = $view2->getFileInfo('sub1')->getId(); - $this->fileIds[self::TEST_FILES_SHARING_API_USER2]['sub1/sub2'] = $view2->getFileInfo('sub1/sub2')->getId(); - - /* - * User 3 - */ - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER3); - $view3 = new View('/' . self::TEST_FILES_SHARING_API_USER3 . '/files'); - $view3->mkdir('/sub1/sub2'); - $view3->rename('/folder', '/sub1/sub2/folder'); - $this->fileIds[self::TEST_FILES_SHARING_API_USER3][''] = $view3->getFileInfo('')->getId(); - $this->fileIds[self::TEST_FILES_SHARING_API_USER3]['sub1'] = $view3->getFileInfo('sub1')->getId(); - $this->fileIds[self::TEST_FILES_SHARING_API_USER3]['sub1/sub2'] = $view3->getFileInfo('sub1/sub2')->getId(); - - /* - * User 4 - */ - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER4); - $view4 = new View('/' . self::TEST_FILES_SHARING_API_USER4 . '/files'); - $view4->mkdir('/sub1/sub2'); - $view4->rename('/inside', '/sub1/sub2/inside'); - $this->fileIds[self::TEST_FILES_SHARING_API_USER4][''] = $view4->getFileInfo('')->getId(); - $this->fileIds[self::TEST_FILES_SHARING_API_USER4]['sub1'] = $view4->getFileInfo('sub1')->getId(); - $this->fileIds[self::TEST_FILES_SHARING_API_USER4]['sub1/sub2'] = $view4->getFileInfo('sub1/sub2')->getId(); - - foreach ($this->fileIds as $user => $ids) { - $this->loginAsUser($user); - foreach ($ids as $id) { - $path = $this->rootView->getPath($id); - $ls = $this->rootView->getDirectoryContent($path); - $this->fileEtags[$id] = $this->rootView->getFileInfo($path)->getEtag(); - } - } - } - - public function testOwnerWritesToShare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - Filesystem::file_put_contents('/sub1/sub2/folder/asd.txt', 'bar'); - $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER4]); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3]); - - $this->assertAllUnchanged(); - } - - public function testOwnerWritesToSingleFileShare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - Filesystem::file_put_contents('/foo.txt', 'longer_bar'); - $t = (int)Filesystem::filemtime('/foo.txt') - 1; - Filesystem::touch('/foo.txt', $t); - $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER4, self::TEST_FILES_SHARING_API_USER3]); - $this->assertEtagsChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2]); - - $this->assertAllUnchanged(); - } - - public function testOwnerWritesToShareWithReshare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - Filesystem::file_put_contents('/sub1/sub2/folder/inside/bar.txt', 'bar'); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - - $this->assertAllUnchanged(); - } - - public function testOwnerRenameInShare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER4]); - Filesystem::rename('/sub1/sub2/folder/file.txt', '/sub1/sub2/folder/renamed.txt'); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3]); - - $this->assertAllUnchanged(); - } - - public function testOwnerRenameInReShare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - Filesystem::rename('/sub1/sub2/folder/inside/file.txt', '/sub1/sub2/folder/inside/renamed.txt'); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - - $this->assertAllUnchanged(); - } - - public function testOwnerRenameIntoReShare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - Filesystem::rename('/sub1/sub2/folder/file.txt', '/sub1/sub2/folder/inside/renamed.txt'); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - - $this->assertAllUnchanged(); - } - - public function testOwnerRenameOutOfReShare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - Filesystem::rename('/sub1/sub2/folder/inside/file.txt', '/sub1/sub2/folder/renamed.txt'); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - - $this->assertAllUnchanged(); - } - - public function testOwnerDeleteInShare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - Filesystem::unlink('/sub1/sub2/folder/file.txt'); - $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER4]); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3]); - - $this->assertAllUnchanged(); - } - - public function testOwnerDeleteInReShare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - Filesystem::unlink('/sub1/sub2/folder/inside/file.txt'); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - - $this->assertAllUnchanged(); - } - - public function testOwnerUnshares() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - $folderInfo = $this->rootView->getFileInfo('/' . self::TEST_FILES_SHARING_API_USER1 . '/files/sub1/sub2/folder'); - $this->assertInstanceOf('\OC\Files\FileInfo', $folderInfo); - - $node = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1)->get('/sub1/sub2/folder'); - $shareManager = \OC::$server->getShareManager(); - $shares = $shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER1, \OCP\Share::SHARE_TYPE_USER, $node, true); - - foreach ($shares as $share) { - if ($share->getSharedWith() === self::TEST_FILES_SHARING_API_USER2) { - $shareManager->deleteShare($share); - } - } - - $this->assertEtagsForFoldersChanged([ - // direct recipient affected - self::TEST_FILES_SHARING_API_USER2, - ]); - - $this->assertAllUnchanged(); - } - - public function testOwnerUnsharesFlatReshares() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - $folderInfo = $this->rootView->getFileInfo('/' . self::TEST_FILES_SHARING_API_USER1 . '/files/sub1/sub2/folder/inside'); - $this->assertInstanceOf('\OC\Files\FileInfo', $folderInfo); - - $node = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1)->get('/sub1/sub2/folder/inside'); - $shareManager = \OC::$server->getShareManager(); - $shares = $shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER1, \OCP\Share::SHARE_TYPE_USER, $node, true); - - foreach ($shares as $share) { - $shareManager->deleteShare($share); - } - - $this->assertEtagsForFoldersChanged([ - // direct recipient affected - self::TEST_FILES_SHARING_API_USER4, - ]); - - $this->assertAllUnchanged(); - } - - public function testRecipientUnsharesFromSelf() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); - $ls = $this->rootView->getDirectoryContent('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/sub1/sub2/'); - $this->assertTrue( - $this->rootView->unlink('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/sub1/sub2/folder') - ); - $this->assertEtagsForFoldersChanged([ - // direct recipient affected - self::TEST_FILES_SHARING_API_USER2, - ]); - - $this->assertAllUnchanged(); - } - - public function testRecipientWritesToShare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); - Filesystem::file_put_contents('/sub1/sub2/folder/asd.txt', 'bar'); - $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER4]); - $this->assertEtagsForFoldersChanged([ - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3 - ]); - - $this->assertAllUnchanged(); - } - - public function testRecipientWritesToReshare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); - Filesystem::file_put_contents('/sub1/sub2/folder/inside/asd.txt', 'bar'); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - - $this->assertAllUnchanged(); - } - - public function testRecipientWritesToOtherRecipientsReshare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER3); - Filesystem::file_put_contents('/sub1/sub2/folder/inside/asd.txt', 'bar'); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - - $this->assertAllUnchanged(); - } - - public function testRecipientRenameInShare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); - Filesystem::rename('/sub1/sub2/folder/file.txt', '/sub1/sub2/folder/renamed.txt'); - $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER4]); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3]); - - $this->assertAllUnchanged(); - } - - public function testRecipientRenameInReShare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); - Filesystem::rename('/sub1/sub2/folder/inside/file.txt', '/sub1/sub2/folder/inside/renamed.txt'); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - - $this->assertAllUnchanged(); - } - - public function testRecipientRenameResharedFolder() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); - Filesystem::rename('/directReshare', '/sub1/directReshare'); - $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - $this->assertEtagsChanged([self::TEST_FILES_SHARING_API_USER2]); - - $this->assertEtagsChanged([self::TEST_FILES_SHARING_API_USER2], 'sub1'); - - $this->assertAllUnchanged(); - } - - public function testRecipientDeleteInShare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); - Filesystem::unlink('/sub1/sub2/folder/file.txt'); - $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER4]); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3]); - - $this->assertAllUnchanged(); - } - - public function testRecipientDeleteInReShare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); - Filesystem::unlink('/sub1/sub2/folder/inside/file.txt'); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - - $this->assertAllUnchanged(); - } - - public function testReshareRecipientWritesToReshare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER4); - Filesystem::file_put_contents('/sub1/sub2/inside/asd.txt', 'bar'); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - - $this->assertAllUnchanged(); - } - - public function testReshareRecipientRenameInReShare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER4); - Filesystem::rename('/sub1/sub2/inside/file.txt', '/sub1/sub2/inside/renamed.txt'); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - - $this->assertAllUnchanged(); - } - - public function testReshareRecipientDeleteInReShare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER4); - Filesystem::unlink('/sub1/sub2/inside/file.txt'); - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - - $this->assertAllUnchanged(); - } - - public function testRecipientUploadInDirectReshare() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); - Filesystem::file_put_contents('/directReshare/test.txt', 'sad'); - $this->assertEtagsNotChanged([self::TEST_FILES_SHARING_API_USER3]); - $this->assertEtagsChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER4]); - - $this->assertAllUnchanged(); - } - - public function testEtagChangeOnPermissionsChange() { - $userFolder = $this->rootFolder->getUserFolder(self::TEST_FILES_SHARING_API_USER1); - $node = $userFolder->get('/sub1/sub2/folder'); - - $shares = $this->shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER1, \OCP\Share::SHARE_TYPE_USER, $node); - /** @var \OCP\Share\IShare[] $shares */ - $shares = array_filter($shares, function(\OCP\Share\IShare $share) { - return $share->getSharedWith() === self::TEST_FILES_SHARING_API_USER2; - }); - $this->assertCount(1, $shares); - - $share = $shares[0]; - $share->setPermissions(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_SHARE); - $this->shareManager->updateShare($share); - - $this->assertEtagsForFoldersChanged([self::TEST_FILES_SHARING_API_USER2]); - - $this->assertAllUnchanged(); - } -} diff --git a/apps/files_sharing/tests/expiresharesjobtest.php b/apps/files_sharing/tests/expiresharesjobtest.php deleted file mode 100644 index bb4f756e6c7..00000000000 --- a/apps/files_sharing/tests/expiresharesjobtest.php +++ /dev/null @@ -1,212 +0,0 @@ - - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\Tests; - -use OCA\Files_Sharing\ExpireSharesJob; - -/** - * Class ExpireSharesJobTest - * - * @group DB - * - * @package OCA\Files_Sharing\Tests - */ -class ExpireSharesJobTest extends \Test\TestCase { - - /** - * @var ExpireSharesJob - */ - private $job; - - /** - * @var \OCP\IDBConnection - */ - private $connection; - - /** - * @var string - */ - private $user1; - - /** - * @var string - */ - private $user2; - - protected function setup() { - parent::setUp(); - - $this->connection = \OC::$server->getDatabaseConnection(); - // clear occasional leftover shares from other tests - $this->connection->executeUpdate('DELETE FROM `*PREFIX*share`'); - - $this->user1 = $this->getUniqueID('user1_'); - $this->user2 = $this->getUniqueID('user2_'); - - $userManager = \OC::$server->getUserManager(); - $userManager->createUser($this->user1, 'pass'); - $userManager->createUser($this->user2, 'pass'); - - \OC::registerShareHooks(); - - $this->job = new ExpireSharesJob(); - } - - protected function tearDown() { - $this->connection->executeUpdate('DELETE FROM `*PREFIX*share`'); - - $userManager = \OC::$server->getUserManager(); - $user1 = $userManager->get($this->user1); - if($user1) { - $user1->delete(); - } - $user2 = $userManager->get($this->user2); - if($user2) { - $user2->delete(); - } - - $this->logout(); - - parent::tearDown(); - } - - private function getShares() { - $shares = []; - $qb = $this->connection->getQueryBuilder(); - - $result = $qb->select('*') - ->from('share') - ->execute(); - - while ($row = $result->fetch()) { - $shares[] = $row; - } - $result->closeCursor(); - return $shares; - } - - public function dataExpireLinkShare() { - return [ - [false, '', false, false], - [false, '', true, false], - [true, 'P1D', false, true], - [true, 'P1D', true, false], - [true, 'P1W', false, true], - [true, 'P1W', true, false], - [true, 'P1M', false, true], - [true, 'P1M', true, false], - [true, 'P1Y', false, true], - [true, 'P1Y', true, false], - ]; - } - - /** - * @dataProvider dataExpireLinkShare - * - * @param bool addExpiration Should we add an expire date - * @param string $interval The dateInterval - * @param bool $addInterval If true add to the current time if false subtract - * @param bool $shouldExpire Should this share be expired - */ - public function testExpireLinkShare($addExpiration, $interval, $addInterval, $shouldExpire) { - $this->loginAsUser($this->user1); - - $view = new \OC\Files\View('/' . $this->user1 . '/'); - $view->mkdir('files/test'); - - $fileInfo = $view->getFileInfo('files/test'); - - $this->assertNotNull( - \OCP\Share::shareItem('folder', $fileInfo->getId(), \OCP\Share::SHARE_TYPE_LINK, null, \OCP\Constants::PERMISSION_READ), - 'Failed asserting that user 1 successfully shared "test" by link.' - ); - - $shares = $this->getShares(); - $this->assertCount(1, $shares); - reset($shares); - $share = current($shares); - - if ($addExpiration) { - $expire = new \DateTime(); - $expire->setTime(0, 0, 0); - if ($addInterval) { - $expire->add(new \DateInterval($interval)); - } else { - $expire->sub(new \DateInterval($interval)); - } - $expire = $expire->format('Y-m-d 00:00:00'); - - // Set expiration date to yesterday - $qb = $this->connection->getQueryBuilder(); - $qb->update('share') - ->set('expiration', $qb->createParameter('expiration')) - ->where($qb->expr()->eq('id', $qb->createParameter('id'))) - ->setParameter('id', $share['id']) - ->setParameter('expiration', $expire) - ->execute(); - - $shares = $this->getShares(); - $this->assertCount(1, $shares); - } - - $this->logout(); - - $this->job->run([]); - - $shares = $this->getShares(); - - if ($shouldExpire) { - $this->assertCount(0, $shares); - } else { - $this->assertCount(1, $shares); - } - } - - public function testDoNotExpireOtherShares() { - $this->loginAsUser($this->user1); - - $view = new \OC\Files\View('/' . $this->user1 . '/'); - $view->mkdir('files/test'); - - $fileInfo = $view->getFileInfo('files/test'); - - $this->assertNotNull( - \OCP\Share::shareItem('folder', $fileInfo->getId(), \OCP\Share::SHARE_TYPE_USER, $this->user2, \OCP\Constants::PERMISSION_READ), - 'Failed asserting that user 1 successfully shared "test" by link with user2.' - ); - - $shares = $this->getShares(); - $this->assertCount(1, $shares); - reset($shares); - $share = current($shares); - - $this->logout(); - - $this->job->run([]); - - $shares = $this->getShares(); - $this->assertCount(1, $shares); - } - -} - diff --git a/apps/files_sharing/tests/external/cache.php b/apps/files_sharing/tests/external/cache.php deleted file mode 100644 index 4ae1bc563df..00000000000 --- a/apps/files_sharing/tests/external/cache.php +++ /dev/null @@ -1,124 +0,0 @@ - - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -namespace OCA\Files_sharing\Tests\External; - -use OCA\Files_sharing\Tests\TestCase; - -/** - * Class Cache - * - * @group DB - * - * @package OCA\Files_sharing\Tests\External - */ -class Cache extends TestCase { - - /** - * @var \OC\Files\Storage\Storage - **/ - private $storage; - - /** - * @var \OCA\Files_Sharing\External\Cache - */ - private $cache; - - /** - * @var string - */ - private $remoteUser; - - protected function setUp() { - parent::setUp(); - - $this->remoteUser = $this->getUniqueID('remoteuser'); - - $this->storage = $this->getMockBuilder('\OCA\Files_Sharing\External\Storage') - ->disableOriginalConstructor() - ->getMock(); - $this->storage - ->expects($this->any()) - ->method('getId') - ->will($this->returnValue('dummystorage::')); - $this->cache = new \OCA\Files_Sharing\External\Cache( - $this->storage, - 'http://example.com/owncloud', - $this->remoteUser - ); - $this->cache->put( - 'test.txt', - array( - 'mimetype' => 'text/plain', - 'size' => 5, - 'mtime' => 123, - ) - ); - } - - protected function tearDown() { - if ($this->cache) { - $this->cache->clear(); - } - parent::tearDown(); - } - - public function testGetInjectsOwnerDisplayName() { - $info = $this->cache->get('test.txt'); - $this->assertEquals( - $this->remoteUser . '@example.com/owncloud', - $info['displayname_owner'] - ); - } - - public function testGetReturnsFalseIfNotFound() { - $info = $this->cache->get('unexisting-entry.txt'); - $this->assertFalse($info); - } - - public function testGetFolderPopulatesOwner() { - $dirId = $this->cache->put( - 'subdir', - array( - 'mimetype' => 'httpd/unix-directory', - 'size' => 5, - 'mtime' => 123, - ) - ); - $this->cache->put( - 'subdir/contents.txt', - array( - 'mimetype' => 'text/plain', - 'size' => 5, - 'mtime' => 123, - ) - ); - - $results = $this->cache->getFolderContentsById($dirId); - $this->assertEquals(1, count($results)); - $this->assertEquals( - $this->remoteUser . '@example.com/owncloud', - $results[0]['displayname_owner'] - ); - } - -} diff --git a/apps/files_sharing/tests/external/managertest.php b/apps/files_sharing/tests/external/managertest.php deleted file mode 100644 index 48a9098ae1d..00000000000 --- a/apps/files_sharing/tests/external/managertest.php +++ /dev/null @@ -1,253 +0,0 @@ - - * @author Lukas Reschke - * @author Robin Appelman - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\Tests\External; - -use OC\Files\Storage\StorageFactory; -use OCA\FederatedFileSharing\DiscoveryManager; -use OCA\Files_Sharing\External\Manager; -use OCA\Files_Sharing\External\MountProvider; -use OCA\Files_Sharing\Tests\TestCase; -use Test\Traits\UserTrait; - -/** - * Class ManagerTest - * - * @group DB - * - * @package OCA\Files_Sharing\Tests\External - */ -class ManagerTest extends TestCase { - use UserTrait; - - /** @var Manager **/ - private $manager; - - /** @var \OC\Files\Mount\Manager */ - private $mountManager; - - /** @var \PHPUnit_Framework_MockObject_MockObject */ - private $httpHelper; - - private $uid; - - /** - * @var \OCP\IUser - */ - private $user; - private $mountProvider; - - protected function setUp() { - parent::setUp(); - - $this->uid = $this->getUniqueID('user'); - $this->createUser($this->uid, ''); - $this->user = \OC::$server->getUserManager()->get($this->uid); - $this->mountManager = new \OC\Files\Mount\Manager(); - $this->httpHelper = $httpHelper = $this->getMockBuilder('\OC\HTTPHelper')->disableOriginalConstructor()->getMock(); - $discoveryManager = new DiscoveryManager( - \OC::$server->getMemCacheFactory(), - \OC::$server->getHTTPClientService() - ); - /** @var \OC\HTTPHelper $httpHelper */ - $this->manager = new Manager( - \OC::$server->getDatabaseConnection(), - $this->mountManager, - new StorageFactory(), - $httpHelper, - \OC::$server->getNotificationManager(), - $discoveryManager, - $this->uid - ); - $this->mountProvider = new MountProvider(\OC::$server->getDatabaseConnection(), function() { - return $this->manager; - }); - } - - private function setupMounts() { - $mounts = $this->mountProvider->getMountsForUser($this->user, new StorageFactory()); - foreach ($mounts as $mount) { - $this->mountManager->addMount($mount); - } - } - - public function testAddShare() { - - $shareData1 = [ - 'remote' => 'http://localhost', - 'token' => 'token1', - 'password' => '', - 'name' => '/SharedFolder', - 'owner' => 'foobar', - 'accepted' => false, - 'user' => $this->uid, - ]; - $shareData2 = $shareData1; - $shareData2['token'] = 'token2'; - $shareData3 = $shareData1; - $shareData3['token'] = 'token3'; - - // Add a share for "user" - $this->assertSame(null, call_user_func_array([$this->manager, 'addShare'], $shareData1)); - $openShares = $this->manager->getOpenShares(); - $this->assertCount(1, $openShares); - $this->assertExternalShareEntry($shareData1, $openShares[0], 1, '{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); - - $this->setupMounts(); - $this->assertNotMount('SharedFolder'); - $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); - - // Add a second share for "user" with the same name - $this->assertSame(null, call_user_func_array([$this->manager, 'addShare'], $shareData2)); - $openShares = $this->manager->getOpenShares(); - $this->assertCount(2, $openShares); - $this->assertExternalShareEntry($shareData1, $openShares[0], 1, '{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); - // New share falls back to "-1" appendix, because the name is already taken - $this->assertExternalShareEntry($shareData2, $openShares[1], 2, '{{TemporaryMountPointName#' . $shareData2['name'] . '}}-1'); - - $this->setupMounts(); - $this->assertNotMount('SharedFolder'); - $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); - $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}-1'); - - $this->httpHelper->expects($this->at(0)) - ->method('post') - ->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $openShares[0]['remote_id']), $this->anything()); - - // Accept the first share - $this->manager->acceptShare($openShares[0]['id']); - - // Check remaining shares - Accepted - $acceptedShares = self::invokePrivate($this->manager, 'getShares', [true]); - $this->assertCount(1, $acceptedShares); - $shareData1['accepted'] = true; - $this->assertExternalShareEntry($shareData1, $acceptedShares[0], 1, $shareData1['name']); - // Check remaining shares - Open - $openShares = $this->manager->getOpenShares(); - $this->assertCount(1, $openShares); - $this->assertExternalShareEntry($shareData2, $openShares[0], 2, '{{TemporaryMountPointName#' . $shareData2['name'] . '}}-1'); - - $this->setupMounts(); - $this->assertMount($shareData1['name']); - $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); - $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}-1'); - - // Add another share for "user" with the same name - $this->assertSame(null, call_user_func_array([$this->manager, 'addShare'], $shareData3)); - $openShares = $this->manager->getOpenShares(); - $this->assertCount(2, $openShares); - $this->assertExternalShareEntry($shareData2, $openShares[0], 2, '{{TemporaryMountPointName#' . $shareData2['name'] . '}}-1'); - // New share falls back to the original name (no "-\d", because the name is not taken) - $this->assertExternalShareEntry($shareData3, $openShares[1], 3, '{{TemporaryMountPointName#' . $shareData3['name'] . '}}'); - - $this->setupMounts(); - $this->assertMount($shareData1['name']); - $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); - $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}-1'); - - $this->httpHelper->expects($this->at(0)) - ->method('post') - ->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $openShares[1]['remote_id'] . '/decline'), $this->anything()); - - // Decline the third share - $this->manager->declineShare($openShares[1]['id']); - - $this->setupMounts(); - $this->assertMount($shareData1['name']); - $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); - $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}-1'); - - // Check remaining shares - Accepted - $acceptedShares = self::invokePrivate($this->manager, 'getShares', [true]); - $this->assertCount(1, $acceptedShares); - $shareData1['accepted'] = true; - $this->assertExternalShareEntry($shareData1, $acceptedShares[0], 1, $shareData1['name']); - // Check remaining shares - Open - $openShares = $this->manager->getOpenShares(); - $this->assertCount(1, $openShares); - $this->assertExternalShareEntry($shareData2, $openShares[0], 2, '{{TemporaryMountPointName#' . $shareData2['name'] . '}}-1'); - - $this->setupMounts(); - $this->assertMount($shareData1['name']); - $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); - $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}-1'); - - $this->httpHelper->expects($this->at(0)) - ->method('post') - ->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $openShares[0]['remote_id'] . '/decline'), $this->anything()); - $this->httpHelper->expects($this->at(1)) - ->method('post') - ->with($this->stringStartsWith('http://localhost/ocs/v1.php/cloud/shares/' . $acceptedShares[0]['remote_id'] . '/decline'), $this->anything()); - - $this->manager->removeUserShares($this->uid); - $this->assertEmpty(self::invokePrivate($this->manager, 'getShares', [null]), 'Asserting all shares for the user have been deleted'); - - $this->mountManager->clear(); - self::invokePrivate($this->manager, 'setupMounts'); - $this->assertNotMount($shareData1['name']); - $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}'); - $this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}-1'); - } - - /** - * @param array $expected - * @param array $actual - * @param int $share - * @param string $mountPoint - */ - protected function assertExternalShareEntry($expected, $actual, $share, $mountPoint) { - $this->assertEquals($expected['remote'], $actual['remote'], 'Asserting remote of a share #' . $share); - $this->assertEquals($expected['token'], $actual['share_token'], 'Asserting token of a share #' . $share); - $this->assertEquals($expected['name'], $actual['name'], 'Asserting name of a share #' . $share); - $this->assertEquals($expected['owner'], $actual['owner'], 'Asserting owner of a share #' . $share); - $this->assertEquals($expected['accepted'], (int) $actual['accepted'], 'Asserting accept of a share #' . $share); - $this->assertEquals($expected['user'], $actual['user'], 'Asserting user of a share #' . $share); - $this->assertEquals($mountPoint, $actual['mountpoint'], 'Asserting mountpoint of a share #' . $share); - } - - private function assertMount($mountPoint) { - $mountPoint = rtrim($mountPoint, '/'); - $mount = $this->mountManager->find($this->getFullPath($mountPoint)); - $this->assertInstanceOf('\OCA\Files_Sharing\External\Mount', $mount); - $this->assertInstanceOf('\OCP\Files\Mount\IMountPoint', $mount); - $this->assertEquals($this->getFullPath($mountPoint), rtrim($mount->getMountPoint(), '/')); - $storage = $mount->getStorage(); - $this->assertInstanceOf('\OCA\Files_Sharing\External\Storage', $storage); - } - - private function assertNotMount($mountPoint) { - $mountPoint = rtrim($mountPoint, '/'); - $mount = $this->mountManager->find($this->getFullPath($mountPoint)); - if ($mount) { - $this->assertInstanceOf('\OCP\Files\Mount\IMountPoint', $mount); - $this->assertNotEquals($this->getFullPath($mountPoint), rtrim($mount->getMountPoint(), '/')); - } else { - $this->assertNull($mount); - } - } - - private function getFullPath($path) { - return '/' . $this->uid . '/files' . $path; - } -} diff --git a/apps/files_sharing/tests/external/scannertest.php b/apps/files_sharing/tests/external/scannertest.php deleted file mode 100644 index f16e9952fce..00000000000 --- a/apps/files_sharing/tests/external/scannertest.php +++ /dev/null @@ -1,82 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\Tests\External; - -use OCA\Files_Sharing\External\Scanner; -use Test\TestCase; - -class ScannerTest extends TestCase { - /** @var \OCA\Files_Sharing\External\Scanner */ - protected $scanner; - /** @var \OCA\Files_Sharing\External\Storage|\PHPUnit_Framework_MockObject_MockObject */ - protected $storage; - /** @var \OC\Files\Cache\Cache|\PHPUnit_Framework_MockObject_MockObject */ - protected $cache; - - protected function setUp() { - parent::setUp(); - - $this->storage = $this->getMockBuilder('\OCA\Files_Sharing\External\Storage') - ->disableOriginalConstructor() - ->getMock(); - $this->cache = $this->getMockBuilder('\OC\Files\Cache\Cache') - ->disableOriginalConstructor() - ->getMock(); - $this->storage->expects($this->any()) - ->method('getCache') - ->willReturn($this->cache); - - $this->scanner = new Scanner($this->storage); - } - - public function testScanAll() { - $this->storage->expects($this->any()) - ->method('getShareInfo') - ->willReturn(['status' => 'success', 'data' => []]); - - // FIXME add real tests, we are currently only checking for - // Declaration of OCA\Files_Sharing\External\Scanner::*() should be - // compatible with OC\Files\Cache\Scanner::*() - $this->scanner->scanAll(); - $this->assertTrue(true); - } - - public function testScan() { - $this->storage->expects($this->any()) - ->method('getShareInfo') - ->willReturn(['status' => 'success', 'data' => []]); - - // FIXME add real tests, we are currently only checking for - // Declaration of OCA\Files_Sharing\External\Scanner::*() should be - // compatible with OC\Files\Cache\Scanner::*() - $this->scanner->scan('test', Scanner::SCAN_RECURSIVE); - $this->assertTrue(true); - } - - public function testScanFile() { - // FIXME add real tests, we are currently only checking for - // Declaration of OCA\Files_Sharing\External\Scanner::*() should be - // compatible with OC\Files\Cache\Scanner::*() - $this->scanner->scanFile('test', Scanner::SCAN_RECURSIVE); - $this->assertTrue(true); - } -} diff --git a/apps/files_sharing/tests/externalstorage.php b/apps/files_sharing/tests/externalstorage.php deleted file mode 100644 index 54cd7d1645c..00000000000 --- a/apps/files_sharing/tests/externalstorage.php +++ /dev/null @@ -1,95 +0,0 @@ - - * @author Morris Jobke - * @author Robin Appelman - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -/** - * Tests for the external Storage class for remote shares. - * - * @group DB - */ -class Test_Files_Sharing_External_Storage extends \Test\TestCase { - - function optionsProvider() { - return array( - array( - 'http://remoteserver:8080/owncloud', - 'http://remoteserver:8080/owncloud/public.php/webdav/', - ), - // extra slash - array( - 'http://remoteserver:8080/owncloud/', - 'http://remoteserver:8080/owncloud/public.php/webdav/', - ), - // extra path - array( - 'http://remoteserver:8080/myservices/owncloud/', - 'http://remoteserver:8080/myservices/owncloud/public.php/webdav/', - ), - // root path - array( - 'http://remoteserver:8080/', - 'http://remoteserver:8080/public.php/webdav/', - ), - // without port - array( - 'http://remoteserver/oc.test', - 'http://remoteserver/oc.test/public.php/webdav/', - ), - // https - array( - 'https://remoteserver/', - 'https://remoteserver/public.php/webdav/', - ), - ); - } - - /** - * @dataProvider optionsProvider - */ - public function testStorageMountOptions($inputUri, $baseUri) { - $certificateManager = \OC::$server->getCertificateManager(); - $storage = new TestSharingExternalStorage( - array( - 'remote' => $inputUri, - 'owner' => 'testOwner', - 'mountpoint' => 'remoteshare', - 'token' => 'abcdef', - 'password' => '', - 'manager' => null, - 'certificateManager' => $certificateManager - ) - ); - $this->assertEquals($baseUri, $storage->getBaseUri()); - } -} - -/** - * Dummy subclass to make it possible to access private members - */ -class TestSharingExternalStorage extends \OCA\Files_Sharing\External\Storage { - - public function getBaseUri() { - return $this->createBaseUri(); - } -} diff --git a/apps/files_sharing/tests/groupetagpropagation.php b/apps/files_sharing/tests/groupetagpropagation.php deleted file mode 100644 index aaa81135279..00000000000 --- a/apps/files_sharing/tests/groupetagpropagation.php +++ /dev/null @@ -1,122 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_sharing\Tests; - -use OC\Files\Filesystem; -use OC\Files\View; - -/** - * @group DB - * - * @package OCA\Files_sharing\Tests - */ -class GroupEtagPropagation extends PropagationTestCase { - /** - * "user1" creates /test, /test/sub and shares with group1 - * "user2" (in group1) reshares /test with group2 and reshared /test/sub with group3 - * "user3" (in group 2) - * "user4" (in group 3) - */ - protected function setUpShares() { - $this->fileIds[self::TEST_FILES_SHARING_API_USER1] = []; - $this->fileIds[self::TEST_FILES_SHARING_API_USER2] = []; - $this->fileIds[self::TEST_FILES_SHARING_API_USER3] = []; - $this->fileIds[self::TEST_FILES_SHARING_API_USER4] = []; - - $this->rootView = new View(''); - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - $view1 = new View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files'); - $view1->mkdir('/test/sub'); - - $this->share( - \OCP\Share::SHARE_TYPE_GROUP, - '/test', - self::TEST_FILES_SHARING_API_USER1, - 'group1', - \OCP\Constants::PERMISSION_ALL - ); - $this->fileIds[self::TEST_FILES_SHARING_API_USER1][''] = $view1->getFileInfo('')->getId(); - $this->fileIds[self::TEST_FILES_SHARING_API_USER1]['test'] = $view1->getFileInfo('test')->getId(); - $this->fileIds[self::TEST_FILES_SHARING_API_USER1]['test/sub'] = $view1->getFileInfo('test/sub')->getId(); - - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); - $view2 = new View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); - - $this->share( - \OCP\Share::SHARE_TYPE_GROUP, - '/test', - self::TEST_FILES_SHARING_API_USER2, - 'group2', - \OCP\Constants::PERMISSION_ALL - ); - $this->share( - \OCP\Share::SHARE_TYPE_GROUP, - '/test/sub', - self::TEST_FILES_SHARING_API_USER2, - 'group3', - \OCP\Constants::PERMISSION_ALL - ); - - $this->fileIds[self::TEST_FILES_SHARING_API_USER2][''] = $view2->getFileInfo('')->getId(); - $this->fileIds[self::TEST_FILES_SHARING_API_USER2]['test'] = $view2->getFileInfo('test')->getId(); - $this->fileIds[self::TEST_FILES_SHARING_API_USER2]['test/sub'] = $view2->getFileInfo('test/sub')->getId(); - - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER3); - $view3 = new View('/' . self::TEST_FILES_SHARING_API_USER3 . '/files'); - $this->fileIds[self::TEST_FILES_SHARING_API_USER3][''] = $view3->getFileInfo('')->getId(); - $this->fileIds[self::TEST_FILES_SHARING_API_USER3]['test'] = $view3->getFileInfo('test')->getId(); - $this->fileIds[self::TEST_FILES_SHARING_API_USER3]['test/sub'] = $view3->getFileInfo('test/sub')->getId(); - - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER4); - $view4 = new View('/' . self::TEST_FILES_SHARING_API_USER4 . '/files'); - $this->fileIds[self::TEST_FILES_SHARING_API_USER4][''] = $view4->getFileInfo('')->getId(); - $this->fileIds[self::TEST_FILES_SHARING_API_USER4]['sub'] = $view4->getFileInfo('sub')->getId(); - - foreach ($this->fileIds as $user => $ids) { - $this->loginAsUser($user); - foreach ($ids as $id) { - $path = $this->rootView->getPath($id); - $this->fileEtags[$id] = $this->rootView->getFileInfo($path)->getEtag(); - } - } - } - - public function testGroupReShareRecipientWrites() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER3); - - Filesystem::file_put_contents('/test/sub/file.txt', 'asd'); - - $this->assertEtagsChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - - $this->assertAllUnchanged(); - } - - public function testGroupReShareSubFolderRecipientWrites() { - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER4); - - Filesystem::file_put_contents('/sub/file.txt', 'asd'); - - $this->assertEtagsChanged([self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]); - - $this->assertAllUnchanged(); - } -} diff --git a/apps/files_sharing/tests/helper.php b/apps/files_sharing/tests/helper.php deleted file mode 100644 index 07f07f911cb..00000000000 --- a/apps/files_sharing/tests/helper.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @author Morris Jobke - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -use OCA\Files_sharing\Tests\TestCase; - -/** - * Class Test_Files_Sharing_Helper - * - * @group DB - */ -class Test_Files_Sharing_Helper extends TestCase { - - /** - * test set and get share folder - */ - function testSetGetShareFolder() { - $this->assertSame('/', \OCA\Files_Sharing\Helper::getShareFolder()); - - \OCA\Files_Sharing\Helper::setShareFolder('/Shared/Folder'); - - $sharedFolder = \OCA\Files_Sharing\Helper::getShareFolder(); - $this->assertSame('/Shared/Folder', \OCA\Files_Sharing\Helper::getShareFolder()); - $this->assertTrue(\OC\Files\Filesystem::is_dir($sharedFolder)); - - // cleanup - \OC::$server->getConfig()->deleteSystemValue('share_folder'); - - } - -} diff --git a/apps/files_sharing/tests/locking.php b/apps/files_sharing/tests/locking.php deleted file mode 100644 index 932afe006f9..00000000000 --- a/apps/files_sharing/tests/locking.php +++ /dev/null @@ -1,113 +0,0 @@ - - * @author Robin Appelman - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_sharing\Tests; - -use OC\Files\Filesystem; -use OC\Files\View; -use OCP\Lock\ILockingProvider; - -/** - * Class Locking - * - * @group DB - * - * @package OCA\Files_sharing\Tests - */ -class Locking extends TestCase { - /** - * @var \Test\Util\User\Dummy - */ - private $userBackend; - - private $ownerUid; - private $recipientUid; - - public function setUp() { - parent::setUp(); - - $this->userBackend = new \Test\Util\User\Dummy(); - \OC::$server->getUserManager()->registerBackend($this->userBackend); - - $this->ownerUid = $this->getUniqueID('owner_'); - $this->recipientUid = $this->getUniqueID('recipient_'); - $this->userBackend->createUser($this->ownerUid, ''); - $this->userBackend->createUser($this->recipientUid, ''); - - $this->loginAsUser($this->ownerUid); - Filesystem::mkdir('/foo'); - Filesystem::file_put_contents('/foo/bar.txt', 'asd'); - $fileId = Filesystem::getFileInfo('/foo/bar.txt')->getId(); - - $this->share( - \OCP\Share::SHARE_TYPE_USER, - '/foo/bar.txt', - $this->ownerUid, - $this->recipientUid, - \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE - ); - - $this->loginAsUser($this->recipientUid); - $this->assertTrue(Filesystem::file_exists('bar.txt')); - } - - public function tearDown() { - \OC::$server->getUserManager()->removeBackend($this->userBackend); - parent::tearDown(); - } - - /** - * @expectedException \OCP\Lock\LockedException - */ - public function testLockAsRecipient() { - $this->loginAsUser($this->ownerUid); - - Filesystem::initMountPoints($this->recipientUid); - $recipientView = new View('/' . $this->recipientUid . '/files'); - $recipientView->lockFile('bar.txt', ILockingProvider::LOCK_EXCLUSIVE); - - Filesystem::rename('/foo', '/asd'); - } - - public function testUnLockAsRecipient() { - $this->loginAsUser($this->ownerUid); - - Filesystem::initMountPoints($this->recipientUid); - $recipientView = new View('/' . $this->recipientUid . '/files'); - $recipientView->lockFile('bar.txt', ILockingProvider::LOCK_EXCLUSIVE); - $recipientView->unlockFile('bar.txt', ILockingProvider::LOCK_EXCLUSIVE); - - $this->assertTrue(Filesystem::rename('/foo', '/asd')); - } - - public function testChangeLock() { - - Filesystem::initMountPoints($this->recipientUid); - $recipientView = new View('/' . $this->recipientUid . '/files'); - $recipientView->lockFile('bar.txt', ILockingProvider::LOCK_SHARED); - $recipientView->changeLock('bar.txt', ILockingProvider::LOCK_EXCLUSIVE); - $recipientView->unlockFile('bar.txt', ILockingProvider::LOCK_EXCLUSIVE); - - $this->assertTrue(true); - } -} diff --git a/apps/files_sharing/tests/middleware/sharingcheckmiddleware.php b/apps/files_sharing/tests/middleware/sharingcheckmiddleware.php deleted file mode 100644 index e80be772a92..00000000000 --- a/apps/files_sharing/tests/middleware/sharingcheckmiddleware.php +++ /dev/null @@ -1,287 +0,0 @@ - - * @author Morris Jobke - * @author Roeland Jago Douma - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\Middleware; -use OCP\AppFramework\Http\NotFoundResponse; -use OCP\Files\NotFoundException; -use OCP\AppFramework\Utility\IControllerMethodReflector; -use OCA\Files_Sharing\Exceptions\S2SException; -use OCP\AppFramework\Http\JSONResponse; - -/** - * @package OCA\Files_Sharing\Middleware\SharingCheckMiddleware - */ -class SharingCheckMiddlewareTest extends \Test\TestCase { - - /** @var \OCP\IConfig */ - private $config; - /** @var \OCP\App\IAppManager */ - private $appManager; - /** @var SharingCheckMiddleware */ - private $sharingCheckMiddleware; - /** @var \OCP\AppFramework\Controller */ - private $controllerMock; - /** @var IControllerMethodReflector */ - private $reflector; - - protected function setUp() { - $this->config = $this->getMockBuilder('\OCP\IConfig') - ->disableOriginalConstructor()->getMock(); - $this->appManager = $this->getMockBuilder('\OCP\App\IAppManager') - ->disableOriginalConstructor()->getMock(); - $this->controllerMock = $this->getMockBuilder('\OCP\AppFramework\Controller') - ->disableOriginalConstructor()->getMock(); - $this->reflector = $this->getMockBuilder('\OCP\AppFramework\Utility\IControllerMethodReflector') - ->disableOriginalConstructor()->getMock(); - - $this->sharingCheckMiddleware = new SharingCheckMiddleware( - 'files_sharing', - $this->config, - $this->appManager, - $this->reflector); - } - - public function testIsSharingEnabledWithAppEnabled() { - $this->appManager - ->expects($this->once()) - ->method('isEnabledForUser') - ->with('files_sharing') - ->will($this->returnValue(true)); - - $this->assertTrue(self::invokePrivate($this->sharingCheckMiddleware, 'isSharingEnabled')); - } - - public function testIsSharingEnabledWithAppDisabled() { - $this->appManager - ->expects($this->once()) - ->method('isEnabledForUser') - ->with('files_sharing') - ->will($this->returnValue(false)); - - $this->assertFalse(self::invokePrivate($this->sharingCheckMiddleware, 'isSharingEnabled')); - } - - public function testIsLinkSharingEnabledWithEverythinEnabled() { - $this->config - ->expects($this->at(0)) - ->method('getAppValue') - ->with('core', 'shareapi_enabled', 'yes') - ->will($this->returnValue('yes')); - - $this->config - ->expects($this->at(1)) - ->method('getAppValue') - ->with('core', 'shareapi_allow_links', 'yes') - ->will($this->returnValue('yes')); - - $this->assertTrue(self::invokePrivate($this->sharingCheckMiddleware, 'isLinkSharingEnabled')); - } - - - public function testIsLinkSharingEnabledWithLinkSharingDisabled() { - $this->config - ->expects($this->at(0)) - ->method('getAppValue') - ->with('core', 'shareapi_enabled', 'yes') - ->will($this->returnValue('yes')); - - $this->config - ->expects($this->at(1)) - ->method('getAppValue') - ->with('core', 'shareapi_allow_links', 'yes') - ->will($this->returnValue('no')); - - $this->assertFalse(self::invokePrivate($this->sharingCheckMiddleware, 'isLinkSharingEnabled')); - } - - public function testIsLinkSharingEnabledWithSharingAPIDisabled() { - $this->config - ->expects($this->once()) - ->method('getAppValue') - ->with('core', 'shareapi_enabled', 'yes') - ->will($this->returnValue('no')); - - $this->assertFalse(self::invokePrivate($this->sharingCheckMiddleware, 'isLinkSharingEnabled')); - } - - public function externalSharesChecksDataProvider() { - - $data = []; - - foreach ([false, true] as $annIn) { - foreach ([false, true] as $annOut) { - foreach ([false, true] as $confIn) { - foreach ([false, true] as $confOut) { - - $res = true; - if (!$annIn && !$confIn) { - $res = false; - } elseif (!$annOut && !$confOut) { - $res = false; - } - - $d = [ - [ - ['NoIncomingFederatedSharingRequired', $annIn], - ['NoOutgoingFederatedSharingRequired', $annOut], - ], - [ - ['files_sharing', 'incoming_server2server_share_enabled', 'yes', $confIn ? 'yes' : 'no'], - ['files_sharing', 'outgoing_server2server_share_enabled', 'yes', $confOut ? 'yes' : 'no'], - ], - $res - ]; - - $data[] = $d; - } - } - } - } - - return $data; - } - - /** - * @dataProvider externalSharesChecksDataProvider - */ - public function testExternalSharesChecks($annotations, $config, $expectedResult) { - $this->reflector - ->expects($this->atLeastOnce()) - ->method('hasAnnotation') - ->will($this->returnValueMap($annotations)); - - $this->config - ->method('getAppValue') - ->will($this->returnValueMap($config)); - - $this->assertEquals($expectedResult, self::invokePrivate($this->sharingCheckMiddleware, 'externalSharesChecks')); - } - - /** - * @dataProvider externalSharesChecksDataProvider - */ - public function testBeforeControllerWithExternalShareControllerWithSharingEnabled($annotations, $config, $noException) { - $this->appManager - ->expects($this->once()) - ->method('isEnabledForUser') - ->with('files_sharing') - ->will($this->returnValue(true)); - - $this->reflector - ->expects($this->atLeastOnce()) - ->method('hasAnnotation') - ->will($this->returnValueMap($annotations)); - - $this->config - ->method('getAppValue') - ->will($this->returnValueMap($config)); - - $controller = $this->getMockBuilder('\OCA\Files_Sharing\Controllers\ExternalSharesController') - ->disableOriginalConstructor()->getMock(); - - $exceptionThrown = false; - - try { - $this->sharingCheckMiddleware->beforeController($controller, 'myMethod'); - } catch (\OCA\Files_Sharing\Exceptions\S2SException $exception) { - $exceptionThrown = true; - } - - $this->assertNotEquals($noException, $exceptionThrown); - } - - public function testBeforeControllerWithShareControllerWithSharingEnabled() { - $this->appManager - ->expects($this->once()) - ->method('isEnabledForUser') - ->with('files_sharing') - ->will($this->returnValue(true)); - - $this->config - ->expects($this->at(0)) - ->method('getAppValue') - ->with('core', 'shareapi_enabled', 'yes') - ->will($this->returnValue('yes')); - - $this->config - ->expects($this->at(1)) - ->method('getAppValue') - ->with('core', 'shareapi_allow_links', 'yes') - ->will($this->returnValue('yes')); - - $controller = $this->getMockBuilder('\OCA\Files_Sharing\Controllers\ShareController') - ->disableOriginalConstructor()->getMock(); - - $this->sharingCheckMiddleware->beforeController($controller, 'myMethod'); - } - - /** - * @expectedException \OCP\Files\NotFoundException - * @expectedExceptionMessage Link sharing is disabled - */ - public function testBeforeControllerWithShareControllerWithSharingEnabledAPIDisabled() { - $this->appManager - ->expects($this->once()) - ->method('isEnabledForUser') - ->with('files_sharing') - ->will($this->returnValue(true)); - - $controller = $this->getMockBuilder('\OCA\Files_Sharing\Controllers\ShareController') - ->disableOriginalConstructor()->getMock(); - - $this->sharingCheckMiddleware->beforeController($controller, 'myMethod'); - } - - /** - * @expectedException \OCP\Files\NotFoundException - * @expectedExceptionMessage Sharing is disabled. - */ - public function testBeforeControllerWithSharingDisabled() { - $this->appManager - ->expects($this->once()) - ->method('isEnabledForUser') - ->with('files_sharing') - ->will($this->returnValue(false)); - - $this->sharingCheckMiddleware->beforeController($this->controllerMock, 'myMethod'); - } - - /** - * @expectedException \Exception - * @expectedExceptionMessage My Exception message - */ - public function testAfterExceptionWithRegularException() { - $this->sharingCheckMiddleware->afterException($this->controllerMock, 'myMethod', new \Exception('My Exception message')); - } - - public function testAfterExceptionWithNotFoundException() { - $this->assertEquals(new NotFoundResponse(), $this->sharingCheckMiddleware->afterException($this->controllerMock, 'myMethod', new NotFoundException('My Exception message'))); - } - - public function testAfterExceptionWithS2SException() { - $this->assertEquals(new JSONResponse('My Exception message', 405), $this->sharingCheckMiddleware->afterException($this->controllerMock, 'myMethod', new S2SException('My Exception message'))); - } - - -} diff --git a/apps/files_sharing/tests/migrationtest.php b/apps/files_sharing/tests/migrationtest.php deleted file mode 100644 index 82e6f47addb..00000000000 --- a/apps/files_sharing/tests/migrationtest.php +++ /dev/null @@ -1,351 +0,0 @@ - - * @author Morris Jobke - * @author Roeland Jago Douma - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - - -use OCA\Files_Sharing\Tests\TestCase; -use OCA\Files_Sharing\Migration; - -/** - * Class MigrationTest - * - * @group DB - */ -class MigrationTest extends TestCase { - - /** @var \OCP\IDBConnection */ - private $connection; - - /** @var Migration */ - private $migration; - - private $table = 'share'; - - public function setUp() { - parent::setUp(); - - $this->connection = \OC::$server->getDatabaseConnection(); - $this->migration = new Migration($this->connection); - - $this->cleanDB(); - } - - public function tearDown() { - parent::tearDown(); - $this->cleanDB(); - } - - private function cleanDB() { - $query = $this->connection->getQueryBuilder(); - $query->delete($this->table)->execute(); - } - - public function addDummyValues() { - $query = $this->connection->getQueryBuilder(); - $query->insert($this->table) - ->values( - array( - 'share_type' => $query->createParameter('share_type'), - 'share_with' => $query->createParameter('share_with'), - 'uid_owner' => $query->createParameter('uid_owner'), - 'uid_initiator' => $query->createParameter('uid_initiator'), - 'parent' => $query->createParameter('parent'), - 'item_type' => $query->createParameter('item_type'), - 'item_source' => $query->createParameter('item_source'), - 'item_target' => $query->createParameter('item_target'), - 'file_source' => $query->createParameter('file_source'), - 'file_target' => $query->createParameter('file_target'), - 'permissions' => $query->createParameter('permissions'), - 'stime' => $query->createParameter('stime'), - ) - ); - // shared contact, shouldn't be modified - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_CONTACT) - ->setParameter('share_with', 'user1') - ->setParameter('uid_owner', 'owner1') - ->setParameter('uid_initiator', '') - ->setParameter('parent', null) - ->setParameter('item_type', 'contact') - ->setParameter('item_source', '2') - ->setParameter('item_target', '/2') - ->setParameter('file_source', null) - ->setParameter('file_target', null) - ->setParameter('permissions', 31) - ->setParameter('stime', time()); - $this->assertSame(1, - $query->execute() - ); - // shared calendar, shouldn't be modified - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) - ->setParameter('share_with', 'user1') - ->setParameter('uid_owner', 'owner1') - ->setParameter('uid_initiator', '') - ->setParameter('parent', null) - ->setParameter('item_type', 'calendar') - ->setParameter('item_source', '2') - ->setParameter('item_target', '/2') - ->setParameter('file_source', null) - ->setParameter('file_target', null) - ->setParameter('permissions', 31) - ->setParameter('stime', time()); - $this->assertSame(1, - $query->execute() - ); - // single user share, shouldn't be modified - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) - ->setParameter('share_with', 'user1') - ->setParameter('uid_owner', 'owner1') - ->setParameter('uid_initiator', '') - ->setParameter('parent', null) - ->setParameter('item_type', 'file') - ->setParameter('item_source', '2') - ->setParameter('item_target', '/2') - ->setParameter('file_source', 2) - ->setParameter('file_target', '/foo') - ->setParameter('permissions', 31) - ->setParameter('stime', time()); - $this->assertSame(1, - $query->execute() - ); - // single group share, shouldn't be modified - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_GROUP) - ->setParameter('share_with', 'group1') - ->setParameter('uid_owner', 'owner1') - ->setParameter('uid_initiator', '') - ->setParameter('parent', null) - ->setParameter('item_type', 'file') - ->setParameter('item_source', '2') - ->setParameter('item_target', '/2') - ->setParameter('file_source', 2) - ->setParameter('file_target', '/foo') - ->setParameter('permissions', 31) - ->setParameter('stime', time()); - $this->assertSame(1, - $query->execute() - ); - $parent = $query->getLastInsertId(); - // unique target for group share, shouldn't be modified - $query->setParameter('share_type', 2) - ->setParameter('share_with', 'group1') - ->setParameter('uid_owner', 'owner1') - ->setParameter('uid_initiator', '') - ->setParameter('parent', $parent) - ->setParameter('item_type', 'file') - ->setParameter('item_source', '2') - ->setParameter('item_target', '/2') - ->setParameter('file_source', 2) - ->setParameter('file_target', '/foo renamed') - ->setParameter('permissions', 31) - ->setParameter('stime', time()); - $this->assertSame(1, - $query->execute() - ); - // first user share, shouldn't be modified - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) - ->setParameter('share_with', 'user1') - ->setParameter('uid_owner', 'owner2') - ->setParameter('uid_initiator', '') - ->setParameter('parent', null) - ->setParameter('item_type', 'file') - ->setParameter('item_source', '2') - ->setParameter('item_target', '/2') - ->setParameter('file_source', 2) - ->setParameter('file_target', '/foobar') - ->setParameter('permissions', 31) - ->setParameter('stime', time()); - $this->assertSame(1, - $query->execute() - ); - $parent = $query->getLastInsertId(); - // first re-share, should be attached to the first user share after migration - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) - ->setParameter('share_with', 'user2') - ->setParameter('uid_owner', 'user1') - ->setParameter('uid_initiator', '') - ->setParameter('parent', $parent) - ->setParameter('item_type', 'file') - ->setParameter('item_source', '2') - ->setParameter('item_target', '/2') - ->setParameter('file_source', 2) - ->setParameter('file_target', '/foobar') - ->setParameter('permissions', 31) - ->setParameter('stime', time()); - $this->assertSame(1, - $query->execute() - ); - $parent = $query->getLastInsertId(); - // second re-share, should be attached to the first user share after migration - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) - ->setParameter('share_with', 'user3') - ->setParameter('uid_owner', 'user2') - ->setParameter('uid_initiator', '') - ->setParameter('parent', $parent) - ->setParameter('item_type', 'file') - ->setParameter('item_source', '2') - ->setParameter('item_target', '/2') - ->setParameter('file_source', 2) - ->setParameter('file_target', '/foobar') - ->setParameter('permissions', 31) - ->setParameter('stime', time()); - $this->assertSame(1, - $query->execute() - ); - $parent = $query->getLastInsertId(); - // third re-share, should be attached to the first user share after migration - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_REMOTE) - ->setParameter('share_with', 'user@server.com') - ->setParameter('uid_owner', 'user3') - ->setParameter('uid_initiator', '') - ->setParameter('parent', $parent) - ->setParameter('item_type', 'file') - ->setParameter('item_source', '2') - ->setParameter('item_target', '/2') - ->setParameter('file_source', 2) - ->setParameter('file_target', '/foobar') - ->setParameter('permissions', 31) - ->setParameter('stime', time()); - $this->assertSame(1, - $query->execute() - ); - - // Link reshare should keep its parent - $query->setParameter('share_type', \OCP\Share::SHARE_TYPE_LINK) - ->setParameter('share_with', null) - ->setParameter('uid_owner', 'user3') - ->setParameter('uid_initiator', '') - ->setParameter('parent', $parent) - ->setParameter('item_type', 'file') - ->setParameter('item_source', '2') - ->setParameter('item_target', '/2') - ->setParameter('file_source', 2) - ->setParameter('file_target', '/foobar') - ->setParameter('permissions', 31) - ->setParameter('stime', time()); - $this->assertSame(1, - $query->execute() - ); - } - - public function testRemoveReShares() { - $this->addDummyValues(); - $this->migration->removeReShares(); - $this->verifyResult(); - } - - public function verifyResult() { - $query = $this->connection->getQueryBuilder(); - $query->select('*')->from($this->table)->orderBy('id'); - $result = $query->execute()->fetchAll(); - $this->assertSame(10, count($result)); - - // shares which shouldn't be modified - for ($i = 0; $i < 4; $i++) { - $this->assertSame('owner1', $result[$i]['uid_owner']); - $this->assertEmpty($result[$i]['uid_initiator']); - $this->assertNull($result[$i]['parent']); - } - // group share with unique target - $this->assertSame('owner1', $result[4]['uid_owner']); - $this->assertEmpty($result[4]['uid_initiator']); - $this->assertNotEmpty($result[4]['parent']); - // initial user share which was re-shared - $this->assertSame('owner2', $result[5]['uid_owner']); - $this->assertEmpty($result[5]['uid_initiator']); - $this->assertNull($result[5]['parent']); - // flatted re-shares - for($i = 6; $i < 9; $i++) { - $this->assertSame('owner2', $result[$i]['uid_owner']); - $user = 'user' . ($i - 5); - $this->assertSame($user, $result[$i]['uid_initiator']); - $this->assertNull($result[$i]['parent']); - } - - /* - * The link share is flattend but has an owner to avoid invisible shares - * see: https://github.com/owncloud/core/pull/22317 - */ - $this->assertSame('owner2', $result[9]['uid_owner']); - $this->assertSame('user3', $result[9]['uid_initiator']); - $this->assertSame($result[7]['id'], $result[9]['parent']); - } - - public function test1001DeepReshares() { - $parent = null; - for ($i = 0; $i < 1001; $i++) { - $query = $this->connection->getQueryBuilder(); - $query->insert($this->table) - ->values( - [ - 'share_type' => $query->createParameter('share_type'), - 'share_with' => $query->createParameter('share_with'), - 'uid_owner' => $query->createParameter('uid_owner'), - 'uid_initiator' => $query->createParameter('uid_initiator'), - 'parent' => $query->createParameter('parent'), - 'item_type' => $query->createParameter('item_type'), - 'item_source' => $query->createParameter('item_source'), - 'item_target' => $query->createParameter('item_target'), - 'file_source' => $query->createParameter('file_source'), - 'file_target' => $query->createParameter('file_target'), - 'permissions' => $query->createParameter('permissions'), - 'stime' => $query->createParameter('stime'), - ] - ) - ->setParameter('share_type', \OCP\Share::SHARE_TYPE_USER) - ->setParameter('share_with', 'user'.($i+1)) - ->setParameter('uid_owner', 'user'.($i)) - ->setParameter('uid_initiator', null) - ->setParameter('parent', $parent) - ->setParameter('item_type', 'file') - ->setParameter('item_source', '2') - ->setParameter('item_target', '/2') - ->setParameter('file_source', 2) - ->setParameter('file_target', '/foobar') - ->setParameter('permissions', 31) - ->setParameter('stime', time()); - - $this->assertSame(1, $query->execute()); - $parent = $query->getLastInsertId(); - } - - $this->migration->removeReShares(); - $this->migration->updateInitiatorInfo(); - - $qb = $this->connection->getQueryBuilder(); - - $stmt = $qb->select('id', 'share_with', 'uid_owner', 'uid_initiator', 'parent') - ->from('share') - ->orderBy('id', 'asc') - ->execute(); - - $i = 0; - while($share = $stmt->fetch()) { - $this->assertEquals('user'.($i+1), $share['share_with']); - $this->assertEquals('user' . ($i), $share['uid_initiator']); - $this->assertEquals('user0', $share['uid_owner']); - $this->assertEquals(null, $share['parent']); - $i++; - } - $stmt->closeCursor(); - $this->assertEquals(1001, $i); - } -} diff --git a/apps/files_sharing/tests/permissions.php b/apps/files_sharing/tests/permissions.php deleted file mode 100644 index c1568ceab0a..00000000000 --- a/apps/files_sharing/tests/permissions.php +++ /dev/null @@ -1,158 +0,0 @@ - - * @author Joas Schilling - * @author Robin Appelman - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -use OC\Files\Cache\Cache; -use OC\Files\Storage\Storage; -use OC\Files\View; - -/** - * Class Test_Files_Sharing_Permissions - * - * @group DB - */ -class Test_Files_Sharing_Permissions extends OCA\Files_sharing\Tests\TestCase { - - /** @var Storage */ - private $sharedStorageRestrictedShare; - - /** @var Storage */ - private $sharedCacheRestrictedShare; - - /** @var View */ - private $secondView; - - /** @var Storage */ - private $ownerStorage; - - /** @var Storage */ - private $sharedStorage; - - /** @var Cache */ - private $sharedCache; - - /** @var Cache */ - private $ownerCache; - - protected function setUp() { - parent::setUp(); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - - // prepare user1's dir structure - $textData = "dummy file data\n"; - $this->view->mkdir('container'); - $this->view->mkdir('container/shareddir'); - $this->view->mkdir('container/shareddir/subdir'); - $this->view->mkdir('container/shareddirrestricted'); - $this->view->mkdir('container/shareddirrestricted/subdir'); - $this->view->file_put_contents('container/shareddir/textfile.txt', $textData); - $this->view->file_put_contents('container/shareddirrestricted/textfile1.txt', $textData); - - list($this->ownerStorage, $internalPath) = $this->view->resolvePath(''); - $this->ownerCache = $this->ownerStorage->getCache(); - $this->ownerStorage->getScanner()->scan(''); - - // share "shareddir" with user2 - $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1); - - $node = $rootFolder->get('container/shareddir'); - $share = $this->shareManager->newShare(); - $share->setNode($node) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); - $this->shareManager->createShare($share); - - $node = $rootFolder->get('container/shareddirrestricted'); - $share = $this->shareManager->newShare(); - $share->setNode($node) - ->setShareType(\OCP\Share::SHARE_TYPE_USER) - ->setSharedWith(self::TEST_FILES_SHARING_API_USER2) - ->setSharedBy(self::TEST_FILES_SHARING_API_USER1) - ->setPermissions(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE); - $this->shareManager->createShare($share); - - // login as user2 - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - - // retrieve the shared storage - $this->secondView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2); - list($this->sharedStorage, $internalPath) = $this->secondView->resolvePath('files/shareddir'); - list($this->sharedStorageRestrictedShare, $internalPath) = $this->secondView->resolvePath('files/shareddirrestricted'); - $this->sharedCache = $this->sharedStorage->getCache(); - $this->sharedCacheRestrictedShare = $this->sharedStorageRestrictedShare->getCache(); - } - - protected function tearDown() { - if ($this->sharedCache) { - $this->sharedCache->clear(); - } - - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - - $shares = $this->shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER1, \OCP\Share::SHARE_TYPE_USER); - foreach ($shares as $share) { - $this->shareManager->deleteShare($share); - } - - $this->view->deleteAll('container'); - - $this->ownerCache->clear(); - - parent::tearDown(); - } - - /** - * Test that the permissions of shared directory are returned correctly - */ - function testGetPermissions() { - $sharedDirPerms = $this->sharedStorage->getPermissions('shareddir'); - $this->assertEquals(31, $sharedDirPerms); - $sharedDirPerms = $this->sharedStorage->getPermissions('shareddir/textfile.txt'); - $this->assertEquals(31, $sharedDirPerms); - $sharedDirRestrictedPerms = $this->sharedStorageRestrictedShare->getPermissions('shareddirrestricted'); - $this->assertEquals(7, $sharedDirRestrictedPerms); - $sharedDirRestrictedPerms = $this->sharedStorageRestrictedShare->getPermissions('shareddirrestricted/textfile.txt'); - $this->assertEquals(7, $sharedDirRestrictedPerms); - } - - /** - * Test that the permissions of shared directory are returned correctly - */ - function testGetDirectoryPermissions() { - $contents = $this->secondView->getDirectoryContent('files/shareddir'); - $this->assertEquals('subdir', $contents[0]['name']); - $this->assertEquals(31, $contents[0]['permissions']); - $this->assertEquals('textfile.txt', $contents[1]['name']); - // 27 is correct because create is reserved to folders only - requires more unit tests overall to ensure this - $this->assertEquals(27, $contents[1]['permissions']); - $contents = $this->secondView->getDirectoryContent('files/shareddirrestricted'); - $this->assertEquals('subdir', $contents[0]['name']); - $this->assertEquals(7, $contents[0]['permissions']); - $this->assertEquals('textfile1.txt', $contents[1]['name']); - // 3 is correct because create is reserved to folders only - $this->assertEquals(3, $contents[1]['permissions']); - } -} diff --git a/apps/files_sharing/tests/propagationtestcase.php b/apps/files_sharing/tests/propagationtestcase.php deleted file mode 100644 index 159a7b859aa..00000000000 --- a/apps/files_sharing/tests/propagationtestcase.php +++ /dev/null @@ -1,103 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_sharing\Tests; - -abstract class PropagationTestCase extends TestCase { - /** - * @var \OC\Files\View - */ - protected $rootView; - protected $fileIds = []; // [$user=>[$path=>$id]] - protected $fileEtags = []; // [$id=>$etag] - - public static function setUpBeforeClass() { - parent::setUpBeforeClass(); - \OCA\Files_Sharing\Helper::registerHooks(); - } - - protected function setUp() { - parent::setUp(); - $this->setUpShares(); - } - - protected function tearDown() { - \OC_Hook::clear('OC_Filesystem', 'post_write'); - \OC_Hook::clear('OC_Filesystem', 'post_delete'); - \OC_Hook::clear('OC_Filesystem', 'post_rename'); - \OC_Hook::clear('OCP\Share', 'post_update_permissions'); - parent::tearDown(); - } - - abstract protected function setUpShares(); - - /** - * @param string[] $users - * @param string $subPath - */ - protected function assertEtagsChanged($users, $subPath = '') { - $oldUser = \OC::$server->getUserSession()->getUser(); - foreach ($users as $user) { - $this->loginAsUser($user); - $id = $this->fileIds[$user][$subPath]; - $path = $this->rootView->getPath($id); - $etag = $this->rootView->getFileInfo($path)->getEtag(); - $this->assertNotEquals($this->fileEtags[$id], $etag, 'Failed asserting that the etag for "' . $subPath . '" of user ' . $user . ' has changed'); - $this->fileEtags[$id] = $etag; - } - $this->loginAsUser($oldUser->getUID()); - } - - /** - * @param string[] $users - * @param string $subPath - */ - protected function assertEtagsNotChanged($users, $subPath = '') { - $oldUser = \OC::$server->getUserSession()->getUser(); - foreach ($users as $user) { - $this->loginAsUser($user); - $id = $this->fileIds[$user][$subPath]; - $path = $this->rootView->getPath($id); - $etag = $this->rootView->getFileInfo($path)->getEtag(); - $this->assertEquals($this->fileEtags[$id], $etag, 'Failed asserting that the etag for "' . $subPath . '" of user ' . $user . ' has not changed'); - $this->fileEtags[$id] = $etag; - } - $this->loginAsUser($oldUser->getUID()); - } - - /** - * Assert that the etags for the root, /sub1 and /sub1/sub2 have changed - * - * @param string[] $users - */ - protected function assertEtagsForFoldersChanged($users) { - $this->assertEtagsChanged($users); - - $this->assertEtagsChanged($users, 'sub1'); - $this->assertEtagsChanged($users, 'sub1/sub2'); - } - - protected function assertAllUnchanged() { - $users = [self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER4]; - $this->assertEtagsNotChanged($users); - } -} diff --git a/apps/files_sharing/tests/share.php b/apps/files_sharing/tests/share.php deleted file mode 100644 index 7707cca190f..00000000000 --- a/apps/files_sharing/tests/share.php +++ /dev/null @@ -1,249 +0,0 @@ - - * @author Joas Schilling - * @author Morris Jobke - * @author Robin Appelman - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -use OCA\Files\Share; - -/** - * Class Test_Files_Sharing - * - * @group DB - */ -class Test_Files_Sharing extends OCA\Files_sharing\Tests\TestCase { - - const TEST_FOLDER_NAME = '/folder_share_api_test'; - - private static $tempStorage; - - protected function setUp() { - parent::setUp(); - - $this->folder = self::TEST_FOLDER_NAME; - $this->subfolder = '/subfolder_share_api_test'; - $this->subsubfolder = '/subsubfolder_share_api_test'; - - $this->filename = '/share-api-test.txt'; - - // save file with content - $this->view->file_put_contents($this->filename, $this->data); - $this->view->mkdir($this->folder); - $this->view->mkdir($this->folder . $this->subfolder); - $this->view->mkdir($this->folder . $this->subfolder . $this->subsubfolder); - $this->view->file_put_contents($this->folder.$this->filename, $this->data); - $this->view->file_put_contents($this->folder . $this->subfolder . $this->filename, $this->data); - } - - protected function tearDown() { - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - $this->view->unlink($this->filename); - $this->view->deleteAll($this->folder); - - self::$tempStorage = null; - - // clear database table - $query = \OCP\DB::prepare('DELETE FROM `*PREFIX*share`'); - $query->execute(); - - parent::tearDown(); - } - - public function testUnshareFromSelf() { - - \OC_Group::createGroup('testGroup'); - \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup'); - \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup'); - - $share1 = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->filename, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE - ); - - $share2 = $this->share( - \OCP\Share::SHARE_TYPE_GROUP, - $this->filename, - self::TEST_FILES_SHARING_API_USER1, - 'testGroup', - \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER3); - $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - \OC\Files\Filesystem::unlink($this->filename); - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - // both group share and user share should be gone - $this->assertFalse(\OC\Files\Filesystem::file_exists($this->filename)); - - // for user3 nothing should change - self::loginHelper(self::TEST_FILES_SHARING_API_USER3); - $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); - - $this->shareManager->deleteShare($share1); - $this->shareManager->deleteShare($share2); - } - - /** - * @param OC\Files\FileInfo[] $content - * @param string[] $expected - */ - public function verifyDirContent($content, $expected) { - foreach ($content as $c) { - if (!in_array($c['name'], $expected)) { - $this->assertTrue(false, "folder should only contain '" . implode(',', $expected) . "', found: " .$c['name']); - } - } - } - - public function testShareWithDifferentShareFolder() { - - $fileinfo = $this->view->getFileInfo($this->filename); - $folderinfo = $this->view->getFileInfo($this->folder); - - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->filename, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE - ); - - \OCA\Files_Sharing\Helper::setShareFolder('/Shared/subfolder'); - - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - - $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); - $this->assertTrue(\OC\Files\Filesystem::file_exists('/Shared/subfolder/' . $this->folder)); - - //cleanup - \OC::$server->getConfig()->deleteSystemValue('share_folder'); - } - - public function testShareWithGroupUniqueName() { - $this->loginHelper(self::TEST_FILES_SHARING_API_USER1); - \OC\Files\Filesystem::file_put_contents('test.txt', 'test'); - - $share = $this->share( - \OCP\Share::SHARE_TYPE_GROUP, - 'test.txt', - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_GROUP1, - \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE - ); - - $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); - - $shares = $this->shareManager->getSharedWith(self::TEST_FILES_SHARING_API_USER2, \OCP\Share::SHARE_TYPE_GROUP); - $share = $shares[0]; - $this->assertSame('/test.txt' ,$share->getTarget()); - $this->assertSame(19, $share->getPermissions()); - - \OC\Files\Filesystem::rename('test.txt', 'new test.txt'); - - $shares = $this->shareManager->getSharedWith(self::TEST_FILES_SHARING_API_USER2, \OCP\Share::SHARE_TYPE_GROUP); - $share = $shares[0]; - $this->assertSame('/new test.txt' ,$share->getTarget()); - $this->assertSame(19, $share->getPermissions()); - - $share->setPermissions(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE); - $this->shareManager->updateShare($share); - - $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); - $shares = $this->shareManager->getSharedWith(self::TEST_FILES_SHARING_API_USER2, \OCP\Share::SHARE_TYPE_GROUP); - $share = $shares[0]; - - $this->assertSame('/new test.txt' ,$share->getTarget()); - $this->assertSame(3, $share->getPermissions()); - } - - /** - * shared files should never have delete permissions - * @dataProvider dataProviderTestFileSharePermissions - */ - public function testFileSharePermissions($permission, $expectedvalid) { - - $pass = true; - try { - $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->filename, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - $permission - ); - } catch (\Exception $e) { - $pass = false; - } - - $this->assertEquals($expectedvalid, $pass); - } - - public function dataProviderTestFileSharePermissions() { - $permission1 = \OCP\Constants::PERMISSION_ALL; - $permission3 = \OCP\Constants::PERMISSION_READ; - $permission4 = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE; - $permission5 = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_DELETE; - $permission6 = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; - - return array( - array($permission1, false), - array($permission3, true), - array($permission4, true), - array($permission5, false), - array($permission6, false), - ); - } - - public function testFileOwner() { - - $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->filename, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_READ - ); - - $this->loginHelper(\Test_Files_Sharing::TEST_FILES_SHARING_API_USER2); - - $info = \OC\Files\Filesystem::getFileInfo($this->filename); - - $this->assertSame(\Test_Files_Sharing::TEST_FILES_SHARING_API_USER1, $info->getOwner()->getUID()); - } -} diff --git a/apps/files_sharing/tests/sharedmount.php b/apps/files_sharing/tests/sharedmount.php deleted file mode 100644 index 48040ab8dc9..00000000000 --- a/apps/files_sharing/tests/sharedmount.php +++ /dev/null @@ -1,434 +0,0 @@ - - * @author Joas Schilling - * @author Morris Jobke - * @author Robin Appelman - * @author Roeland Jago Douma - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -/** - * Class Test_Files_Sharing_Api - * - * @group DB - */ -class Test_Files_Sharing_Mount extends OCA\Files_sharing\Tests\TestCase { - - protected function setUp() { - parent::setUp(); - - $this->folder = '/folder_share_storage_test'; - - $this->filename = '/share-api-storage.txt'; - - - $this->view->mkdir($this->folder); - - // save file with content - $this->view->file_put_contents($this->filename, "root file"); - $this->view->file_put_contents($this->folder . $this->filename, "file in subfolder"); - } - - protected function tearDown() { - if ($this->view) { - if ($this->view->file_exists($this->folder)) { - $this->view->unlink($this->folder); - } - if ($this->view->file_exists($this->filename)) { - $this->view->unlink($this->filename); - } - } - - parent::tearDown(); - } - - /** - * test if the mount point moves up if the parent folder no longer exists - */ - public function testShareMountLoseParentFolder() { - - // share to user - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL); - - $share->setTarget('/foo/bar' . $this->folder); - $this->shareManager->moveShare($share, self::TEST_FILES_SHARING_API_USER2); - - $share = $this->shareManager->getShareById($share->getFullId()); - $this->assertSame('/foo/bar' . $this->folder, $share->getTarget()); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - // share should have moved up - - $share = $this->shareManager->getShareById($share->getFullId()); - $this->assertSame($this->folder, $share->getTarget()); - - //cleanup - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - $this->shareManager->deleteShare($share); - $this->view->unlink($this->folder); - } - - /** - * @medium - */ - public function testDeleteParentOfMountPoint() { - // share to user - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); - $this->assertTrue($user2View->file_exists($this->folder)); - - // create a local folder - $result = $user2View->mkdir('localfolder'); - $this->assertTrue($result); - - // move mount point to local folder - $result = $user2View->rename($this->folder, '/localfolder/' . $this->folder); - $this->assertTrue($result); - - // mount point in the root folder should no longer exist - $this->assertFalse($user2View->is_dir($this->folder)); - - // delete the local folder - $result = $user2View->unlink('/localfolder'); - $this->assertTrue($result); - - //enforce reload of the mount points - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - - //mount point should be back at the root - $this->assertTrue($user2View->is_dir($this->folder)); - - //cleanup - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - $this->view->unlink($this->folder); - } - - public function testMoveSharedFile() { - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->filename, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - - \OC\Files\Filesystem::rename($this->filename, $this->filename . '_renamed'); - - $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename . '_renamed')); - $this->assertFalse(\OC\Files\Filesystem::file_exists($this->filename)); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); - $this->assertFalse(\OC\Files\Filesystem::file_exists($this->filename . '_renamed')); - - // rename back to original name - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - \OC\Files\Filesystem::rename($this->filename . '_renamed', $this->filename); - $this->assertFalse(\OC\Files\Filesystem::file_exists($this->filename . '_renamed')); - $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); - - //cleanup - $this->shareManager->deleteShare($share); - } - - /** - * share file with a group if a user renames the file the filename should not change - * for the other users - */ - public function testMoveGroupShare () { - \OC_Group::createGroup('testGroup'); - \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER1, 'testGroup'); - \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup'); - \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup'); - - $fileinfo = $this->view->getFileInfo($this->filename); - $share = $this->share( - \OCP\Share::SHARE_TYPE_GROUP, - $this->filename, - self::TEST_FILES_SHARING_API_USER1, - 'testGroup', - \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - - $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); - - \OC\Files\Filesystem::rename($this->filename, "newFileName"); - - $this->assertTrue(\OC\Files\Filesystem::file_exists('newFileName')); - $this->assertFalse(\OC\Files\Filesystem::file_exists($this->filename)); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER3); - $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); - $this->assertFalse(\OC\Files\Filesystem::file_exists("newFileName")); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER3); - $this->assertTrue(\OC\Files\Filesystem::file_exists($this->filename)); - $this->assertFalse(\OC\Files\Filesystem::file_exists("newFileName")); - - //cleanup - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - $this->shareManager->deleteShare($share); - \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER1, 'testGroup'); - \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup'); - \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup'); - } - - /** - * @dataProvider dataProviderTestStripUserFilesPath - * @param string $path - * @param string $expectedResult - * @param bool $exception if a exception is expected - */ - public function testStripUserFilesPath($path, $expectedResult, $exception) { - $testClass = new DummyTestClassSharedMount(null, null); - try { - $result = $testClass->stripUserFilesPathDummy($path); - $this->assertSame($expectedResult, $result); - } catch (\Exception $e) { - if ($exception) { - $this->assertSame(10, $e->getCode()); - } else { - $this->assertTrue(false, "Exception catched, but expected: " . $expectedResult); - } - } - } - - public function dataProviderTestStripUserFilesPath() { - return array( - array('/user/files/foo.txt', '/foo.txt', false), - array('/user/files/folder/foo.txt', '/folder/foo.txt', false), - array('/data/user/files/foo.txt', null, true), - array('/data/user/files/', null, true), - array('/files/foo.txt', null, true), - array('/foo.txt', null, true), - ); - } - - public function dataPermissionMovedGroupShare() { - $data = []; - - $powerset = function($permissions) { - $results = [\OCP\Constants::PERMISSION_READ]; - - foreach ($permissions as $permission) { - foreach ($results as $combination) { - $results[] = $permission | $combination; - } - } - return $results; - }; - - //Generate file permissions - $permissions = [ - \OCP\Constants::PERMISSION_UPDATE, - \OCP\Constants::PERMISSION_SHARE, - ]; - - $allPermissions = $powerset($permissions); - - foreach ($allPermissions as $before) { - foreach ($allPermissions as $after) { - if ($before === $after) { continue; } - - $data[] = [ - 'file', - $before, - $after, - ]; - } - } - - //Generate folder permissions - $permissions = [ - \OCP\Constants::PERMISSION_UPDATE, - \OCP\Constants::PERMISSION_CREATE, - \OCP\Constants::PERMISSION_SHARE, - \OCP\Constants::PERMISSION_DELETE, - ]; - - $allPermissions = $powerset($permissions); - - foreach ($allPermissions as $before) { - foreach ($allPermissions as $after) { - if ($before === $after) { continue; } - - $data[] = [ - 'folder', - $before, - $after, - ]; - } - } - - return $data; - } - - - - /** - * moved mountpoints of a group share should keep the same permission as their parent group share. - * See #15253 - * - * @dataProvider dataPermissionMovedGroupShare - */ - function testPermissionMovedGroupShare($type, $beforePerm, $afterPerm) { - - if ($type === 'file') { - $path = $this->filename; - } else if ($type === 'folder') { - $path = $this->folder; - } - - \OC_Group::createGroup('testGroup'); - \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER1, 'testGroup'); - \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup'); - \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup'); - - // Share item with group - $share = $this->share( - \OCP\Share::SHARE_TYPE_GROUP, - $path, - self::TEST_FILES_SHARING_API_USER1, - 'testGroup', - $beforePerm - ); - - // Login as user 2 and verify the item exists - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $this->assertTrue(\OC\Files\Filesystem::file_exists($path)); - $result = $this->shareManager->getShareById($share->getFullId(), self::TEST_FILES_SHARING_API_USER2); - $this->assertEquals($beforePerm, $result->getPermissions()); - - // Now move the item forcing a new entry in the share table - \OC\Files\Filesystem::rename($path, "newPath"); - $this->assertTrue(\OC\Files\Filesystem::file_exists('newPath')); - $this->assertFalse(\OC\Files\Filesystem::file_exists($path)); - - // change permissions - $share->setPermissions($afterPerm); - $this->shareManager->updateShare($share); - - // Login as user 3 and verify that the permissions are changed - self::loginHelper(self::TEST_FILES_SHARING_API_USER3); - $result = $this->shareManager->getShareById($share->getFullId(), self::TEST_FILES_SHARING_API_USER3); - $this->assertNotEmpty($result); - $this->assertEquals($afterPerm, $result->getPermissions()); - - // Login as user 2 and verify that the permissions are changed - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $result = $this->shareManager->getShareById($share->getFullId(), self::TEST_FILES_SHARING_API_USER2); - $this->assertNotEmpty($result); - $this->assertEquals($afterPerm, $result->getPermissions()); - $this->assertEquals('/newPath', $result->getTarget()); - - //cleanup - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - $this->shareManager->deleteShare($share); - \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER1, 'testGroup'); - \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup'); - \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup'); - } - - /** - * If the permissions on a group share are upgraded be sure to still respect - * removed shares by a member of that group - */ - function testPermissionUpgradeOnUserDeletedGroupShare() { - \OC_Group::createGroup('testGroup'); - \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER1, 'testGroup'); - \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup'); - \OC_Group::addToGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup'); - - $connection = \OC::$server->getDatabaseConnection(); - - // Share item with group - $fileinfo = $this->view->getFileInfo($this->folder); - $share = $this->share( - \OCP\Share::SHARE_TYPE_GROUP, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - 'testGroup', - \OCP\Constants::PERMISSION_READ - ); - - // Login as user 2 and verify the item exists - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $this->assertTrue(\OC\Files\Filesystem::file_exists($this->folder)); - $result = $this->shareManager->getShareById($share->getFullId(), self::TEST_FILES_SHARING_API_USER2); - $this->assertNotEmpty($result); - $this->assertEquals(\OCP\Constants::PERMISSION_READ, $result->getPermissions()); - - // Delete the share - $this->assertTrue(\OC\Files\Filesystem::rmdir($this->folder)); - $this->assertFalse(\OC\Files\Filesystem::file_exists($this->folder)); - - // Verify we do not get a share - $result = $this->shareManager->getShareById($share->getFullId(), self::TEST_FILES_SHARING_API_USER2); - $this->assertEquals(0, $result->getPermissions()); - - // Login as user 1 again and change permissions - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - $share->setPermissions(\OCP\Constants::PERMISSION_ALL); - $share = $this->shareManager->updateShare($share); - - // Login as user 2 and verify - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $this->assertFalse(\OC\Files\Filesystem::file_exists($this->folder)); - $result = $this->shareManager->getShareById($share->getFullId(), self::TEST_FILES_SHARING_API_USER2); - $this->assertEquals(0, $result->getPermissions()); - - $this->shareManager->deleteShare($share); - - //cleanup - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER1, 'testGroup'); - \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER2, 'testGroup'); - \OC_Group::removeFromGroup(self::TEST_FILES_SHARING_API_USER3, 'testGroup'); - } - -} - -class DummyTestClassSharedMount extends \OCA\Files_Sharing\SharedMount { - public function __construct($storage, $mountpoint, $arguments = null, $loader = null){ - // noop - } - - public function stripUserFilesPathDummy($path) { - return $this->stripUserFilesPath($path); - } -} diff --git a/apps/files_sharing/tests/sharedstorage.php b/apps/files_sharing/tests/sharedstorage.php deleted file mode 100644 index 19edc44f9b4..00000000000 --- a/apps/files_sharing/tests/sharedstorage.php +++ /dev/null @@ -1,532 +0,0 @@ - - * @author Joas Schilling - * @author Morris Jobke - * @author Robin Appelman - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -use OCA\Files\Share; - -/** - * Class Test_Files_Sharing_Api - * - * @group DB - */ -class Test_Files_Sharing_Storage extends OCA\Files_sharing\Tests\TestCase { - - protected function setUp() { - parent::setUp(); - \OCA\Files_Trashbin\Trashbin::registerHooks(); - $this->folder = '/folder_share_storage_test'; - - $this->filename = '/share-api-storage.txt'; - - - $this->view->mkdir($this->folder); - - // save file with content - $this->view->file_put_contents($this->filename, "root file"); - $this->view->file_put_contents($this->folder . $this->filename, "file in subfolder"); - } - - protected function tearDown() { - if ($this->view) { - if ($this->view->file_exists($this->folder)) { - $this->view->unlink($this->folder); - } - if ($this->view->file_exists($this->filename)) { - $this->view->unlink($this->filename); - } - } - - \OC\Files\Filesystem::getLoader()->removeStorageWrapper('oc_trashbin'); - - parent::tearDown(); - } - - /** - * if the parent of the mount point is gone then the mount point should move up - * - * @medium - */ - public function testParentOfMountPointIsGone() { - - // share to user - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); - $this->assertTrue($user2View->file_exists($this->folder)); - - // create a local folder - $result = $user2View->mkdir('localfolder'); - $this->assertTrue($result); - - // move mount point to local folder - $result = $user2View->rename($this->folder, '/localfolder/' . $this->folder); - $this->assertTrue($result); - - // mount point in the root folder should no longer exist - $this->assertFalse($user2View->is_dir($this->folder)); - - // delete the local folder - /** @var \OC\Files\Storage\Storage $storage */ - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/localfolder'); - $storage->rmdir($internalPath); - - //enforce reload of the mount points - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - - //mount point should be back at the root - $this->assertTrue($user2View->is_dir($this->folder)); - - //cleanup - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - $this->view->unlink($this->folder); - } - - /** - * @medium - */ - public function testRenamePartFile() { - - // share to user - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL - ); - - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); - - $this->assertTrue($user2View->file_exists($this->folder)); - - // create part file - $result = $user2View->file_put_contents($this->folder . '/foo.txt.part', 'some test data'); - - $this->assertTrue(is_int($result)); - // rename part file to real file - $result = $user2View->rename($this->folder . '/foo.txt.part', $this->folder . '/foo.txt'); - - $this->assertTrue($result); - - // check if the new file really exists - $this->assertTrue($user2View->file_exists($this->folder . '/foo.txt')); - - // check if the rename also affected the owner - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - - $this->assertTrue($this->view->file_exists($this->folder . '/foo.txt')); - - //cleanup - $this->shareManager->deleteShare($share); - } - - public function testFilesize() { - $folderSize = $this->view->filesize($this->folder); - $file1Size = $this->view->filesize($this->folder . $this->filename); - $file2Size = $this->view->filesize($this->filename); - - $share1 = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL - ); - - $share2 = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->filename, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE - ); - - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - - // compare file size between user1 and user2, should always be the same - $this->assertSame($folderSize, \OC\Files\Filesystem::filesize($this->folder)); - $this->assertSame($file1Size, \OC\Files\Filesystem::filesize($this->folder . $this->filename)); - $this->assertSame($file2Size, \OC\Files\Filesystem::filesize($this->filename)); - - //cleanup - $this->shareManager->deleteShare($share1); - $this->shareManager->deleteShare($share2); - } - - public function testGetPermissions() { - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_READ - ); - - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - - $this->assertTrue(\OC\Files\Filesystem::is_dir($this->folder)); - - // for the share root we expect: - // the shared permissions (1) - // the delete permission (8), to enable unshare - $rootInfo = \OC\Files\Filesystem::getFileInfo($this->folder); - $this->assertSame(9, $rootInfo->getPermissions()); - - // for the file within the shared folder we expect: - // the shared permissions (1) - $subfileInfo = \OC\Files\Filesystem::getFileInfo($this->folder . $this->filename); - $this->assertSame(1, $subfileInfo->getPermissions()); - - - //cleanup - $this->shareManager->deleteShare($share); - } - - public function testFopenWithReadOnlyPermission() { - $this->view->file_put_contents($this->folder . '/existing.txt', 'foo'); - - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_READ - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); - - // part file should be forbidden - $handle = $user2View->fopen($this->folder . '/test.txt.part', 'w'); - $this->assertFalse($handle); - - // regular file forbidden - $handle = $user2View->fopen($this->folder . '/test.txt', 'w'); - $this->assertFalse($handle); - - // rename forbidden - $this->assertFalse($user2View->rename($this->folder . '/existing.txt', $this->folder . '/existing2.txt')); - - // delete forbidden - $this->assertFalse($user2View->unlink($this->folder . '/existing.txt')); - - //cleanup - $this->shareManager->deleteShare($share); - } - - public function testFopenWithCreateOnlyPermission() { - $this->view->file_put_contents($this->folder . '/existing.txt', 'foo'); - $fileinfoFolder = $this->view->getFileInfo($this->folder); - - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); - - // create part file allowed - $handle = $user2View->fopen($this->folder . '/test.txt.part', 'w'); - $this->assertNotFalse($handle); - fclose($handle); - - // create regular file allowed - $handle = $user2View->fopen($this->folder . '/test-create.txt', 'w'); - $this->assertNotFalse($handle); - fclose($handle); - - // rename file never allowed - $this->assertFalse($user2View->rename($this->folder . '/test-create.txt', $this->folder . '/newtarget.txt')); - $this->assertFalse($user2View->file_exists($this->folder . '/newtarget.txt')); - - // rename file not allowed if target exists - $this->assertFalse($user2View->rename($this->folder . '/newtarget.txt', $this->folder . '/existing.txt')); - - // overwriting file not allowed - $handle = $user2View->fopen($this->folder . '/existing.txt', 'w'); - $this->assertFalse($handle); - - // overwrite forbidden (no update permission) - $this->assertFalse($user2View->rename($this->folder . '/test.txt.part', $this->folder . '/existing.txt')); - - // delete forbidden - $this->assertFalse($user2View->unlink($this->folder . '/existing.txt')); - - //cleanup - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - $result = \OCP\Share::unshare('folder', $fileinfoFolder['fileid'], \OCP\Share::SHARE_TYPE_USER, - self::TEST_FILES_SHARING_API_USER2); - $this->assertTrue($result); - } - - public function testFopenWithUpdateOnlyPermission() { - $this->view->file_put_contents($this->folder . '/existing.txt', 'foo'); - - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); - - // create part file allowed - $handle = $user2View->fopen($this->folder . '/test.txt.part', 'w'); - $this->assertNotFalse($handle); - fclose($handle); - - // create regular file not allowed - $handle = $user2View->fopen($this->folder . '/test-create.txt', 'w'); - $this->assertFalse($handle); - - // rename part file not allowed to non-existing file - $this->assertFalse($user2View->rename($this->folder . '/test.txt.part', $this->folder . '/nonexist.txt')); - - // rename part file allowed to target existing file - $this->assertTrue($user2View->rename($this->folder . '/test.txt.part', $this->folder . '/existing.txt')); - $this->assertTrue($user2View->file_exists($this->folder . '/existing.txt')); - - // rename regular file allowed - $this->assertTrue($user2View->rename($this->folder . '/existing.txt', $this->folder . '/existing-renamed.txt')); - $this->assertTrue($user2View->file_exists($this->folder . '/existing-renamed.txt')); - - // overwriting file directly is allowed - $handle = $user2View->fopen($this->folder . '/existing-renamed.txt', 'w'); - $this->assertNotFalse($handle); - fclose($handle); - - // delete forbidden - $this->assertFalse($user2View->unlink($this->folder . '/existing-renamed.txt')); - - //cleanup - $this->shareManager->deleteShare($share); - } - - public function testFopenWithDeleteOnlyPermission() { - $this->view->file_put_contents($this->folder . '/existing.txt', 'foo'); - - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_DELETE - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); - - // part file should be forbidden - $handle = $user2View->fopen($this->folder . '/test.txt.part', 'w'); - $this->assertFalse($handle); - - // regular file forbidden - $handle = $user2View->fopen($this->folder . '/test.txt', 'w'); - $this->assertFalse($handle); - - // rename forbidden - $this->assertFalse($user2View->rename($this->folder . '/existing.txt', $this->folder . '/existing2.txt')); - - // delete allowed - $this->assertTrue($user2View->unlink($this->folder . '/existing.txt')); - - //cleanup - $this->shareManager->deleteShare($share); - } - - public function testMountSharesOtherUser() { - $rootView = new \OC\Files\View(''); - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - - // share 2 different files with 2 different users - $share1 = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL - ); - $share2 = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->filename, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER3, - \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $this->assertTrue($rootView->file_exists('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/' . $this->folder)); - - $mountConfigManager = \OC::$server->getMountProviderCollection(); - $mounts = $mountConfigManager->getMountsForUser(\OC::$server->getUserManager()->get(self::TEST_FILES_SHARING_API_USER3)); - array_walk($mounts, array(\OC\Files\Filesystem::getMountManager(), 'addMount')); - - $this->assertTrue($rootView->file_exists('/' . self::TEST_FILES_SHARING_API_USER3 . '/files/' . $this->filename)); - - // make sure we didn't double setup shares for user 2 or mounted the shares for user 3 in user's 2 home - $this->assertFalse($rootView->file_exists('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/' . $this->folder . ' (2)')); - $this->assertFalse($rootView->file_exists('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/' . $this->filename)); - - //cleanup - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - $this->view->unlink($this->folder); - - $this->shareManager->deleteShare($share1); - $this->shareManager->deleteShare($share2); - } - - public function testCopyFromStorage() { - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $view = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); - $this->assertTrue($view->file_exists($this->folder)); - - /** - * @var \OCP\Files\Storage $sharedStorage - */ - list($sharedStorage,) = $view->resolvePath($this->folder); - $this->assertTrue($sharedStorage->instanceOfStorage('OCA\Files_Sharing\ISharedStorage')); - - $sourceStorage = new \OC\Files\Storage\Temporary(array()); - $sourceStorage->file_put_contents('foo.txt', 'asd'); - - $sharedStorage->copyFromStorage($sourceStorage, 'foo.txt', 'bar.txt'); - $this->assertTrue($sharedStorage->file_exists('bar.txt')); - $this->assertEquals('asd', $sharedStorage->file_get_contents('bar.txt')); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - $this->view->unlink($this->folder); - $this->shareManager->deleteShare($share); - } - - public function testMoveFromStorage() { - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $view = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); - $this->assertTrue($view->file_exists($this->folder)); - - /** - * @var \OCP\Files\Storage $sharedStorage - */ - list($sharedStorage,) = $view->resolvePath($this->folder); - $this->assertTrue($sharedStorage->instanceOfStorage('OCA\Files_Sharing\ISharedStorage')); - - $sourceStorage = new \OC\Files\Storage\Temporary(array()); - $sourceStorage->file_put_contents('foo.txt', 'asd'); - - $sharedStorage->moveFromStorage($sourceStorage, 'foo.txt', 'bar.txt'); - $this->assertTrue($sharedStorage->file_exists('bar.txt')); - $this->assertEquals('asd', $sharedStorage->file_get_contents('bar.txt')); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - $this->view->unlink($this->folder); - $this->shareManager->deleteShare($share); - } - - public function testNameConflict() { - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - $view1 = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files'); - $view1->mkdir('foo'); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER3); - $view3 = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER3 . '/files'); - $view3->mkdir('foo'); - - // share a folder with the same name from two different users to the same user - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - - $share1 = $this->share( - \OCP\Share::SHARE_TYPE_GROUP, - 'foo', - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_GROUP1, - \OCP\Constants::PERMISSION_ALL - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER3); - - $share2 = $this->share( - \OCP\Share::SHARE_TYPE_GROUP, - 'foo', - self::TEST_FILES_SHARING_API_USER3, - self::TEST_FILES_SHARING_API_GROUP1, - \OCP\Constants::PERMISSION_ALL - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - $view2 = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); - - $this->assertTrue($view2->file_exists('/foo')); - $this->assertTrue($view2->file_exists('/foo (2)')); - - $mount = $view2->getMount('/foo'); - $this->assertInstanceOf('\OCA\Files_Sharing\SharedMount', $mount); - /** @var \OC\Files\Storage\Shared $storage */ - $storage = $mount->getStorage(); - - $this->assertEquals(self::TEST_FILES_SHARING_API_USER1, $storage->getOwner('')); - - $this->shareManager->deleteShare($share1); - $this->shareManager->deleteShare($share2); - } -} diff --git a/apps/files_sharing/tests/sizepropagation.php b/apps/files_sharing/tests/sizepropagation.php deleted file mode 100644 index c0f5696c16d..00000000000 --- a/apps/files_sharing/tests/sizepropagation.php +++ /dev/null @@ -1,121 +0,0 @@ - - * @author Robin Appelman - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_sharing\Tests; - -use OC\Files\View; -use Test\Traits\MountProviderTrait; -use Test\Traits\UserTrait; - -/** - * Class SizePropagation - * - * @group DB - * - * @package OCA\Files_sharing\Tests - */ -class SizePropagation extends TestCase { - use UserTrait; - use MountProviderTrait; - - protected function setupUser($name, $password = '') { - $this->createUser($name, $password); - $tmpFolder = \OC::$server->getTempManager()->getTemporaryFolder(); - $this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]); - $this->loginAsUser($name); - return new View('/' . $name . '/files'); - } - - public function testSizePropagationWhenOwnerChangesFile() { - $recipientView = $this->setupUser(self::TEST_FILES_SHARING_API_USER1); - - $ownerView = $this->setupUser(self::TEST_FILES_SHARING_API_USER2); - $ownerView->mkdir('/sharedfolder/subfolder'); - $ownerView->file_put_contents('/sharedfolder/subfolder/foo.txt', 'bar'); - - $this->share( - \OCP\Share::SHARE_TYPE_USER, - '/sharedfolder', - self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER1, - \OCP\Constants::PERMISSION_ALL - ); - $ownerRootInfo = $ownerView->getFileInfo('', false); - - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - $this->assertTrue($recipientView->file_exists('/sharedfolder/subfolder/foo.txt')); - $recipientRootInfo = $recipientView->getFileInfo('', false); - - // when file changed as owner - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); - $ownerView->file_put_contents('/sharedfolder/subfolder/foo.txt', 'foobar'); - - // size of recipient's root stays the same - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - $newRecipientRootInfo = $recipientView->getFileInfo('', false); - $this->assertEquals($recipientRootInfo->getSize(), $newRecipientRootInfo->getSize()); - - // size of owner's root increases - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); - $newOwnerRootInfo = $ownerView->getFileInfo('', false); - $this->assertEquals($ownerRootInfo->getSize() + 3, $newOwnerRootInfo->getSize()); - } - - public function testSizePropagationWhenRecipientChangesFile() { - $recipientView = $this->setupUser(self::TEST_FILES_SHARING_API_USER1); - - $ownerView = $this->setupUser(self::TEST_FILES_SHARING_API_USER2); - $ownerView->mkdir('/sharedfolder/subfolder'); - $ownerView->file_put_contents('/sharedfolder/subfolder/foo.txt', 'bar'); - - $this->share( - \OCP\Share::SHARE_TYPE_USER, - '/sharedfolder', - self::TEST_FILES_SHARING_API_USER2, - self::TEST_FILES_SHARING_API_USER1, - \OCP\Constants::PERMISSION_ALL - ); - $ownerRootInfo = $ownerView->getFileInfo('', false); - - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER1); - $this->assertTrue($recipientView->file_exists('/sharedfolder/subfolder/foo.txt')); - $recipientRootInfo = $recipientView->getFileInfo('', false); - $recipientRootInfoWithMounts = $recipientView->getFileInfo('', true); - - // when file changed as recipient - $recipientView->file_put_contents('/sharedfolder/subfolder/foo.txt', 'foobar'); - - // size of recipient's root stays the same - $newRecipientRootInfo = $recipientView->getFileInfo('', false); - $this->assertEquals($recipientRootInfo->getSize(), $newRecipientRootInfo->getSize()); - - // but the size including mountpoints increases - $newRecipientRootInfo = $recipientView->getFileInfo('', true); - $this->assertEquals($recipientRootInfoWithMounts->getSize() +3, $newRecipientRootInfo->getSize()); - - // size of owner's root increases - $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2); - $newOwnerRootInfo = $ownerView->getFileInfo('', false); - $this->assertEquals($ownerRootInfo->getSize() + 3, $newOwnerRootInfo->getSize()); - } -} diff --git a/apps/files_sharing/tests/testcase.php b/apps/files_sharing/tests/testcase.php deleted file mode 100644 index 9078a3d4578..00000000000 --- a/apps/files_sharing/tests/testcase.php +++ /dev/null @@ -1,233 +0,0 @@ - - * @author Joas Schilling - * @author Jörn Friedrich Dreyer - * @author Lukas Reschke - * @author Morris Jobke - * @author Robin Appelman - * @author Robin McCorkell - * @author Roeland Jago Douma - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_Sharing\Tests; - -use OC\Files\Filesystem; -use OCA\Files\Share; -use OCA\Files_Sharing\AppInfo\Application; - -/** - * Class Test_Files_Sharing_Base - * - * @group DB - * - * Base class for sharing tests. - */ -abstract class TestCase extends \Test\TestCase { - - const TEST_FILES_SHARING_API_USER1 = "test-share-user1"; - const TEST_FILES_SHARING_API_USER2 = "test-share-user2"; - const TEST_FILES_SHARING_API_USER3 = "test-share-user3"; - const TEST_FILES_SHARING_API_USER4 = "test-share-user4"; - - const TEST_FILES_SHARING_API_GROUP1 = "test-share-group1"; - - public $filename; - public $data; - /** - * @var \OC\Files\View - */ - public $view; - public $folder; - public $subfolder; - - /** @var \OCP\Share\IManager */ - protected $shareManager; - /** @var \OCP\Files\IRootFolder */ - protected $rootFolder; - - public static function setUpBeforeClass() { - parent::setUpBeforeClass(); - - $application = new Application(); - $application->registerMountProviders(); - - // reset backend - \OC_User::clearBackends(); - \OC_Group::clearBackends(); - - // clear share hooks - \OC_Hook::clear('OCP\\Share'); - \OC::registerShareHooks(); - - // create users - $backend = new \Test\Util\User\Dummy(); - \OC_User::useBackend($backend); - $backend->createUser(self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER1); - $backend->createUser(self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER2); - $backend->createUser(self::TEST_FILES_SHARING_API_USER3, self::TEST_FILES_SHARING_API_USER3); - $backend->createUser(self::TEST_FILES_SHARING_API_USER4, self::TEST_FILES_SHARING_API_USER4); - - // create group - $groupBackend = new \Test\Util\Group\Dummy(); - $groupBackend->createGroup(self::TEST_FILES_SHARING_API_GROUP1); - $groupBackend->createGroup('group'); - $groupBackend->createGroup('group1'); - $groupBackend->createGroup('group2'); - $groupBackend->createGroup('group3'); - $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER1, 'group'); - $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER2, 'group'); - $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER3, 'group'); - $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER2, 'group1'); - $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER3, 'group2'); - $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER4, 'group3'); - $groupBackend->addToGroup(self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_GROUP1); - \OC_Group::useBackend($groupBackend); - } - - protected function setUp() { - parent::setUp(); - - //login as user1 - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - - $this->data = 'foobar'; - $this->view = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files'); - - $this->shareManager = \OC::$server->getShareManager(); - $this->rootFolder = \OC::$server->getRootFolder(); - } - - protected function tearDown() { - $query = \OCP\DB::prepare('DELETE FROM `*PREFIX*share`'); - $query->execute(); - - parent::tearDown(); - } - - public static function tearDownAfterClass() { - // cleanup users - $user = \OC::$server->getUserManager()->get(self::TEST_FILES_SHARING_API_USER1); - if ($user !== null) { $user->delete(); } - $user = \OC::$server->getUserManager()->get(self::TEST_FILES_SHARING_API_USER2); - if ($user !== null) { $user->delete(); } - $user = \OC::$server->getUserManager()->get(self::TEST_FILES_SHARING_API_USER3); - if ($user !== null) { $user->delete(); } - - // delete group - \OC_Group::deleteGroup(self::TEST_FILES_SHARING_API_GROUP1); - - \OC_Util::tearDownFS(); - \OC_User::setUserId(''); - Filesystem::tearDown(); - - // reset backend - \OC_User::clearBackends(); - \OC_User::useBackend('database'); - \OC_Group::clearBackends(); - \OC_Group::useBackend(new \OC\Group\Database()); - - parent::tearDownAfterClass(); - } - - /** - * @param string $user - * @param bool $create - * @param bool $password - */ - protected static function loginHelper($user, $create = false, $password = false) { - - if ($password === false) { - $password = $user; - } - - if ($create) { - \OC::$server->getUserManager()->createUser($user, $password); - \OC_Group::createGroup('group'); - \OC_Group::addToGroup($user, 'group'); - } - - self::resetStorage(); - - \OC_Util::tearDownFS(); - \OC::$server->getUserSession()->setUser(null); - \OC\Files\Filesystem::tearDown(); - \OC::$server->getUserSession()->login($user, $password); - \OC::$server->getUserFolder($user); - - \OC_Util::setupFS($user); - } - - /** - * reset init status for the share storage - */ - protected static function resetStorage() { - $storage = new \ReflectionClass('\OC\Files\Storage\Shared'); - $isInitialized = $storage->getProperty('initialized'); - $isInitialized->setAccessible(true); - $isInitialized->setValue($storage, false); - $isInitialized->setAccessible(false); - } - - /** - * get some information from a given share - * @param int $shareID - * @return array with: item_source, share_type, share_with, item_type, permissions - */ - protected function getShareFromId($shareID) { - $sql = 'SELECT `item_source`, `share_type`, `share_with`, `item_type`, `permissions` FROM `*PREFIX*share` WHERE `id` = ?'; - $args = array($shareID); - $query = \OCP\DB::prepare($sql); - $result = $query->execute($args); - - $share = Null; - - if ($result) { - $share = $result->fetchRow(); - } - - return $share; - - } - - /** - * @param int $type The share type - * @param string $path The path to share relative to $initiators root - * @param string $initiator - * @param string $recipient - * @param int $permissions - * @return \OCP\Share\IShare - */ - protected function share($type, $path, $initiator, $recipient, $permissions) { - $userFolder = $this->rootFolder->getUserFolder($initiator); - $node = $userFolder->get($path); - - $share = $this->shareManager->newShare(); - $share->setShareType($type) - ->setSharedWith($recipient) - ->setSharedBy($initiator) - ->setNode($node) - ->setPermissions($permissions); - $share = $this->shareManager->createShare($share); - - return $share; - } -} diff --git a/apps/files_sharing/tests/unsharechildren.php b/apps/files_sharing/tests/unsharechildren.php deleted file mode 100644 index 6104dc98080..00000000000 --- a/apps/files_sharing/tests/unsharechildren.php +++ /dev/null @@ -1,113 +0,0 @@ - - * @author Joas Schilling - * @author Morris Jobke - * @author Robin Appelman - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OCA\Files_sharing\Tests; - -use OCA\Files\Share; - -/** - * Class UnshareChildren - * - * @group DB - * - * @package OCA\Files_sharing\Tests - */ -class UnshareChildren extends TestCase { - - protected $subsubfolder; - - const TEST_FOLDER_NAME = '/folder_share_api_test'; - - private static $tempStorage; - - protected function setUp() { - parent::setUp(); - - \OCP\Util::connectHook('OC_Filesystem', 'post_delete', '\OCA\Files_Sharing\Hooks', 'unshareChildren'); - - $this->folder = self::TEST_FOLDER_NAME; - $this->subfolder = '/subfolder_share_api_test'; - $this->subsubfolder = '/subsubfolder_share_api_test'; - - $this->filename = '/share-api-test'; - - // save file with content - $this->view->mkdir($this->folder); - $this->view->mkdir($this->folder . $this->subfolder); - $this->view->mkdir($this->folder . $this->subfolder . $this->subsubfolder); - $this->view->file_put_contents($this->folder . $this->filename, $this->data); - $this->view->file_put_contents($this->folder . $this->subfolder . $this->filename, $this->data); - } - - protected function tearDown() { - if ($this->view) { - $this->view->deleteAll($this->folder); - } - - self::$tempStorage = null; - - parent::tearDown(); - } - - /** - * @medium - */ - function testUnshareChildren() { - - $fileInfo2 = \OC\Files\Filesystem::getFileInfo($this->folder); - - $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL - ); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - - // one folder should be shared with the user - $shares = $this->shareManager->getSharedWith(self::TEST_FILES_SHARING_API_USER2, \OCP\Share::SHARE_TYPE_USER); - $this->assertCount(1, $shares); - - // move shared folder to 'localDir' - \OC\Files\Filesystem::mkdir('localDir'); - $result = \OC\Files\Filesystem::rename($this->folder, '/localDir/' . $this->folder); - $this->assertTrue($result); - - \OC\Files\Filesystem::unlink('localDir'); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - - // after the parent directory was deleted the share should be unshared - $shares = $this->shareManager->getSharedWith(self::TEST_FILES_SHARING_API_USER2, \OCP\Share::SHARE_TYPE_USER); - $this->assertEmpty($shares); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - - // the folder for the owner should still exists - $this->assertTrue(\OC\Files\Filesystem::file_exists($this->folder)); - } -} diff --git a/apps/files_sharing/tests/updater.php b/apps/files_sharing/tests/updater.php deleted file mode 100644 index 53e7fc47665..00000000000 --- a/apps/files_sharing/tests/updater.php +++ /dev/null @@ -1,232 +0,0 @@ - - * @author Joas Schilling - * @author Morris Jobke - * @author Robin Appelman - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - - -/** - * Class Test_Files_Sharing_Updater - * - * @group DB - */ -class Test_Files_Sharing_Updater extends OCA\Files_Sharing\Tests\TestCase { - - const TEST_FOLDER_NAME = '/folder_share_updater_test'; - - public static function setUpBeforeClass() { - parent::setUpBeforeClass(); - \OCA\Files_Sharing\Helper::registerHooks(); - } - - protected function setUp() { - parent::setUp(); - - $this->folder = self::TEST_FOLDER_NAME; - - $this->filename = '/share-updater-test.txt'; - - // save file with content - $this->view->file_put_contents($this->filename, $this->data); - $this->view->mkdir($this->folder); - $this->view->file_put_contents($this->folder . '/' . $this->filename, $this->data); - } - - protected function tearDown() { - if ($this->view) { - $this->view->unlink($this->filename); - $this->view->deleteAll($this->folder); - } - - parent::tearDown(); - } - - /** - * test deletion of a folder which contains share mount points. Share mount - * points should be unshared before the folder gets deleted so - * that the mount point doesn't end up at the trash bin - */ - function testDeleteParentFolder() { - $status = \OC_App::isEnabled('files_trashbin'); - \OC_App::enable('files_trashbin'); - - \OCA\Files_Trashbin\Trashbin::registerHooks(); - - $fileinfo = \OC\Files\Filesystem::getFileInfo($this->folder); - $this->assertTrue($fileinfo instanceof \OC\Files\FileInfo); - - $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL - ); - - $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); - $view = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files'); - - // check if user2 can see the shared folder - $this->assertTrue($view->file_exists($this->folder)); - - $foldersShared = \OCP\Share::getItemsSharedWith('folder'); - $this->assertSame(1, count($foldersShared)); - - $view->mkdir("localFolder"); - $view->file_put_contents("localFolder/localFile.txt", "local file"); - - $view->rename($this->folder, 'localFolder/' . $this->folder); - - // share mount point should now be moved to the subfolder - $this->assertFalse($view->file_exists($this->folder)); - $this->assertTrue($view->file_exists('localFolder/' .$this->folder)); - - $view->unlink('localFolder'); - - $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); - - // shared folder should be unshared - $foldersShared = \OCP\Share::getItemsSharedWith('folder'); - $this->assertTrue(empty($foldersShared)); - - // trashbin should contain the local file but not the mount point - $rootView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2); - $trashContent = \OCA\Files_Trashbin\Helper::getTrashFiles('/', self::TEST_FILES_SHARING_API_USER2); - $this->assertSame(1, count($trashContent)); - $firstElement = reset($trashContent); - $timestamp = $firstElement['mtime']; - $this->assertTrue($rootView->file_exists('files_trashbin/files/localFolder.d' . $timestamp . '/localFile.txt')); - $this->assertFalse($rootView->file_exists('files_trashbin/files/localFolder.d' . $timestamp . '/' . $this->folder)); - - //cleanup - $rootView->deleteAll('files_trashin'); - - if ($status === false) { - \OC_App::disable('files_trashbin'); - } - - \OC\Files\Filesystem::getLoader()->removeStorageWrapper('oc_trashbin'); - } - - public function shareFolderProvider() { - return [ - ['/'], - ['/my_shares'], - ]; - } - - /** - * if a file gets shared the etag for the recipients root should change - * - * @dataProvider shareFolderProvider - * - * @param string $shareFolder share folder to use - */ - public function testShareFile($shareFolder) { - $config = \OC::$server->getConfig(); - $oldShareFolder = $config->getSystemValue('share_folder'); - $config->setSystemValue('share_folder', $shareFolder); - - $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); - - $beforeShareRoot = \OC\Files\Filesystem::getFileInfo(''); - $etagBeforeShareRoot = $beforeShareRoot->getEtag(); - - \OC\Files\Filesystem::mkdir($shareFolder); - - $beforeShareDir = \OC\Files\Filesystem::getFileInfo($shareFolder); - $etagBeforeShareDir = $beforeShareDir->getEtag(); - - $this->loginHelper(self::TEST_FILES_SHARING_API_USER1); - - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL - ); - - $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); - - $afterShareRoot = \OC\Files\Filesystem::getFileInfo(''); - $etagAfterShareRoot = $afterShareRoot->getEtag(); - - $afterShareDir = \OC\Files\Filesystem::getFileInfo($shareFolder); - $etagAfterShareDir = $afterShareDir->getEtag(); - - $this->assertTrue(is_string($etagBeforeShareRoot)); - $this->assertTrue(is_string($etagBeforeShareDir)); - $this->assertTrue(is_string($etagAfterShareRoot)); - $this->assertTrue(is_string($etagAfterShareDir)); - $this->assertTrue($etagBeforeShareRoot !== $etagAfterShareRoot); - $this->assertTrue($etagBeforeShareDir !== $etagAfterShareDir); - - // cleanup - $this->loginHelper(self::TEST_FILES_SHARING_API_USER1); - $this->shareManager->deleteShare($share); - - $config->setSystemValue('share_folder', $oldShareFolder); - } - - /** - * if a folder gets renamed all children mount points should be renamed too - */ - function testRename() { - - $fileinfo = \OC\Files\Filesystem::getFileInfo($this->folder); - - $share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - $this->folder, - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL - ); - - $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); - - // make sure that the shared folder exists - $this->assertTrue(\OC\Files\Filesystem::file_exists($this->folder)); - - \OC\Files\Filesystem::mkdir('oldTarget'); - \OC\Files\Filesystem::mkdir('oldTarget/subfolder'); - \OC\Files\Filesystem::mkdir('newTarget'); - - \OC\Files\Filesystem::rename($this->folder, 'oldTarget/subfolder/' . $this->folder); - - // re-login to make sure that the new mount points are initialized - $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); - - \OC\Files\Filesystem::rename('/oldTarget', '/newTarget/oldTarget'); - - // re-login to make sure that the new mount points are initialized - $this->loginHelper(self::TEST_FILES_SHARING_API_USER2); - - $this->assertTrue(\OC\Files\Filesystem::file_exists('/newTarget/oldTarget/subfolder/' . $this->folder)); - - // cleanup - $this->shareManager->deleteShare($share); - } - -} diff --git a/apps/files_sharing/tests/watcher.php b/apps/files_sharing/tests/watcher.php deleted file mode 100644 index 19e1bc0b615..00000000000 --- a/apps/files_sharing/tests/watcher.php +++ /dev/null @@ -1,178 +0,0 @@ - - * @author Joas Schilling - * @author Jörn Friedrich Dreyer - * @author Morris Jobke - * @author Robin Appelman - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -/** - * Class Test_Files_Sharing_Watcher - * - * @group DB - */ -class Test_Files_Sharing_Watcher extends OCA\Files_sharing\Tests\TestCase { - - /** @var \OC\Files\Storage\Storage */ - private $ownerStorage; - - /** @var \OC\Files\Cache\Cache */ - private $ownerCache; - - /** @var \OC\Files\Storage\Storage */ - private $sharedStorage; - - /** @var \OC\Files\Cache\Cache */ - private $sharedCache; - - /** @var \OCP\Share\IShare */ - private $_share; - - protected function setUp() { - parent::setUp(); - - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - - // prepare user1's dir structure - $this->view->mkdir('container'); - $this->view->mkdir('container/shareddir'); - $this->view->mkdir('container/shareddir/subdir'); - - list($this->ownerStorage, $internalPath) = $this->view->resolvePath(''); - $this->ownerCache = $this->ownerStorage->getCache(); - $this->ownerStorage->getScanner()->scan(''); - - // share "shareddir" with user2 - $this->_share = $this->share( - \OCP\Share::SHARE_TYPE_USER, - 'container/shareddir', - self::TEST_FILES_SHARING_API_USER1, - self::TEST_FILES_SHARING_API_USER2, - \OCP\Constants::PERMISSION_ALL - ); - - // login as user2 - self::loginHelper(self::TEST_FILES_SHARING_API_USER2); - - // retrieve the shared storage - $secondView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2); - list($this->sharedStorage, $internalPath) = $secondView->resolvePath('files/shareddir'); - $this->sharedCache = $this->sharedStorage->getCache(); - } - - protected function tearDown() { - if ($this->sharedCache) { - $this->sharedCache->clear(); - } - - self::loginHelper(self::TEST_FILES_SHARING_API_USER1); - - if ($this->view) { - $this->shareManager->deleteShare($this->_share); - - $this->view->deleteAll('container'); - - $this->ownerCache->clear(); - } - - parent::tearDown(); - } - - /** - * Tests that writing a file using the shared storage will propagate the file - * size to the owner's parent folders. - */ - function testFolderSizePropagationToOwnerStorage() { - $initialSizes = self::getOwnerDirSizes('files/container/shareddir'); - - $textData = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - $dataLen = strlen($textData); - $this->sharedCache->put('bar.txt', array('mtime' => 10, 'storage_mtime' => 10, 'size' => $dataLen, 'mimetype' => 'text/plain')); - $this->sharedStorage->file_put_contents('bar.txt', $textData); - $this->sharedCache->put('', array('mtime' => 10, 'storage_mtime' => 10, 'size' => '-1', 'mimetype' => 'httpd/unix-directory')); - - // run the propagation code - $this->sharedStorage->getWatcher()->checkUpdate(''); - $this->sharedStorage->getCache()->correctFolderSize(''); - - // the owner's parent dirs must have increase size - $newSizes = self::getOwnerDirSizes('files/container/shareddir'); - $this->assertEquals($initialSizes[''] + $dataLen, $newSizes['']); - $this->assertEquals($initialSizes['files'] + $dataLen, $newSizes['files']); - $this->assertEquals($initialSizes['files/container'] + $dataLen, $newSizes['files/container']); - $this->assertEquals($initialSizes['files/container/shareddir'] + $dataLen, $newSizes['files/container/shareddir']); - - // no more updates - $result = $this->sharedStorage->getWatcher()->checkUpdate(''); - - $this->assertFalse($result); - } - - /** - * Tests that writing a file using the shared storage will propagate the file - * size to the owner's parent folders. - */ - function testSubFolderSizePropagationToOwnerStorage() { - $initialSizes = self::getOwnerDirSizes('files/container/shareddir/subdir'); - - $textData = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - $dataLen = strlen($textData); - $this->sharedCache->put('subdir/bar.txt', array('mtime' => 10, 'storage_mtime' => 10, 'size' => $dataLen, 'mimetype' => 'text/plain')); - $this->sharedStorage->file_put_contents('subdir/bar.txt', $textData); - $this->sharedCache->put('subdir', array('mtime' => 10, 'storage_mtime' => 10, 'size' => $dataLen, 'mimetype' => 'text/plain')); - - // run the propagation code - $this->sharedStorage->getWatcher()->checkUpdate('subdir'); - $this->sharedStorage->getCache()->correctFolderSize('subdir'); - - // the owner's parent dirs must have increase size - $newSizes = self::getOwnerDirSizes('files/container/shareddir/subdir'); - $this->assertEquals($initialSizes[''] + $dataLen, $newSizes['']); - $this->assertEquals($initialSizes['files'] + $dataLen, $newSizes['files']); - $this->assertEquals($initialSizes['files/container'] + $dataLen, $newSizes['files/container']); - $this->assertEquals($initialSizes['files/container/shareddir'] + $dataLen, $newSizes['files/container/shareddir']); - $this->assertEquals($initialSizes['files/container/shareddir/subdir'] + $dataLen, $newSizes['files/container/shareddir/subdir']); - - // no more updates - $result = $this->sharedStorage->getWatcher()->checkUpdate('subdir'); - - $this->assertFalse($result); - } - - /** - * Returns the sizes of the path and its parent dirs in a hash - * where the key is the path and the value is the size. - * @param string $path - */ - function getOwnerDirSizes($path) { - $result = array(); - - while ($path != '' && $path != '' && $path != '.') { - $cachedData = $this->ownerCache->get($path); - $result[$path] = $cachedData['size']; - $path = dirname($path); - } - $cachedData = $this->ownerCache->get(''); - $result[''] = $cachedData['size']; - return $result; - } -} -- cgit v1.2.3