diff --git a/apps/dav/lib/Connector/Sabre/CorsPlugin.php b/apps/dav/lib/Connector/Sabre/CorsPlugin.php index bf402a0ec2b1..f17d18616c37 100644 --- a/apps/dav/lib/Connector/Sabre/CorsPlugin.php +++ b/apps/dav/lib/Connector/Sabre/CorsPlugin.php @@ -48,6 +48,10 @@ class CorsPlugin extends ServerPlugin { /** @var array */ private $extraHeaders; + /** + * @var bool + */ + private $alreadyExecuted = false; /** * @param IUserSession $userSession @@ -105,9 +109,13 @@ public function initialize(\Sabre\DAV\Server $server) { } $this->server->on('beforeMethod', [$this, 'setCorsHeaders']); - $this->server->on('beforeMethod:OPTIONS', [$this, 'setOptionsRequestHeaders']); + $this->server->on('exception', [$this, 'onException']); + $this->server->on('beforeMethod:OPTIONS', [$this, 'setOptionsRequestHeaders'], 5); } + public function onException(\Throwable $ex) { + $this->setCorsHeaders($this->server->httpRequest, $this->server->httpResponse); + } /** * This method sets the cors headers for all requests * @@ -116,18 +124,23 @@ public function initialize(\Sabre\DAV\Server $server) { * @return void */ public function setCorsHeaders(RequestInterface $request, ResponseInterface $response) { - if ($request->getHeader('origin') !== null) { - $requesterDomain = $request->getHeader('origin'); - // unauthenticated request shall add cors headers as well - $userId = null; - if ($this->userSession->getUser() !== null) { - $userId = $this->userSession->getUser()->getUID(); - } + if ($request->getHeader('origin') === null) { + return; + } + if ($this->alreadyExecuted) { + return; + } + $this->alreadyExecuted = true; + $requesterDomain = $request->getHeader('origin'); + // unauthenticated request shall add cors headers as well + $userId = null; + if ($this->userSession->getUser() !== null) { + $userId = $this->userSession->getUser()->getUID(); + } - $headers = \OC_Response::setCorsHeaders($userId, $requesterDomain, null, $this->getExtraHeaders($request)); - foreach ($headers as $key => $value) { - $response->addHeader($key, \implode(',', $value)); - } + $headers = \OC_Response::setCorsHeaders($userId, $requesterDomain, null, $this->getExtraHeaders($request)); + foreach ($headers as $key => $value) { + $response->addHeader($key, \implode(',', $value)); } } diff --git a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php index f3bedae4c30f..76485ec2f683 100644 --- a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php +++ b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php @@ -32,6 +32,7 @@ use OCA\FederatedFileSharing\FedShareManager; use OCA\FederatedFileSharing\Middleware\OcmMiddleware; use OCA\FederatedFileSharing\Ocm\Exception\BadRequestException; +use OCA\FederatedFileSharing\Ocm\Exception\ForbiddenException; use OCA\FederatedFileSharing\Ocm\Exception\NotImplementedException; use OCA\FederatedFileSharing\Ocm\Exception\OcmException; use OCP\AppFramework\Http; @@ -255,6 +256,18 @@ public function acceptShare($id) { $token = $this->request->getParam('token', null); $share = $this->ocmMiddleware->getValidShare($id, $token); $this->fedShareManager->acceptShare($share); + } catch (BadRequestException $e) { + return new Result( + null, + Http::STATUS_GONE, + $e->getMessage() + ); + } catch (ForbiddenException $e) { + return new Result( + null, + Http::STATUS_FORBIDDEN, + $e->getMessage() + ); } catch (NotImplementedException $e) { return new Result( null, @@ -281,6 +294,18 @@ public function declineShare($id) { $this->ocmMiddleware->assertOutgoingSharingEnabled(); $share = $this->ocmMiddleware->getValidShare($id, $token); $this->fedShareManager->declineShare($share); + } catch (BadRequestException $e) { + return new Result( + null, + Http::STATUS_GONE, + $e->getMessage() + ); + } catch (ForbiddenException $e) { + return new Result( + null, + Http::STATUS_FORBIDDEN, + $e->getMessage() + ); } catch (NotImplementedException $e) { return new Result( null, diff --git a/apps/federatedfilesharing/tests/Controller/RequestHandlerTest.php b/apps/federatedfilesharing/tests/Controller/RequestHandlerTest.php index a13dcc700c33..ee7a1dc82d6d 100644 --- a/apps/federatedfilesharing/tests/Controller/RequestHandlerTest.php +++ b/apps/federatedfilesharing/tests/Controller/RequestHandlerTest.php @@ -308,6 +308,42 @@ public function testAcceptSuccess() { ); } + public function testAcceptFailedWhenInvalidShareId() { + $this->request->expects($this->any()) + ->method('getParam') + ->willReturn(self::DEFAULT_TOKEN); + + $this->ocmMiddleware->method('getValidShare') + ->willThrowException(new BadRequestException()); + + $this->fedShareManager->expects($this->never()) + ->method('acceptShare'); + + $response = $this->requestHandlerController->acceptShare(2); + $this->assertEquals( + Http::STATUS_GONE, + $response->getStatusCode() + ); + } + + public function testAcceptFailedWhenShareIdHasInvalidSecret() { + $this->request->expects($this->any()) + ->method('getParam') + ->willReturn(self::DEFAULT_TOKEN); + + $this->ocmMiddleware->method('getValidShare') + ->willThrowException(new ForbiddenException()); + + $this->fedShareManager->expects($this->never()) + ->method('acceptShare'); + + $response = $this->requestHandlerController->acceptShare(2); + $this->assertEquals( + Http::STATUS_FORBIDDEN, + $response->getStatusCode() + ); + } + public function testDeclineFailedWhenSharingIsDisabled() { $this->ocmMiddleware->method('assertOutgoingSharingEnabled') ->willThrowException(new NotImplementedException()); @@ -346,6 +382,42 @@ public function testDeclineSuccess() { ); } + public function testDeclineFailedWhenInvalidShareId() { + $this->request->expects($this->any()) + ->method('getParam') + ->willReturn(self::DEFAULT_TOKEN); + + $this->ocmMiddleware->method('getValidShare') + ->willThrowException(new BadRequestException()); + + $this->fedShareManager->expects($this->never()) + ->method('declineShare'); + + $response = $this->requestHandlerController->declineShare(2); + $this->assertEquals( + Http::STATUS_GONE, + $response->getStatusCode() + ); + } + + public function testDeclineFailedWhenShareIdHasInvalidSecret() { + $this->request->expects($this->any()) + ->method('getParam') + ->willReturn(self::DEFAULT_TOKEN); + + $this->ocmMiddleware->method('getValidShare') + ->willThrowException(new ForbiddenException()); + + $this->fedShareManager->expects($this->never()) + ->method('declineShare'); + + $response = $this->requestHandlerController->declineShare(2); + $this->assertEquals( + Http::STATUS_FORBIDDEN, + $response->getStatusCode() + ); + } + public function testUnshareFailedWhenSharingIsDisabled() { $this->ocmMiddleware->method('assertOutgoingSharingEnabled') ->willThrowException(new NotImplementedException()); diff --git a/apps/files_sharing/appinfo/routes.php b/apps/files_sharing/appinfo/routes.php index b6d04dcf27c1..21fed452d6ab 100644 --- a/apps/files_sharing/appinfo/routes.php +++ b/apps/files_sharing/appinfo/routes.php @@ -50,7 +50,52 @@ 'name' => 'sharees#search', 'url' => '/api/v1/sharees', 'verb' => 'GET', - ] + ], + [ + 'name' => 'Share20Ocs#getShares', + 'url' => '/api/v1/shares', + 'verb' => 'GET' + ], + [ + 'name' => 'Share20Ocs#createShare', + 'url' => '/api/v1/shares', + 'verb' => 'POST' + ], + [ + 'name' => 'Share20Ocs#acceptShare', + 'url' => '/api/v1/shares/pending/{id}', + 'verb' => 'POST' + ], + [ + 'name' => 'Share20Ocs#declineShare', + 'url' => '/api/v1/shares/pending/{id}', + 'verb' => 'DELETE' + ], + [ + 'name' => 'Share20Ocs#getShare', + 'url' => '/api/v1/shares/{id}', + 'verb' => 'GET' + ], + [ + 'name' => 'Share20Ocs#updateShare', + 'url' => '/api/v1/shares/{id}', + 'verb' => 'PUT' + ], + [ + 'name' => 'Share20Ocs#deleteShare', + 'url' => '/api/v1/shares/{id}', + 'verb' => 'DELETE' + ], + [ + 'name' => 'Share20Ocs#notifyRecipients', + 'url' => '/api/v1/notification/send', + 'verb' => 'POST' + ], + [ + 'name' => 'Share20Ocs#notifyRecipientsDisabled', + 'url' => '/api/v1/notification/marksent', + 'verb' => 'POST' + ], ] ]); @@ -70,46 +115,8 @@ function () { ->actionInclude('files_sharing/ajax/external.php'); // OCS API - //TODO: SET: mail notification, waiting for PR #4689 to be accepted -$OCSShare = new \OCA\Files_Sharing\API\OCSShareWrapper($application); - -API::register('get', - '/apps/files_sharing/api/v1/shares', - [$OCSShare, 'getAllShares'], - 'files_sharing'); - -API::register('post', - '/apps/files_sharing/api/v1/shares', - [$OCSShare, 'createShare'], - 'files_sharing'); - -API::register('post', - '/apps/files_sharing/api/v1/shares/pending/{id}', - [$OCSShare, 'acceptShare'], - 'files_sharing'); - -API::register('delete', - '/apps/files_sharing/api/v1/shares/pending/{id}', - [$OCSShare, 'declineShare'], - 'files_sharing'); - -API::register('get', - '/apps/files_sharing/api/v1/shares/{id}', - [$OCSShare, 'getShare'], - 'files_sharing'); - -API::register('put', - '/apps/files_sharing/api/v1/shares/{id}', - [$OCSShare, 'updateShare'], - 'files_sharing'); - -API::register('delete', - '/apps/files_sharing/api/v1/shares/{id}', - [$OCSShare, 'deleteShare'], - 'files_sharing'); - API::register('get', '/apps/files_sharing/api/v1/remote_shares', ['\OCA\Files_Sharing\API\Remote', 'getShares'], diff --git a/apps/files_sharing/lib/API/OCSShareWrapper.php b/apps/files_sharing/lib/API/OCSShareWrapper.php deleted file mode 100644 index ecaca2183af9..000000000000 --- a/apps/files_sharing/lib/API/OCSShareWrapper.php +++ /dev/null @@ -1,88 +0,0 @@ - - * - * @copyright Copyright (c) 2018, ownCloud GmbH - * @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 OCA\Files_Sharing\AppInfo\Application; -use OCA\Files_Sharing\Service\NotificationPublisher; -use OCA\Files_Sharing\SharingBlacklist; - -class OCSShareWrapper { - - /** @var Application */ - private $application; - - public function __construct(Application $application) { - $this->application = $application; - } - - /** - * @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'), - \OC::$server->getConfig(), - $this->application->getContainer()->query(NotificationPublisher::class), - \OC::$server->getEventDispatcher(), - $this->application->getContainer()->query(SharingBlacklist::class) - ); - } - - 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); - } - - public function acceptShare($params) { - $id = $params['id']; - return $this->getShare20OCS()->acceptShare($id); - } - - public function declineShare($params) { - $id = $params['id']; - return $this->getShare20OCS()->declineShare($id); - } -} diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php index f9b0f175fa57..9ce2c3cac5fc 100644 --- a/apps/files_sharing/lib/AppInfo/Application.php +++ b/apps/files_sharing/lib/AppInfo/Application.php @@ -28,11 +28,13 @@ namespace OCA\Files_Sharing\AppInfo; use OC\AppFramework\Utility\SimpleContainer; +use OCA\Files_Sharing\Controller\Share20OcsController; use OCA\Files_Sharing\Controllers\ExternalSharesController; use OCA\Files_Sharing\Controllers\ShareController; use OCA\Files_Sharing\Middleware\SharingCheckMiddleware; use OCA\Files_Sharing\MountProvider; use OCA\Files_Sharing\Notifier; +use OCA\Files_Sharing\SharingBlacklist; use OCP\AppFramework\App; use OCP\IContainer; use OCA\Files_Sharing\Hooks; @@ -75,6 +77,24 @@ public function __construct(array $urlParams = []) { ); }); + $container->registerService('Share20OcsController', function (SimpleContainer $c) use ($server) { + return new Share20OcsController( + $c->query('AppName'), + $server->getRequest(), + $server->getShareManager(), + $server->getGroupManager(), + $server->getUserManager(), + $server->getRootFolder(), + $server->getURLGenerator(), + $server->getUserSession(), + $server->getL10N('files_sharing'), + $server->getConfig(), + $c->query(NotificationPublisher::class), + $server->getEventDispatcher(), + $c->query(SharingBlacklist::class) + ); + }); + /** * Core class wrappers */ diff --git a/apps/files_sharing/lib/API/Share20OCS.php b/apps/files_sharing/lib/Controller/Share20OcsController.php similarity index 62% rename from apps/files_sharing/lib/API/Share20OCS.php rename to apps/files_sharing/lib/Controller/Share20OcsController.php index fc14d2b24930..4431d7e76f16 100644 --- a/apps/files_sharing/lib/API/Share20OCS.php +++ b/apps/files_sharing/lib/Controller/Share20OcsController.php @@ -1,10 +1,6 @@ - * @author Roeland Jago Douma - * @author Vincent Petry * @author Viktar Dubiniuk - * @author Semih Serhat Karakaya * * @copyright Copyright (c) 2019, ownCloud GmbH * @license AGPL-3.0 @@ -22,9 +18,12 @@ * along with this program. If not, see * */ -namespace OCA\Files_Sharing\API; + +namespace OCA\Files_Sharing\Controller; use OCP\Constants; +use OC\OCS\Result; +use OCP\AppFramework\OCSController; use OCP\Files\IRootFolder; use OCP\Files\NotFoundException; use OCP\IConfig; @@ -34,8 +33,10 @@ use OCP\IURLGenerator; use OCP\IUser; use OCP\IUserManager; +use OCP\IUserSession; use OCP\Lock\ILockingProvider; use OCP\Lock\LockedException; +use OCP\Share; use OCP\Share\Exceptions\GenericShareException; use OCP\Share\Exceptions\ShareNotFound; use OCP\Share\IManager; @@ -47,26 +48,23 @@ use Symfony\Component\EventDispatcher\GenericEvent; /** - * Class Share20OCS + * Class Share20OcsController * - * @package OCA\Files_Sharing\API + * @package OCA\Files_Sharing\Controller */ -class Share20OCS { - +class Share20OcsController extends OCSController { /** @var IManager */ private $shareManager; /** @var IGroupManager */ private $groupManager; /** @var IUserManager */ private $userManager; - /** @var IRequest */ - private $request; /** @var IRootFolder */ private $rootFolder; + /** @var IUserSession */ + private $userSession; /** @var IURLGenerator */ private $urlGenerator; - /** @var IUser */ - private $currentUser; /** @var IL10N */ private $l; /** @var IConfig */ @@ -75,55 +73,43 @@ class Share20OCS { private $notificationPublisher; /** @var EventDispatcher */ private $eventDispatcher; + /** @var SharingBlacklist */ private $sharingBlacklist; - /** * @var string */ private $additionalInfoField; - /** - * Share20OCS constructor. - * - * @param IManager $shareManager - * @param IGroupManager $groupManager - * @param IUserManager $userManager - * @param IRequest $request - * @param IRootFolder $rootFolder - * @param IURLGenerator $urlGenerator - * @param IUser $currentUser - * @param IL10N $l10n - * @param IConfig $config - * @param NotificationPublisher $notificationPublisher - */ public function __construct( - IManager $shareManager, - IGroupManager $groupManager, - IUserManager $userManager, - IRequest $request, - IRootFolder $rootFolder, - IURLGenerator $urlGenerator, - IUser $currentUser, - IL10N $l10n, - IConfig $config, - NotificationPublisher $notificationPublisher, - EventDispatcher $eventDispatcher, - SharingBlacklist $sharingBlacklist + $appName, + IRequest $request, + IManager $shareManager, + IGroupManager $groupManager, + IUserManager $userManager, + IRootFolder $rootFolder, + IURLGenerator $urlGenerator, + IUserSession $userSession, + IL10N $l10n, + IConfig $config, + NotificationPublisher $notificationPublisher, + EventDispatcher $eventDispatcher, + SharingBlacklist $sharingBlacklist ) { + parent::__construct($appName, $request); + $this->request = $request; $this->shareManager = $shareManager; - $this->userManager = $userManager; $this->groupManager = $groupManager; - $this->request = $request; + $this->userManager = $userManager; $this->rootFolder = $rootFolder; $this->urlGenerator = $urlGenerator; - $this->currentUser = $currentUser; $this->l = $l10n; $this->config = $config; $this->notificationPublisher = $notificationPublisher; $this->eventDispatcher = $eventDispatcher; $this->sharingBlacklist = $sharingBlacklist; $this->additionalInfoField = $this->config->getAppValue('core', 'user_additional_info_field', ''); + $this->userSession = $userSession; } /** @@ -144,12 +130,12 @@ private function getAdditionalUserInfo(IUser $user) { /** * Convert an IShare to an array for OCS output * - * @param \OCP\Share\IShare $share + * @param IShare $share * @param bool $received whether it's formatting received shares * @return array * @throws NotFoundException In case the node can't be resolved. */ - protected function formatShare(\OCP\Share\IShare $share, $received = false) { + protected function formatShare(IShare $share, $received = false) { $sharedBy = $this->userManager->get($share->getSharedBy()); $shareOwner = $this->userManager->get($share->getShareOwner()); @@ -172,14 +158,14 @@ protected function formatShare(\OCP\Share\IShare $share, $received = false) { $result['state'] = $share->getState(); // can only fetch path info if mounted already or if owner - if ($share->getState() === \OCP\Share::STATE_ACCEPTED || $share->getShareOwner() === $this->currentUser->getUID()) { - $userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); + if ($share->getState() === Share::STATE_ACCEPTED || $share->getShareOwner() === $this->userSession->getUser()->getUID()) { + $userFolder = $this->rootFolder->getUserFolder($this->userSession->getUser()->getUID()); } else { // need to go through owner user for pending shares $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner()); } } else { - $userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); + $userFolder = $this->rootFolder->getUserFolder($this->userSession->getUser()->getUID()); } $nodes = $userFolder->getById($share->getNodeId(), true); @@ -202,18 +188,18 @@ protected function formatShare(\OCP\Share\IShare $share, $received = false) { $result['file_parent'] = $node->getParent()->getId(); $result['file_target'] = $share->getTarget(); - if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { + if ($share->getShareType() === 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(); if ($sharedWith !== null) { $result['share_with_additional_info'] = $this->getAdditionalUserInfo($sharedWith); } - } elseif ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { + } elseif ($share->getShareType() === Share::SHARE_TYPE_GROUP) { $group = $this->groupManager->get($share->getSharedWith()); $result['share_with'] = $share->getSharedWith(); $result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith(); - } elseif ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { + } elseif ($share->getShareType() === Share::SHARE_TYPE_LINK) { $result['share_with'] = '***redacted***'; $result['share_with_displayname'] = '***redacted***'; $result['name'] = $share->getName(); @@ -227,7 +213,7 @@ protected function formatShare(\OCP\Share\IShare $share, $received = false) { if ($expiration !== null) { $result['expiration'] = $expiration->format('Y-m-d 00:00:00'); } - } elseif ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) { + } elseif ($share->getShareType() === Share::SHARE_TYPE_REMOTE) { $result['share_with'] = $share->getSharedWith(); $result['share_with_displayname'] = $share->getSharedWith(); $result['token'] = $share->getToken(); @@ -241,75 +227,84 @@ protected function formatShare(\OCP\Share\IShare $share, $received = false) { /** * Get a specific share by id * + * @NoCSRFRequired + * @NoAdminRequired + * * @param string $id - * @return \OC\OCS\Result + * @return Result */ public function getShare($id) { if (!$this->shareManager->shareApiEnabled()) { - return new \OC\OCS\Result(null, 404, $this->l->t('Share API is disabled')); + return new 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')); + return new 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]); + return new Result([$share]); } catch (NotFoundException $e) { //Fall trough } } - return new \OC\OCS\Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); + return new Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); } /** * Delete a share * + * @NoCSRFRequired + * @NoAdminRequired + * * @param string $id - * @return \OC\OCS\Result + * @return Result */ public function deleteShare($id) { if (!$this->shareManager->shareApiEnabled()) { - return new \OC\OCS\Result(null, 404, $this->l->t('Share API is disabled')); + return new 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')); + return new 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'); + return new 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')); + return new 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 new Result(); } /** - * @return \OC\OCS\Result + * @NoCSRFRequired + * @NoAdminRequired + * + * @return 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')); + return new Result(null, 404, $this->l->t('Share API is disabled')); } $name = $this->request->getParam('name', null); @@ -317,15 +312,15 @@ public function createShare() { // 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')); + return new Result(null, 404, $this->l->t('Please specify a file or folder path')); } - $userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); + $userFolder = $this->rootFolder->getUserFolder($this->userSession->getUser()->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')); + return new Result(null, 404, $this->l->t('Wrong path, file/folder doesn\'t exist')); } $share->setNode($path); @@ -333,7 +328,7 @@ public function createShare() { try { $share->getNode()->lock(ILockingProvider::LOCK_SHARED); } catch (LockedException $e) { - return new \OC\OCS\Result(null, 404, 'Could not create share'); + return new Result(null, 404, 'Could not create share'); } $shareType = (int)$this->request->getParam('shareType', '-1'); @@ -341,35 +336,35 @@ public function createShare() { // Parse permissions (if available) $permissions = $this->request->getParam('permissions', null); if ($permissions === null) { - if ($shareType !== \OCP\Share::SHARE_TYPE_LINK) { - $permissions = $this->config->getAppValue('core', 'shareapi_default_permissions', \OCP\Constants::PERMISSION_ALL); - $permissions |= \OCP\Constants::PERMISSION_READ; + if ($shareType !== Share::SHARE_TYPE_LINK) { + $permissions = $this->config->getAppValue('core', 'shareapi_default_permissions', Constants::PERMISSION_ALL); + $permissions |= Constants::PERMISSION_READ; } else { - $permissions = \OCP\Constants::PERMISSION_ALL; + $permissions = Constants::PERMISSION_ALL; } } else { $permissions = (int)$permissions; } - if ($permissions < 0 || $permissions > \OCP\Constants::PERMISSION_ALL) { + if ($permissions < 0 || $permissions > Constants::PERMISSION_ALL) { $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC\OCS\Result(null, 404, 'invalid permissions'); + return new Result(null, 404, 'invalid permissions'); } if ($permissions === 0) { - return new \OC\OCS\Result(null, 400, $this->l->t('Cannot remove all permissions')); + return new Result(null, 400, $this->l->t('Cannot remove all permissions')); } // link shares can have create-only without read (anonymous upload) - if ($shareType !== \OCP\Share::SHARE_TYPE_LINK && $permissions !== \OCP\Constants::PERMISSION_CREATE) { + if ($shareType !== Share::SHARE_TYPE_LINK && $permissions !== Constants::PERMISSION_CREATE) { // Shares always require read permissions - $permissions |= \OCP\Constants::PERMISSION_READ; + $permissions |= 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; + $permissions &= ~Constants::PERMISSION_DELETE; + $permissions &= ~Constants::PERMISSION_CREATE; } /* @@ -385,79 +380,79 @@ public function createShare() { $globalAutoAcceptValue = $this->config->getAppValue('core', 'shareapi_auto_accept_share', 'yes'); $autoAccept = $this->config->getUserValue($shareWith, 'files_sharing', 'auto_accept_share', $globalAutoAcceptValue) === 'yes'; - if ($shareType === \OCP\Share::SHARE_TYPE_USER) { + if ($shareType === 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')); + return new Result(null, 404, $this->l->t('Please specify a valid user')); } $share->setSharedWith($shareWith); $share->setPermissions($permissions); if ($autoAccept) { - $share->setState(\OCP\Share::STATE_ACCEPTED); + $share->setState(Share::STATE_ACCEPTED); } else { - $share->setState(\OCP\Share::STATE_PENDING); + $share->setState(Share::STATE_PENDING); } - } elseif ($shareType === \OCP\Share::SHARE_TYPE_GROUP) { + } elseif ($shareType === 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')); + return new 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')); + return new Result(null, 404, $this->l->t('Please specify a valid group')); } if ($this->sharingBlacklist->isGroupBlacklisted($this->groupManager->get($shareWith))) { - return new \OC\OCS\Result(null, 403, $this->l->t('The group is blacklisted for sharing')); + return new Result(null, 403, $this->l->t('The group is blacklisted for sharing')); } $share->setSharedWith($shareWith); $share->setPermissions($permissions); if ($autoAccept) { - $share->setState(\OCP\Share::STATE_ACCEPTED); + $share->setState(Share::STATE_ACCEPTED); } else { - $share->setState(\OCP\Share::STATE_PENDING); + $share->setState(Share::STATE_PENDING); } - } elseif ($shareType === \OCP\Share::SHARE_TYPE_LINK) { + } elseif ($shareType === 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')); + return new Result(null, 404, $this->l->t('Public link sharing is disabled by the administrator')); } // legacy way, expecting that this won't be used together with "create-only" shares $publicUpload = $this->request->getParam('publicUpload', null); // a few permission checks - if ($publicUpload === 'true' || $permissions === \OCP\Constants::PERMISSION_CREATE) { + if ($publicUpload === 'true' || $permissions === Constants::PERMISSION_CREATE) { // 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')); + return new 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')); + return new Result(null, 404, $this->l->t('Public upload is only possible for publicly shared folders')); } } // convert to permissions if ($publicUpload === 'true') { $share->setPermissions( - \OCP\Constants::PERMISSION_READ | - \OCP\Constants::PERMISSION_CREATE | - \OCP\Constants::PERMISSION_UPDATE | - \OCP\Constants::PERMISSION_DELETE + Constants::PERMISSION_READ | + Constants::PERMISSION_CREATE | + Constants::PERMISSION_UPDATE | + Constants::PERMISSION_DELETE ); - } elseif ($permissions === \OCP\Constants::PERMISSION_CREATE || - $permissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE)) { + } elseif ($permissions === Constants::PERMISSION_CREATE || + $permissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)) { $share->setPermissions($permissions); } else { // because when "publicUpload" is passed usually no permissions are set, // which defaults to ALL. But in the case of link shares we default to READ... - $share->setPermissions(\OCP\Constants::PERMISSION_READ); + $share->setPermissions(Constants::PERMISSION_READ); } // set name only if passed as parameter, empty string is allowed @@ -481,69 +476,69 @@ public function createShare() { $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')); + return new Result(null, 404, $this->l->t('Invalid date, date format must be YYYY-MM-DD')); } } - } elseif ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) { + } elseif ($shareType === 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])); + return new 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')); + return new Result(null, 400, $this->l->t('Unknown share type')); } $share->setShareType($shareType); - $share->setSharedBy($this->currentUser->getUID()); + $share->setSharedBy($this->userSession->getUser()->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()); + return new Result(null, $code, $e->getHint()); } catch (\Exception $e) { $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC\OCS\Result(null, 403, $e->getMessage()); + return new Result(null, 403, $e->getMessage()); } $share->getNode()->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED); $formattedShareAfterCreate = $this->formatShare($share); - return new \OC\OCS\Result($formattedShareAfterCreate); + return new Result($formattedShareAfterCreate); } /** * @param \OCP\Files\File|\OCP\Files\Folder $node * @param boolean $includeTags include tags in response * @param int|null $stateFilter state filter or empty for all, defaults to 0 (accepted) - * @return \OC\OCS\Result + * @return Result */ private function getSharedWithMe($node = null, $includeTags, $stateFilter = 0) { - $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); + $userShares = $this->shareManager->getSharedWith($this->userSession->getUser()->getUID(), Share::SHARE_TYPE_USER, $node, -1, 0); + $groupShares = $this->shareManager->getSharedWith($this->userSession->getUser()->getUID(), Share::SHARE_TYPE_GROUP, $node, -1, 0); $shares = \array_merge($userShares, $groupShares); $shares = \array_filter($shares, function (IShare $share) { - return $share->getShareOwner() !== $this->currentUser->getUID(); + return $share->getShareOwner() !== $this->userSession->getUser()->getUID(); }); $formatted = []; foreach ($shares as $share) { if (($stateFilter === null || $share->getState() === $stateFilter) && - $this->canAccessShare($share)) { + $this->canAccessShare($share)) { try { /** * Check if the group to which the user belongs is not allowed * to reshare */ - if ($this->shareManager->sharingDisabledForUser($this->currentUser->getUID())) { + if ($this->shareManager->sharingDisabledForUser($this->userSession->getUser()->getUID())) { /** * Now set the permission to 15. Which will allow not to reshare. */ @@ -561,27 +556,27 @@ private function getSharedWithMe($node = null, $includeTags, $stateFilter = 0) { $formatted = \OCA\Files\Helper::populateTags($formatted, 'file_source'); } - return new \OC\OCS\Result($formatted); + return new Result($formatted); } /** * @param \OCP\Files\Folder $folder - * @return \OC\OCS\Result + * @return Result */ private function getSharesInDir($folder) { if (!($folder instanceof \OCP\Files\Folder)) { - return new \OC\OCS\Result(null, 400, $this->l->t('Not a directory')); + return new Result(null, 400, $this->l->t('Not a directory')); } $nodes = $folder->getDirectoryListing(); - /** @var \OCP\Share\IShare[] $shares */ + /** @var 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)); + $shares = \array_merge($shares, $this->shareManager->getSharesBy($this->userSession->getUser()->getUID(), Share::SHARE_TYPE_USER, $node, false, -1, 0)); + $shares = \array_merge($shares, $this->shareManager->getSharesBy($this->userSession->getUser()->getUID(), Share::SHARE_TYPE_GROUP, $node, false, -1, 0)); + $shares = \array_merge($shares, $this->shareManager->getSharesBy($this->userSession->getUser()->getUID(), 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)); + $shares = \array_merge($shares, $this->shareManager->getSharesBy($this->userSession->getUser()->getUID(), Share::SHARE_TYPE_REMOTE, $node, false, -1, 0)); } } @@ -594,23 +589,26 @@ private function getSharesInDir($folder) { } } - return new \OC\OCS\Result($formatted); + return new Result($formatted); } /** * The getShares function. * + * @NoCSRFRequired + * @NoAdminRequired + * * - 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 + * @return Result */ public function getShares() { if (!$this->shareManager->shareApiEnabled()) { - return new \OC\OCS\Result(); + return new Result(); } $sharedWithMe = $this->request->getParam('shared_with_me', null); @@ -621,21 +619,21 @@ public function getShares() { $includeTags = $this->request->getParam('include_tags', false); if ($path !== null) { - $userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); + $userFolder = $this->rootFolder->getUserFolder($this->userSession->getUser()->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')); + return new 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')); + return new Result(null, 404, $this->l->t('Could not lock path')); } } if ($sharedWithMe === 'true') { - $stateFilter = $this->request->getParam('state', \OCP\Share::STATE_ACCEPTED); + $stateFilter = $this->request->getParam('state', Share::STATE_ACCEPTED); if ($stateFilter === '') { - $stateFilter = \OCP\Share::STATE_ACCEPTED; + $stateFilter = Share::STATE_ACCEPTED; } elseif ($stateFilter === 'all') { $stateFilter = null; // which means all } else { @@ -663,13 +661,13 @@ public function getShares() { } // 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); + $userShares = $this->shareManager->getSharesBy($this->userSession->getUser()->getUID(), Share::SHARE_TYPE_USER, $path, $reshares, -1, 0); + $groupShares = $this->shareManager->getSharesBy($this->userSession->getUser()->getUID(), Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0); + $linkShares = $this->shareManager->getSharesBy($this->userSession->getUser()->getUID(), 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); + $federatedShares = $this->shareManager->getSharesBy($this->userSession->getUser()->getUID(), Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0); $shares = \array_merge($shares, $federatedShares); } @@ -690,29 +688,32 @@ public function getShares() { $path->unlock(ILockingProvider::LOCK_SHARED); } - return new \OC\OCS\Result($formatted); + return new Result($formatted); } /** + * @NoCSRFRequired + * @NoAdminRequired + * * @param int $id - * @return \OC\OCS\Result + * @return Result */ public function updateShare($id) { if (!$this->shareManager->shareApiEnabled()) { - return new \OC\OCS\Result(null, 404, $this->l->t('Share API is disabled')); + return new 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')); + return new 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')); + return new Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); } $permissions = $this->request->getParam('permissions', null); @@ -724,17 +725,17 @@ public function updateShare($id) { /* * expirationdate, password and publicUpload only make sense for link shares */ - if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { + if ($share->getShareType() === Share::SHARE_TYPE_LINK) { if ($permissions === null && $password === null && $publicUpload === null && $expireDate === null && $name === null) { $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC\OCS\Result(null, 400, 'Wrong or no update parameter given'); + return new 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 | \OCP\Constants::PERMISSION_DELETE; + $newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE; } elseif ($publicUpload === 'false') { - $newPermissions = \OCP\Constants::PERMISSION_READ; + $newPermissions = Constants::PERMISSION_READ; } if ($permissions !== null) { @@ -742,49 +743,49 @@ public function updateShare($id) { } if ($newPermissions !== null && - $newPermissions !== \OCP\Constants::PERMISSION_READ && - $newPermissions !== \OCP\Constants::PERMISSION_CREATE && + $newPermissions !== Constants::PERMISSION_READ && + $newPermissions !== Constants::PERMISSION_CREATE && // legacy - $newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE) && + $newPermissions !== (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE) && // correct - $newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) + $newPermissions !== (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE) ) { $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC\OCS\Result(null, 400, $this->l->t('Can\'t change permissions for public share links')); + return new Result(null, 400, $this->l->t('Can\'t change permissions for public share links')); } if ( // legacy - $newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE) || + $newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE) || // correct - $newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) + $newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE) ) { 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')); + return new 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')); + return new Result(null, 400, $this->l->t('Public upload is only possible for publicly shared folders')); } // normalize to correct public upload permissions - $newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; + $newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE; } // create-only (upload-only) if ( - $newPermissions === \OCP\Constants::PERMISSION_CREATE + $newPermissions === Constants::PERMISSION_CREATE ) { 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')); + return new 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')); + return new Result(null, 400, $this->l->t('Public upload is only possible for publicly shared folders')); } } @@ -806,7 +807,7 @@ public function updateShare($id) { $expireDate = $this->parseDate($expireDate); } catch (\Exception $e) { $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC\OCS\Result(null, 400, $e->getMessage()); + return new Result(null, 400, $e->getMessage()); } $share->setExpirationDate($expireDate); } @@ -820,17 +821,17 @@ public function updateShare($id) { // 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')); + return new Result(null, 400, $this->l->t('Wrong or no update parameter given')); } else { $permissions = (int)$permissions; $share->setPermissions($permissions); } } - if ($permissions !== null && $share->getShareOwner() !== $this->currentUser->getUID()) { + if ($permissions !== null && $share->getShareOwner() !== $this->userSession->getUser()->getUID()) { /* Check if this is an incoming 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)); + $incomingShares = $this->shareManager->getSharedWith($this->userSession->getUser()->getUID(), Share::SHARE_TYPE_USER, $share->getNode(), -1, 0); + $incomingShares = \array_merge($incomingShares, $this->shareManager->getSharedWith($this->userSession->getUser()->getUID(), Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0)); if (!empty($incomingShares)) { $maxPermissions = 0; @@ -840,65 +841,161 @@ public function updateShare($id) { if ($share->getPermissions() & ~$maxPermissions) { $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC\OCS\Result(null, 404, $this->l->t('Cannot increase permissions')); + return new Result(null, 404, $this->l->t('Cannot increase permissions')); } } } if ($share->getPermissions() === 0) { - return new \OC\OCS\Result(null, 400, $this->l->t('Cannot remove all permissions')); + return new Result(null, 400, $this->l->t('Cannot remove all 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()); + return new Result(null, 400, $e->getMessage()); } $share->getNode()->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED); - return new \OC\OCS\Result($this->formatShare($share)); + return new Result($this->formatShare($share)); } /** + * @NoCSRFRequired + * @NoAdminRequired + * * @param int $id - * @return \OC\OCS\Result + * @return Result */ public function acceptShare($id) { - return $this->updateShareState($id, \OCP\Share::STATE_ACCEPTED); + return $this->updateShareState($id, Share::STATE_ACCEPTED); } /** + * @NoCSRFRequired + * @NoAdminRequired + * * @param int $id - * @return \OC\OCS\Result + * @return Result */ public function declineShare($id) { - return $this->updateShareState($id, \OCP\Share::STATE_REJECTED); + return $this->updateShareState($id, Share::STATE_REJECTED); + } + + /** + * Send a notification to share recipient(s) + * + * @NoCSRFRequired + * @NoAdminRequired + * + * @param int $itemSource + * @param int $shareType + * @param string $recipient + * + * @return Result + */ + public function notifyRecipients($itemSource, $shareType, $recipient) { + $recipientList = []; + if ($shareType === Share::SHARE_TYPE_USER) { + $recipientList[] = $this->userManager->get($recipient); + } elseif ($shareType === Share::SHARE_TYPE_GROUP) { + $group = \OC::$server->getGroupManager()->get($recipient); + $recipientList = $group->searchUsers(''); + } + // don't send a mail to the user who shared the file + $recipientList = \array_filter($recipientList, function ($user) { + /** @var IUser $user */ + return $user->getUID() !== $this->userSession->getUser()->getUID(); + }); + + $defaults = new \OCP\Defaults(); + $mailNotification = new \OC\Share\MailNotifications( + $this->shareManager, + $this->userSession->getUser(), + \OC::$server->getL10N('lib'), + \OC::$server->getMailer(), + $this->config, + \OC::$server->getLogger(), + $defaults, + $this->urlGenerator, + $this->eventDispatcher + ); + + $userFolder = $this->rootFolder->getUserFolder($this->userSession->getUser()->getUID()); + $nodes = $userFolder->getById($itemSource, true); + $node = $nodes[0] ?? null; + $result = $mailNotification->sendInternalShareMail($node, $shareType, $recipientList); + + // if we were able to send to at least one recipient, mark as sent + // allowing the user to resend would spam users who already got a notification + if (\count($result) < \count($recipientList)) { + $items = $this->shareManager->getSharedWith($recipient, $shareType, $node); + if (\count($items) > 0) { + $share = $items[0]; + $share->setMailSend(true); + $this->shareManager->updateShare($share); + } + } + + $message = empty($result) + ? null + : $this->l->t( + "Couldn't send mail to following recipient(s): %s ", + \implode(', ', $result) + ); + return new Result([], 200, $message); + } + + /** + * Just mark a notification to share recipient(s) as sent + * + * @NoCSRFRequired + * @NoAdminRequired + * + * @param int $itemSource + * @param int $shareType + * @param string $recipient + * + * @return Result + */ + public function notifyRecipientsDisabled($itemSource, $shareType, $recipient) { + $userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); + $nodes = $userFolder->getById($itemSource); + $node = $nodes[0]; + + $items = $this->shareManager->getSharedWith($recipient, $shareType, $node); + if (\count($items) > 0) { + $share = $items[0]; + $share->setMailSend(true); + $this->shareManager->updateShare($share); + } + return new Result(); } /** * @param $id * @param $state - * @return \OC\OCS\Result + * @return Result */ private function updateShareState($id, $state) { $eventName = ''; - if ($state === \OCP\Share::STATE_ACCEPTED) { + if ($state === Share::STATE_ACCEPTED) { $eventName = 'accept'; - } elseif ($state === \OCP\Share::STATE_REJECTED) { + } elseif ($state === Share::STATE_REJECTED) { $eventName = 'reject'; } if (!$this->shareManager->shareApiEnabled()) { - return new \OC\OCS\Result(null, 404, $this->l->t('Share API is disabled')); + return new Result(null, 404, $this->l->t('Share API is disabled')); } try { - $share = $this->getShareById($id, $this->currentUser->getUID()); + $share = $this->getShareById($id, $this->userSession->getUser()->getUID()); $this->eventDispatcher->dispatch('share.before' . $eventName, new GenericEvent(null, ['share' => $share])); } catch (ShareNotFound $e) { - return new \OC\OCS\Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); + return new Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); } $node = $share->getNode(); @@ -907,14 +1004,14 @@ private function updateShareState($id, $state) { // this checks that we are either the owner or recipient if (!$this->canAccessShare($share)) { $node->unlock(ILockingProvider::LOCK_SHARED); - return new \OC\OCS\Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); + return new Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); } // only recipient can accept/reject share - if ($share->getShareOwner() === $this->currentUser->getUID() || - $share->getSharedBy() === $this->currentUser->getUID()) { + if ($share->getShareOwner() === $this->userSession->getUser()->getUID() || + $share->getSharedBy() === $this->userSession->getUser()->getUID()) { $node->unlock(ILockingProvider::LOCK_SHARED); - return new \OC\OCS\Result(null, 403, $this->l->t('Only recipient can change accepted state')); + return new Result(null, 403, $this->l->t('Only recipient can change accepted state')); } if ($share->getState() === $state) { @@ -923,16 +1020,16 @@ private function updateShareState($id, $state) { } // if there are no changes in the state, just return the share as if the change was successful $node->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED); - return new \OC\OCS\Result([$this->formatShare($share, true)]); + return new Result([$this->formatShare($share, true)]); } // we actually want to update all shares related to the node in case there are multiple // incoming shares for the same node (ex: receiving simultaneously through group share and user share) - $allShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $node, -1, 0); - $allShares = \array_merge($allShares, $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $node, -1, 0)); + $allShares = $this->shareManager->getSharedWith($this->userSession->getUser()->getUID(), Share::SHARE_TYPE_USER, $node, -1, 0); + $allShares = \array_merge($allShares, $this->shareManager->getSharedWith($this->userSession->getUser()->getUID(), Share::SHARE_TYPE_GROUP, $node, -1, 0)); // resolve and deduplicate target if accepting - if ($state === \OCP\Share::STATE_ACCEPTED) { + if ($state === Share::STATE_ACCEPTED) { $share = $this->deduplicateShareTarget($share); } @@ -942,11 +1039,11 @@ private function updateShareState($id, $state) { foreach ($allShares as $aShare) { $aShare->setState($share->getState()); $aShare->setTarget($share->getTarget()); - $this->shareManager->updateShareForRecipient($aShare, $this->currentUser->getUID()); + $this->shareManager->updateShareForRecipient($aShare, $this->userSession->getUser()->getUID()); } } catch (\Exception $e) { $share->getNode()->unlock(ILockingProvider::LOCK_SHARED); - return new \OC\OCS\Result(null, 400, $e->getMessage()); + return new Result(null, 400, $e->getMessage()); } $node->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED); @@ -955,14 +1052,14 @@ private function updateShareState($id, $state) { \OC\Files\Filesystem::tearDown(); // FIXME: trigger mount for user to make sure the new node is mounted already // before formatShare resolves it - $this->rootFolder->getUserFolder($this->currentUser->getUID()); + $this->rootFolder->getUserFolder($this->userSession->getUser()->getUID()); - $this->notificationPublisher->discardNotificationForUser($share, $this->currentUser->getUID()); + $this->notificationPublisher->discardNotificationForUser($share, $this->userSession->getUser()->getUID()); if ($eventName !== '') { $this->eventDispatcher->dispatch('share.after' . $eventName, new GenericEvent(null, ['share' => $share])); } - return new \OC\OCS\Result([$this->formatShare($share, true)]); + return new Result([$this->formatShare($share, true)]); } /** @@ -973,7 +1070,7 @@ private function updateShareState($id, $state) { * @return IShare same share with target updated if necessary */ private function deduplicateShareTarget(IShare $share) { - $userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); + $userFolder = $this->rootFolder->getUserFolder($this->userSession->getUser()->getUID()); $mountPoint = \basename($share->getTarget()); $parentDir = \dirname($share->getTarget()); if (!$userFolder->nodeExists($parentDir)) { @@ -999,33 +1096,33 @@ private function deduplicateShareTarget(IShare $share) { } /** - * @param \OCP\Share\IShare $share + * @param IShare $share * @return bool */ - protected function canAccessShare(\OCP\Share\IShare $share) { + protected function canAccessShare(IShare $share) { // A file with permissions 0 can't be accessed by us, // unless it's a rejected sub-group share in which case we want it visible to let the user accept it again if ($share->getPermissions() === 0 - && !($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP && $share->getState() === \OCP\Share::STATE_REJECTED)) { + && !($share->getShareType() === Share::SHARE_TYPE_GROUP && $share->getState() === Share::STATE_REJECTED)) { 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() + if ($share->getShareOwner() === $this->userSession->getUser()->getUID() || + $share->getSharedBy() === $this->userSession->getUser()->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()) { + if ($share->getShareType() === Share::SHARE_TYPE_USER && + $share->getSharedWith() === $this->userSession->getUser()->getUID()) { return true; } - if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { + if ($share->getShareType() === Share::SHARE_TYPE_GROUP) { $sharedWith = $this->groupManager->get($share->getSharedWith()); - if ($sharedWith !== null && $sharedWith->inGroup($this->currentUser)) { + if ($sharedWith !== null && $sharedWith->inGroup($this->userSession->getUser())) { return true; } } @@ -1064,7 +1161,7 @@ private function parseDate($expireDate) { * not support this we need to check all backends. * * @param string $id - * @return \OCP\Share\IShare + * @return IShare * @throws ShareNotFound */ private function getShareById($id, $recipient = null) { diff --git a/apps/files_sharing/lib/Notifier.php b/apps/files_sharing/lib/Notifier.php index 9f5ca1c9b37a..0cdea6bc72db 100644 --- a/apps/files_sharing/lib/Notifier.php +++ b/apps/files_sharing/lib/Notifier.php @@ -19,7 +19,7 @@ * */ -namespace OCA\Files_sharing; +namespace OCA\Files_Sharing; use OCP\Notification\INotification; use OCP\Notification\INotifier; diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php index 10e764da11cc..c3e64838691a 100644 --- a/apps/files_sharing/tests/ApiTest.php +++ b/apps/files_sharing/tests/ApiTest.php @@ -31,6 +31,7 @@ use OCP\Constants; use OCP\IL10N; use OCP\IRequest; +use OCP\IUserSession; use OCP\Share; use OCA\Files_Sharing\Service\NotificationPublisher; use OCA\Files_Sharing\SharingBlacklist; @@ -104,10 +105,12 @@ private function createRequest(array $data) { /** * @param \OCP\IRequest $request * @param string $userId The userId of the caller - * @return \OCA\Files_Sharing\API\Share20OCS + * @return \OCA\Files_Sharing\Controller\Share20OcsController */ private function createOCS($request, $userId) { $currentUser = \OC::$server->getUserManager()->get($userId); + $userSession = $this->createMock(IUserSession::class); + $userSession->method('getUser')->willReturn($currentUser); $l = $this->createMock(IL10N::class); $l->method('t') @@ -115,14 +118,15 @@ private function createOCS($request, $userId) { return \vsprintf($text, $parameters); })); - return new \OCA\Files_Sharing\API\Share20OCS( + return new \OCA\Files_Sharing\Controller\Share20OcsController( + 'files_sharing', + $request, $this->shareManager, \OC::$server->getGroupManager(), \OC::$server->getUserManager(), - $request, \OC::$server->getRootFolder(), \OC::$server->getURLGenerator(), - $currentUser, + $userSession, $l, \OC::$server->getConfig(), \OC::$server->getAppContainer('files_sharing')->query(NotificationPublisher::class), diff --git a/apps/files_sharing/tests/AppInfo/ApplicationTest.php b/apps/files_sharing/tests/AppInfo/ApplicationTest.php new file mode 100644 index 000000000000..82da9ab3b8a5 --- /dev/null +++ b/apps/files_sharing/tests/AppInfo/ApplicationTest.php @@ -0,0 +1,36 @@ + + * + * @copyright Copyright (c) 2018, ownCloud GmbH + * @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\AppInfo; + +use OCA\Files_Sharing\AppInfo\Application; +use OCA\Files_Sharing\Tests\TestCase; + +/** + * Class ApplicationTest + * @group DB + */ +class ApplicationTest extends TestCase { + public function testConstructor() { + $app = new Application(); + $app->getContainer()->query('Share20OcsController'); + } +} diff --git a/apps/files_sharing/tests/API/Share20OCSTest.php b/apps/files_sharing/tests/Controller/Share20OcsControllerTest.php similarity index 98% rename from apps/files_sharing/tests/API/Share20OCSTest.php rename to apps/files_sharing/tests/Controller/Share20OcsControllerTest.php index dcdd0b149fed..667f4eb6bd2b 100644 --- a/apps/files_sharing/tests/API/Share20OCSTest.php +++ b/apps/files_sharing/tests/Controller/Share20OcsControllerTest.php @@ -25,7 +25,7 @@ namespace OCA\Files_Sharing\Tests\API; use OC\OCS\Result; -use OCA\Files_Sharing\API\Share20OCS; +use OCA\Files_Sharing\Controller\Share20OcsController; use OCA\Files_Sharing\Service\NotificationPublisher; use OCA\Files_Sharing\SharingBlacklist; use OCP\Files\IRootFolder; @@ -38,6 +38,7 @@ use OCP\IUser; use OCP\IGroup; use OCP\IUserManager; +use OCP\IUserSession; use OCP\Lock\LockedException; use OCP\Share; use Symfony\Component\EventDispatcher\EventDispatcher; @@ -48,12 +49,12 @@ use OCP\Share\Exceptions\ShareNotFound; /** - * Class Share20OCSTest + * Class Share20OcsControllerTest * - * @package OCA\Files_Sharing\Tests\API + * @package OCA\Files_Sharing\Tests\Controller * @group DB */ -class Share20OCSTest extends TestCase { +class Share20OcsControllerTest extends TestCase { /** @var \OC\Share20\Manager | \PHPUnit_Framework_MockObject_MockObject */ private $shareManager; @@ -76,7 +77,10 @@ class Share20OCSTest extends TestCase { /** @var IUser */ private $currentUser; - /** @var Share20OCS */ + /** @var IUserSession */ + private $userSession; + + /** @var Share20OcsController */ private $ocs; /** @var IL10N */ @@ -88,6 +92,8 @@ class Share20OCSTest extends TestCase { private $eventDispatcher; /** @var SharingBlacklist */ private $sharingBlacklist; + /** @var IConfig */ + private $config; protected function setUp() { $this->shareManager = $this->getMockBuilder('OCP\Share\IManager') @@ -104,8 +110,10 @@ protected function setUp() { $this->urlGenerator = $this->createMock('OCP\IURLGenerator'); $this->currentUser = $this->createMock('OCP\IUser'); $this->currentUser->method('getUID')->willReturn('currentUser'); + $this->userSession = $this->createMock(IUserSession::class); + $this->userSession->method('getUser')->willReturn($this->currentUser); - $this->userManager->expects($this->any())->method('userExists')->willReturn(true); + $this->userManager->method('userExists')->willReturn(true); $this->l = $this->createMock('\OCP\IL10N'); $this->l->method('t') @@ -124,14 +132,15 @@ protected function setUp() { $this->eventDispatcher = $this->createMock(EventDispatcher::class); $this->sharingBlacklist = $this->createMock(SharingBlacklist::class); - $this->ocs = new Share20OCS( + $this->ocs = new Share20OcsController( + 'files_sharing', + $this->request, $this->shareManager, $this->groupManager, $this->userManager, - $this->request, $this->rootFolder, $this->urlGenerator, - $this->currentUser, + $this->userSession, $this->l, $this->config, $this->notificationPublisher, @@ -144,16 +153,20 @@ public function tearDown() { parent::tearDown(); } + /** + * @return Share20OcsController | \PHPUnit_Framework_MockObject_MockObject + */ private function mockFormatShare() { - return $this->getMockBuilder(\OCA\Files_Sharing\API\Share20OCS::class) + return $this->getMockBuilder(Share20OcsController::class) ->setConstructorArgs([ + 'files_sharing', + $this->request, $this->shareManager, $this->groupManager, $this->userManager, - $this->request, $this->rootFolder, $this->urlGenerator, - $this->currentUser, + $this->userSession, $this->l, $this->config, $this->notificationPublisher, @@ -470,15 +483,16 @@ public function dataGetShare() { * @dataProvider dataGetShare */ public function testGetShare(\OCP\Share\IShare $share, array $result) { - $ocs = $this->getMockBuilder('OCA\Files_Sharing\API\Share20OCS') + $ocs = $this->getMockBuilder(Share20OcsController::class) ->setConstructorArgs([ + 'files_sharing', + $this->request, $this->shareManager, $this->groupManager, $this->userManager, - $this->request, $this->rootFolder, $this->urlGenerator, - $this->currentUser, + $this->userSession, $this->l, $this->config, $this->notificationPublisher, @@ -487,7 +501,7 @@ public function testGetShare(\OCP\Share\IShare $share, array $result) { ])->setMethods(['canAccessShare']) ->getMock(); - $ocs->method('canAccessShare')->willReturn(true); + $ocs->expects($this->any())->method('canAccessShare')->willReturn(true); $this->shareManager ->expects($this->once()) @@ -2757,7 +2771,7 @@ public function testFormatShare(array $expects, \OCP\Share\IShare $share, array } /** - * @return Share20OCS + * @return Share20OcsController */ public function getOcsDisabledAPI() { $shareManager = $this->getMockBuilder('OCP\Share\IManager') @@ -2768,14 +2782,15 @@ public function getOcsDisabledAPI() { ->method('shareApiEnabled') ->willReturn(false); - return new Share20OCS( + return new Share20OcsController( + 'files_sharing', + $this->request, $shareManager, $this->groupManager, $this->userManager, - $this->request, $this->rootFolder, $this->urlGenerator, - $this->currentUser, + $this->userSession, $this->l, $this->config, $this->notificationPublisher, @@ -2861,14 +2876,15 @@ public function testGetShareAdditionalInfo($configValue, $expectedInfo) { $recipient->method('getUID')->willReturn('recipient_id'); $recipient->method('getEMailAddress')->willReturn('email@example.com'); - $ocs = new Share20OCS( + $ocs = new Share20OcsController( + 'files_sharing', + $this->request, $this->shareManager, $this->groupManager, $this->userManager, - $this->request, $this->rootFolder, $this->urlGenerator, - $this->currentUser, + $this->userSession, $this->l, $config, $this->notificationPublisher, @@ -2976,7 +2992,7 @@ public function testGetSharesAll($requestedPath, $requestedReshares, $fedAllowed $this->shareManager->method('outgoingServer2ServerSharesAllowed')->willReturn($fedAllowed); $ocs = $this->mockFormatShare(); - $ocs->method('formatShare')->will($this->returnArgument(0)); + $ocs->expects($this->any())->method('formatShare')->will($this->returnArgument(0)); $result = $ocs->getShares(); if ($fedAllowed) { @@ -3096,7 +3112,7 @@ public function testGetSharesSharedWithMe($requestedPath, $stateFilter) { ])); $ocs = $this->mockFormatShare(); - $ocs->method('formatShare')->will($this->returnArgument(0)); + $ocs->expects($this->any())->method('formatShare')->will($this->returnArgument(0)); $result = $ocs->getShares(); $this->assertContains($userShare, $result->getData(), 'result contains user share'); @@ -3173,7 +3189,7 @@ public function testGetSharesSharedWithMeAndBlockGroup() { ])); $ocs = $this->mockFormatShare(); - $ocs->method('formatShare')->will($this->returnArgument(0)); + $ocs->expects($this->any())->method('formatShare')->will($this->returnArgument(0)); $result = $ocs->getShares(); $this->assertEquals($userShare->getPermissions(), $result->getData()[0]->getPermissions()); } @@ -3257,7 +3273,7 @@ public function testAcceptRejectShare($method, $target, $targetExists, $expected ->willReturn($userFolder); $ocs = $this->mockFormatShare(); - $ocs->method('formatShare')->will($this->returnArgument(0)); + $ocs->expects($this->any())->method('formatShare')->will($this->returnArgument(0)); $result = $ocs->$method(123); $this->assertEquals(100, $result->getStatusCode()); @@ -3387,7 +3403,7 @@ public function testAcceptRejectShareMultiple($method, $target, $targetExists, $ ->willReturn($userFolder); $ocs = $this->mockFormatShare(); - $ocs->method('formatShare')->will($this->returnArgument(0)); + $ocs->expects($this->any())->method('formatShare')->will($this->returnArgument(0)); $result = $ocs->$method(123); $this->assertEquals(100, $result->getStatusCode()); diff --git a/apps/files_sharing/tests/Service/NotificationPublisherTest.php b/apps/files_sharing/tests/Service/NotificationPublisherTest.php index 5640b232b96f..7ee69a4c110c 100644 --- a/apps/files_sharing/tests/Service/NotificationPublisherTest.php +++ b/apps/files_sharing/tests/Service/NotificationPublisherTest.php @@ -29,7 +29,7 @@ use OCP\IUser; /** - * Class Share20OCSTest + * Class NotificationPublisherTest * * @package OCA\Files_Sharing\Tests\Service * @group DB diff --git a/core/ajax/share.php b/core/ajax/share.php index 8f054c3494e5..74d88c0d6e31 100644 --- a/core/ajax/share.php +++ b/core/ajax/share.php @@ -36,7 +36,6 @@ */ use OC\Share\Filters\MailNotificationFilter; -use OCP\IUser; OC_JSON::checkLoggedIn(); OCP\JSON::callCheck(); @@ -77,91 +76,8 @@ function displayNamesInGroups($gids, $search = '', $limit = -1, $offset = 0) { return $displayNames; } -/** - * @param $gid - * @param string $search - * @param int $limit - * @param int $offset - * @return array - */ -function usersInGroup($gid, $search = '', $limit = -1, $offset = 0) { - $group = \OC::$server->getGroupManager()->get($gid); - if ($group) { - $users = $group->searchUsers($search, $limit, $offset); - $userIds = []; - foreach ($users as $user) { - $userIds[] = $user->getUID(); - } - return $userIds; - } else { - return []; - } -} - if (isset($_POST['action'], $_POST['itemType'], $_POST['itemSource'])) { switch ($_POST['action']) { - case 'informRecipients': - $l = \OC::$server->getL10N('core'); - $shareType = (int) $_POST['shareType']; - $itemType = (string)$_POST['itemType']; - $itemSource = (string)$_POST['itemSource']; - $recipient = (string)$_POST['recipient']; - - $userManager = \OC::$server->getUserManager(); - $recipientList = []; - if ($shareType === \OCP\Share::SHARE_TYPE_USER) { - $recipientList[] = $userManager->get($recipient); - } elseif ($shareType === \OCP\Share::SHARE_TYPE_GROUP) { - $recipientList = usersInGroup($recipient); - $group = \OC::$server->getGroupManager()->get($recipient); - $recipientList = $group->searchUsers(''); - } - // don't send a mail to the user who shared the file - $recipientList = \array_filter($recipientList, function ($user) { - /** @var IUser $user */ - return $user->getUID() !== \OCP\User::getUser(); - }); - - $mailNotification = new \OC\Share\MailNotifications( - \OC::$server->getUserSession()->getUser(), - \OC::$server->getL10N('lib'), - \OC::$server->getMailer(), - \OC::$server->getConfig(), - \OC::$server->getLogger(), - $defaults, - \OC::$server->getURLGenerator(), - \OC::$server->getEventDispatcher() - ); - - $result = $mailNotification->sendInternalShareMail($recipientList, $itemSource, $itemType); - - // if we were able to send to at least one recipient, mark as sent - // allowing the user to resend would spam users who already got a notification - if (\count($result) < \count($recipientList)) { - \OCP\Share::setSendMailStatus($itemType, $itemSource, $shareType, $recipient, true); - } - - if (empty($result)) { - OCP\JSON::success(); - } else { - OCP\JSON::error([ - 'data' => [ - 'message' => $l->t("Couldn't send mail to following recipient(s): %s ", - \implode(', ', $result) - ) - ] - ]); - } - break; - case 'informRecipientsDisabled': - $itemSource = (string)$_POST['itemSource']; - $shareType = (int)$_POST['shareType']; - $itemType = (string)$_POST['itemType']; - $recipient = (string)$_POST['recipient']; - \OCP\Share::setSendMailStatus($itemType, $itemSource, $shareType, $recipient, false); - OCP\JSON::success(); - break; - case 'email': $emailBody = null; @@ -194,6 +110,7 @@ function usersInGroup($gid, $search = '', $limit = -1, $offset = 0) { $sendingUser = \OC::$server->getUserSession()->getUser(); $mailNotification = new \OC\Share\MailNotifications( + \OC::$server->getShareManager(), $sendingUser, $l10n, \OC::$server->getMailer(), diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js index 9593a1a3d7dc..6012055e5330 100644 --- a/core/js/sharedialogshareelistview.js +++ b/core/js/sharedialogshareelistview.js @@ -300,12 +300,12 @@ $loading.removeClass('hidden'); this.model.sendNotificationForShare(shareType, shareWith, true).then(function(result) { - if (result.status === 'success') { + if (result.ocs.meta.status === 'ok') { OC.Notification.showTemporary(t('core', 'Email notification was sent!')); $target.remove(); } else { // sending was successful but some users might not have any email address - OC.dialogs.alert(t('core', result.data.message), t('core', 'Email notification not sent')); + OC.dialogs.alert(t('core', result.ocs.meta.message), t('core', 'Email notification not sent')); } $target.removeClass('hidden'); diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js index 4e34dafed35f..0fb11352a986 100644 --- a/core/js/shareitemmodel.js +++ b/core/js/shareitemmodel.js @@ -416,11 +416,13 @@ sendNotificationForShare: function(shareType, shareWith, state) { var itemType = this.get('itemType'); var itemSource = this.get('itemSource'); + var baseUrl = OC.linkToOCS('/apps/files_sharing/api/v1/notification/', 2); + var action = state ? 'send' : 'marksent'; return $.post( - OC.generateUrl('core/ajax/share.php'), + baseUrl + action, { - action: state ? 'informRecipients' : 'informRecipientsDisabled', + format: 'json', recipient: shareWith, shareType: shareType, itemSource: itemSource, diff --git a/core/js/tests/specs/sharedialogshareelistview.js b/core/js/tests/specs/sharedialogshareelistview.js index 52a83d3a49ac..910dc93269c4 100644 --- a/core/js/tests/specs/sharedialogshareelistview.js +++ b/core/js/tests/specs/sharedialogshareelistview.js @@ -188,7 +188,7 @@ describe('OC.Share.ShareDialogShareeListView', function () { expect(notificationStub.called).toEqual(true); notificationStub.restore(); - deferred.resolve({status: 'success'}); + deferred.resolve({ ocs: { meta: {status: 'ok' }}}); expect(notifStub.calledOnce).toEqual(true); notifStub.restore(); @@ -213,7 +213,7 @@ describe('OC.Share.ShareDialogShareeListView', function () { expect(notificationStub.called).toEqual(true); notificationStub.restore(); - deferred.resolve({status: 'error', data: {message: 'message'}}); + deferred.resolve({ ocs: { meta: {status: 'error', message: 'message'}}}); expect(notifStub.calledOnce).toEqual(true); notifStub.restore(); diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php index c3ad2ad564c5..29fceb02d417 100644 --- a/lib/private/AppFramework/DependencyInjection/DIContainer.php +++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php @@ -31,7 +31,6 @@ namespace OC\AppFramework\DependencyInjection; use OC; -use OC\AppFramework\Core\API; use OC\AppFramework\Http; use OC\AppFramework\Http\Dispatcher; use OC\AppFramework\Http\Output; @@ -42,6 +41,7 @@ use OC\AppFramework\Utility\SimpleContainer; use OC\Core\Middleware\AccountModuleMiddleware; use OC\Core\Middleware\TwoFactorMiddleware; +use OCP\API; use OCP\App\IServiceLoader; use OCP\AppFramework\IApi; use OCP\AppFramework\IAppContainer; diff --git a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php index 88d048542bd4..78726ed6f99d 100644 --- a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php +++ b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php @@ -33,13 +33,16 @@ use OC\AppFramework\Middleware\Security\Exceptions\NotLoggedInException; use OC\AppFramework\Utility\ControllerMethodReflector; use OC\Core\Controller\LoginController; +use OC\OCS\Result; use OC\Security\CSP\ContentSecurityPolicyManager; +use OCP\API; use OCP\AppFramework\Http\ContentSecurityPolicy; use OCP\AppFramework\Http\RedirectResponse; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Middleware; use OCP\AppFramework\Http\Response; use OCP\AppFramework\Http\JSONResponse; +use OCP\AppFramework\OCSController; use OCP\INavigationManager; use OCP\IURLGenerator; use OCP\IRequest; @@ -184,6 +187,13 @@ public function afterController($controller, $methodName, Response $response) { * @return Response a Response object or null in case that the exception could not be handled */ public function afterException($controller, $methodName, \Exception $exception) { + if ($controller instanceof OCSController) { + if ($exception instanceof NotLoggedInException) { + return $controller->buildResponse(new Result(null, API::RESPOND_UNAUTHORISED, 'Unauthorised')); + } + return $controller->buildResponse(new Result(null, API::RESPOND_SERVER_ERROR, $exception->getMessage())); + } + if ($exception instanceof SecurityException) { if (\stripos($this->request->getHeader('Accept'), 'html') === false) { $response = new JSONResponse( diff --git a/lib/private/Share/MailNotifications.php b/lib/private/Share/MailNotifications.php index 6a20c87cbe59..7e8e78c55c0f 100644 --- a/lib/private/Share/MailNotifications.php +++ b/lib/private/Share/MailNotifications.php @@ -29,7 +29,7 @@ namespace OC\Share; -use DateTime; +use OCP\Files\Node; use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; @@ -37,6 +37,8 @@ use OCP\Mail\IMailer; use OCP\ILogger; use OCP\Defaults; +use OCP\Share\IManager; +use OCP\Share\IShare; use OCP\Util; use OC\Share\Filters\MailNotificationFilter; use Symfony\Component\EventDispatcher\EventDispatcher; @@ -48,7 +50,8 @@ * @package OC\Share */ class MailNotifications { - + /** @var IManager */ + private $shareManager; /** @var IUser sender userId */ private $user; /** @var string sender email address */ @@ -78,17 +81,22 @@ class MailNotifications { * @param ILogger $logger * @param Defaults $defaults * @param IURLGenerator $urlGenerator + * @param EventDispatcher $eventDispatcher */ - public function __construct(IUser $user, - IL10N $l10n, - IMailer $mailer, - IConfig $config, - ILogger $logger, - Defaults $defaults, - IURLGenerator $urlGenerator, - EventDispatcher $eventDispatcher) { - $this->l = $l10n; + public function __construct( + IManager $shareManager, + IUser $user, + IL10N $l10n, + IMailer $mailer, + IConfig $config, + ILogger $logger, + Defaults $defaults, + IURLGenerator $urlGenerator, + EventDispatcher $eventDispatcher + ) { + $this->shareManager = $shareManager; $this->user = $user; + $this->l = $l10n; $this->mailer = $mailer; $this->config = $config; $this->logger = $logger; @@ -121,12 +129,13 @@ private function _mailStringToArray($mailsstring) { /** * inform users if a file was shared with them * + * @param Node shared node + * @param string $shareType share type * @param IUser[] $recipientList list of recipients - * @param string $itemSource shared item source - * @param string $itemType shared item type + * * @return array list of user to whom the mail send operation failed */ - public function sendInternalShareMail($recipientList, $itemSource, $itemType) { + public function sendInternalShareMail($node, $shareType, $recipientList) { $noMail = []; foreach ($recipientList as $recipient) { @@ -138,12 +147,19 @@ public function sendInternalShareMail($recipientList, $itemSource, $itemType) { continue; } - $items = $this->getItemSharedWithUser($itemSource, $itemType, $recipient); - $filename = \trim($items[0]['file_target'], '/'); + $items = $this->shareManager->getSharedWith($recipient->getUID(), $shareType, $node); + if (\count($items) === 0) { + $noMail[] = $recipientDisplayName; + continue; + } + /** @var IShare $firstItem */ + $firstItem = $items[0]; + + $filename = \trim($firstItem->getTarget(), '/'); $expiration = null; - if (isset($items[0]['expiration'])) { + if ($firstItem->getExpirationDate() instanceof \DateTime) { try { - $date = new DateTime($items[0]['expiration']); + $date = $firstItem->getExpirationDate(); $expiration = $date->getTimestamp(); } catch (\Exception $e) { $this->logger->error("Couldn't read date: ".$e->getMessage(), ['app' => 'sharing']); @@ -152,7 +168,7 @@ public function sendInternalShareMail($recipientList, $itemSource, $itemType) { $link = $this->urlGenerator->linkToRouteAbsolute( 'files.viewcontroller.showFile', - ['fileId' => $items[0]['item_source']] + ['fileId' => $firstItem->getNodeId()] ); $filter = new MailNotificationFilter([ @@ -359,16 +375,6 @@ public function createMailBody($filename, return [$htmlMail, $plainTextMail]; } - /** - * @param string $itemSource - * @param string $itemType - * @param IUser $recipient - * @return array - */ - protected function getItemSharedWithUser($itemSource, $itemType, $recipient) { - return Share::getItemSharedWithUser($itemType, $itemSource, $recipient->getUID()); - } - /** * Get default sender details * diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php index 4a3508ae4853..c05b7d768796 100644 --- a/lib/private/Share20/DefaultShareProvider.php +++ b/lib/private/Share20/DefaultShareProvider.php @@ -212,6 +212,7 @@ public function update(\OCP\Share\IShare $share) { ->set('item_source', $qb->createNamedParameter($share->getNode()->getId())) ->set('file_source', $qb->createNamedParameter($share->getNode()->getId())) ->set('accepted', $qb->createNamedParameter($share->getState())) + ->set('mail_send', $qb->createNamedParameter((int) $share->getMailSend())) ->execute(); } elseif ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { $qb = $this->dbConn->getQueryBuilder(); @@ -223,6 +224,7 @@ public function update(\OCP\Share\IShare $share) { ->set('item_source', $qb->createNamedParameter($share->getNode()->getId())) ->set('file_source', $qb->createNamedParameter($share->getNode()->getId())) ->set('accepted', $qb->createNamedParameter($share->getState())) + ->set('mail_send', $qb->createNamedParameter((int) $share->getMailSend())) ->execute(); /* diff --git a/lib/public/AppFramework/OCSController.php b/lib/public/AppFramework/OCSController.php index f6c06518fbf8..7a3a06c48036 100644 --- a/lib/public/AppFramework/OCSController.php +++ b/lib/public/AppFramework/OCSController.php @@ -33,6 +33,7 @@ namespace OCP\AppFramework; use OC\OCS\Result; +use OCP\API; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\OCSResponse; use OCP\AppFramework\Http\Response; @@ -147,6 +148,11 @@ public function buildResponse($response, $format = 'json') { } } + if ($resp->getStatusCode() === API::RESPOND_UNAUTHORISED) { + // HTTP code + $resp->setStatus(401); + } + return $resp; } } diff --git a/tests/lib/Share/MailNotificationsTest.php b/tests/lib/Share/MailNotificationsTest.php index 40decf2e846c..d055e071a523 100644 --- a/tests/lib/Share/MailNotificationsTest.php +++ b/tests/lib/Share/MailNotificationsTest.php @@ -21,6 +21,7 @@ namespace Test\Share; +use OC\Mail\Message; use OC\Share\MailNotifications; use OCP\Defaults; use OCP\IConfig; @@ -29,12 +30,12 @@ use OCP\IURLGenerator; use OCP\IUser; use OCP\Mail\IMailer; +use OCP\Share\IManager; use OCP\Share\IShare; use OCP\Util; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\GenericEvent; use Test\TestCase; -use OC\Mail\Message; /** * Class MailNotificationsTest @@ -42,6 +43,8 @@ * @group DB */ class MailNotificationsTest extends TestCase { + /** @var IManager | \PHPUnit_Framework_MockObject_MockObject */ + private $shareManager; /** @var IL10N */ private $l10n; /** @var IMailer | \PHPUnit_Framework_MockObject_MockObject */ @@ -58,21 +61,19 @@ class MailNotificationsTest extends TestCase { private $urlGenerator; private $eventDispatcher; + /** @var MailNotifications */ + private $mailNotifications; + public function setUp() { parent::setUp(); - $this->l10n = $this->getMockBuilder(IL10N::class) - ->disableOriginalConstructor()->getMock(); - $this->mailer = $this->getMockBuilder(IMailer::class) - ->disableOriginalConstructor()->getMock(); - $this->logger = $this->getMockBuilder(ILogger::class) - ->disableOriginalConstructor()->getMock(); - $this->config = $this->getMockBuilder(IConfig::class) - ->disableOriginalConstructor()->getMock(); - $this->defaults = $this->getMockBuilder(Defaults::class) - ->disableOriginalConstructor()->getMock(); - $this->user = $this->getMockBuilder(IUser::class) - ->disableOriginalConstructor()->getMock(); + $this->shareManager = $this->createMock(IManager::class); + $this->l10n = $this->createMock(IL10N::class); + $this->mailer = $this->createMock(IMailer::class); + $this->logger = $this->createMock(ILogger::class); + $this->config = $this->createMock(IConfig::class); + $this->defaults = $this->createMock(Defaults::class); + $this->user = $this->createMock(IUser::class); $this->urlGenerator = $this->createMock(IURLGenerator::class); $this->eventDispatcher = new EventDispatcher(); @@ -95,12 +96,22 @@ public function setUp() { ->expects($this->once()) ->method('getDisplayName') ->willReturn('TestUser'); + + $this->mailNotifications = new MailNotifications( + $this->shareManager, + $this->user, + $this->l10n, + $this->mailer, + $this->config, + $this->logger, + $this->defaults, + $this->urlGenerator, + $this->eventDispatcher + ); } public function testSendLinkShareMailWithoutReplyTo() { - $message = $this->getMockBuilder(Message::class) - ->disableOriginalConstructor()->getMock(); - + $message = $this->createMock(Message::class); $message ->expects($this->once()) ->method('setSubject') @@ -130,24 +141,14 @@ public function testSendLinkShareMailWithoutReplyTo() { ->with($message) ->will($this->returnValue([])); - $mailNotifications = new MailNotifications( - $this->user, - $this->l10n, - $this->mailer, - $this->config, - $this->logger, - $this->defaults, - $this->urlGenerator, - $this->eventDispatcher + $this->assertSame( + [], + $this->mailNotifications->sendLinkShareMail('lukas@owncloud.com', 'MyFile', 'https://owncloud.com/file/?foo=bar', 3600) ); - - $this->assertSame([], $mailNotifications->sendLinkShareMail('lukas@owncloud.com', 'MyFile', 'https://owncloud.com/file/?foo=bar', 3600)); } public function testSendLinkShareMailWithRecipientAndOptions() { - $message = $this->getMockBuilder(Message::class) - ->disableOriginalConstructor()->getMock(); - + $message = $this->createMock(Message::class); $message ->expects($this->once()) ->method('setSubject') @@ -164,7 +165,6 @@ public function testSendLinkShareMailWithRecipientAndOptions() { ->expects($this->once()) ->method('setPlainBody') ->with($this->stringContains("personal note\n")); - $message ->expects($this->once()) ->method('setFrom') @@ -174,30 +174,21 @@ public function testSendLinkShareMailWithRecipientAndOptions() { ->expects($this->once()) ->method('createMessage') ->will($this->returnValue($message)); - $this->mailer ->expects($this->once()) ->method('send') ->with($message) ->will($this->returnValue([])); - $mailNotifications = new MailNotifications( - $this->user, - $this->l10n, - $this->mailer, - $this->config, - $this->logger, - $this->defaults, - $this->urlGenerator, - $this->eventDispatcher - ); - $calledEvent = []; $this->eventDispatcher->addListener('share.sendmail', function (GenericEvent $event) use (&$calledEvent) { $calledEvent[] = 'share.sendmail'; $calledEvent[] = $event; }); - $this->assertSame([], $mailNotifications->sendLinkShareMail('lukas@owncloud.com', 'MyFile', 'https://owncloud.com/file/?foo=bar', 3600, "personal note\n", ['to' => 'lukas@owncloud.com', 'bcc' => 'foo@bar.com,fabulous@world.com', 'cc' => 'abc@foo.com,tester@world.com'])); + $this->assertSame( + [], + $this->mailNotifications->sendLinkShareMail('lukas@owncloud.com', 'MyFile', 'https://owncloud.com/file/?foo=bar', 3600, "personal note\n", ['to' => 'lukas@owncloud.com', 'bcc' => 'foo@bar.com,fabulous@world.com', 'cc' => 'abc@foo.com,tester@world.com']) + ); $this->assertEquals('share.sendmail', $calledEvent[0]); $this->assertInstanceOf(GenericEvent::class, $calledEvent[1]); @@ -212,9 +203,7 @@ public function testSendLinkShareMailWithRecipientAndOptions() { } public function testSendLinkShareMailPersonalNote() { - $message = $this->getMockBuilder(Message::class) - ->disableOriginalConstructor()->getMock(); - + $message = $this->createMock(Message::class); $message ->expects($this->once()) ->method('setSubject') @@ -231,7 +220,6 @@ public function testSendLinkShareMailPersonalNote() { ->expects($this->once()) ->method('setPlainBody') ->with($this->stringContains("personal note\n")); - $message ->expects($this->once()) ->method('setFrom') @@ -241,30 +229,21 @@ public function testSendLinkShareMailPersonalNote() { ->expects($this->once()) ->method('createMessage') ->will($this->returnValue($message)); - $this->mailer ->expects($this->once()) ->method('send') ->with($message) ->will($this->returnValue([])); - $mailNotifications = new MailNotifications( - $this->user, - $this->l10n, - $this->mailer, - $this->config, - $this->logger, - $this->defaults, - $this->urlGenerator, - $this->eventDispatcher - ); - $calledEvent = []; $this->eventDispatcher->addListener('share.sendmail', function (GenericEvent $event) use (&$calledEvent) { $calledEvent[] = 'share.sendmail'; $calledEvent[] = $event; }); - $this->assertSame([], $mailNotifications->sendLinkShareMail('lukas@owncloud.com', 'MyFile', 'https://owncloud.com/file/?foo=bar', 3600, "personal note\n", ['to' => 'lukas@owncloud.com'])); + $this->assertSame( + [], + $this->mailNotifications->sendLinkShareMail('lukas@owncloud.com', 'MyFile', 'https://owncloud.com/file/?foo=bar', 3600, "personal note\n", ['to' => 'lukas@owncloud.com']) + ); $this->assertEquals('share.sendmail', $calledEvent[0]); $this->assertInstanceOf(GenericEvent::class, $calledEvent[1]); @@ -291,9 +270,7 @@ public function dataSendLinkShareMailWithReplyTo() { * @param array $expectedTo */ public function testSendLinkShareMailWithReplyTo($to, array $expectedTo) { - $message = $this->getMockBuilder(Message::class) - ->disableOriginalConstructor()->getMock(); - + $message = $this->createMock(Message::class); $message ->expects($this->once()) ->method('setSubject') @@ -327,17 +304,10 @@ public function testSendLinkShareMailWithReplyTo($to, array $expectedTo) { ->with($message) ->will($this->returnValue([])); - $mailNotifications = new MailNotifications( - $this->user, - $this->l10n, - $this->mailer, - $this->config, - $this->logger, - $this->defaults, - $this->urlGenerator, - $this->eventDispatcher + $this->assertSame( + [], + $this->mailNotifications->sendLinkShareMail($to, 'MyFile', 'https://owncloud.com/file/?foo=bar', 3600) ); - $this->assertSame([], $mailNotifications->sendLinkShareMail($to, 'MyFile', 'https://owncloud.com/file/?foo=bar', 3600)); } public function dataSendLinkShareMailException() { @@ -362,17 +332,6 @@ public function dataSendLinkShareMailException() { public function testSendLinkShareMailException($to, $cc, $bcc, $toList, $expectedRecipientErrorList) { $this->setupMailerMock('TestUser shared »MyFile« with you', [$to]); - $mailNotifications = new MailNotifications( - $this->user, - $this->l10n, - $this->mailer, - $this->config, - $this->logger, - $this->defaults, - $this->urlGenerator, - $this->eventDispatcher - ); - $options = []; if ($toList !== '') { @@ -389,44 +348,27 @@ public function testSendLinkShareMailException($to, $cc, $bcc, $toList, $expecte $this->assertSame( [$expectedRecipientErrorList], - $mailNotifications->sendLinkShareMail($to, 'MyFile', 'https://owncloud.com/file/?foo=bar', 3600, null, $options) + $this->mailNotifications->sendLinkShareMail($to, 'MyFile', 'https://owncloud.com/file/?foo=bar', 3600, null, $options) ); } public function testSendInternalShareMail() { $this->setupMailerMock('TestUser shared ».txt« with you', ['recipient@owncloud.com' => 'Recipient'], false); - /** @var MailNotifications | \PHPUnit_Framework_MockObject_MockObject $mailNotifications */ - $mailNotifications = $this->getMockBuilder(MailNotifications::class) - ->setMethods(['getItemSharedWithUser']) - ->setConstructorArgs([ - $this->user, - $this->l10n, - $this->mailer, - $this->config, - $this->logger, - $this->defaults, - $this->urlGenerator, - $this->eventDispatcher - ]) - ->getMock(); - - $mailNotifications->method('getItemSharedWithUser') + $shareMock = $this->getShareMock( + ['file_target' => '/.txt', 'item_source' => 123, 'expiration' => '2017-01-01T15:03:01.012345Z'] + ); + $this->shareManager->method('getSharedWith') ->withAnyParameters() - ->willReturn([ - ['file_target' => '/.txt', 'item_source' => 123, 'expiration' => '2017-01-01T15:03:01.012345Z'], - ]); + ->willReturn([$shareMock]); - $recipient = $this->getMockBuilder(IUser::class) - ->disableOriginalConstructor()->getMock(); - $recipient - ->expects($this->once()) - ->method('getEMailAddress') - ->willReturn('recipient@owncloud.com'); - $recipient - ->expects($this->once()) - ->method('getDisplayName') - ->willReturn('Recipient'); + $recipient = $this->createMock(IUser::class); + $recipient->expects($this->once()) + ->method('getEMailAddress') + ->willReturn('recipient@owncloud.com'); + $recipient->expects($this->once()) + ->method('getDisplayName') + ->willReturn('Recipient'); $this->urlGenerator->expects($this->once()) ->method('linkToRouteAbsolute') @@ -438,36 +380,21 @@ public function testSendInternalShareMail() { ); $recipientList = [$recipient]; - $result = $mailNotifications->sendInternalShareMail($recipientList, '3', 'file'); + $result = $this->mailNotifications->sendInternalShareMail('3', 'file', $recipientList); $this->assertSame([], $result); } public function testSendInternalShareMailException() { $this->setupMailerMock('TestUser shared ».txt« with you', ['recipient@owncloud.com' => 'Recipient'], false); - /** @var MailNotifications | \PHPUnit_Framework_MockObject_MockObject $mailNotifications */ - $mailNotifications = $this->getMockBuilder(MailNotifications::class) - ->setMethods(['getItemSharedWithUser']) - ->setConstructorArgs([ - $this->user, - $this->l10n, - $this->mailer, - $this->config, - $this->logger, - $this->defaults, - $this->urlGenerator, - $this->eventDispatcher - ]) - ->getMock(); - - $mailNotifications->method('getItemSharedWithUser') + $share = $this->getShareMock( + ['file_target' => '/.txt', 'item_source' => 123, 'expiration' => 'foo'] + ); + $this->shareManager->method('getSharedWith') ->withAnyParameters() - ->willReturn([ - ['file_target' => '/.txt', 'item_source' => 123, 'expiration' => 'foo'], - ]); + ->willReturn([$share]); - $recipient = $this->getMockBuilder(IUser::class) - ->disableOriginalConstructor()->getMock(); + $recipient = $this->createMock(IUser::class); $recipient ->expects($this->once()) ->method('getEMailAddress') @@ -491,43 +418,10 @@ public function testSendInternalShareMailException() { ->willThrowException(new \Exception()); $recipientList = [$recipient]; - $result = $mailNotifications->sendInternalShareMail($recipientList, '3', 'file'); + $result = $this->mailNotifications->sendInternalShareMail('3', 'file', $recipientList); $this->assertEquals(['Recipient'], $result); } - public function testGetItemSharedWithUser() { - $mailNotifications = new MailNotifications( - $this->user, - $this->l10n, - $this->mailer, - $this->config, - $this->logger, - $this->defaults, - $this->urlGenerator, - $this->eventDispatcher - ); - /** - * The below piece of code is borrowed from - * https://github.com/owncloud/core/blob/master/tests/lib/Share/ShareTest.php#L621-L639 - */ - $uid1 = $this->getUniqueID('user1_'); - $uid2 = $this->getUniqueID('user2_'); - $user2 = $this->createMock(IUser::class); - $user2->expects($this->once()) - ->method('getUID') - ->willReturn($uid2); - - //add dummy values to the share table - $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (' - .' `item_type`, `item_source`, `item_target`, `share_type`,' - .' `share_with`, `uid_owner`) VALUES (?,?,?,?,?,?)'); - $args = ['test', 99, 'target1', \OCP\Share::SHARE_TYPE_USER, $uid2, $uid1]; - $query->execute($args); - - $result = $this->invokePrivate($mailNotifications, 'getItemSharedWithUser', [99, 'test', $user2]); - $this->assertCount(1, $result); - } - public function emptinessProvider() { return [ [null], @@ -539,23 +433,7 @@ public function emptinessProvider() { * @dataProvider emptinessProvider */ public function testSendInternalShareMailNoMail($emptiness) { - /** @var MailNotifications | \PHPUnit_Framework_MockObject_MockObject $mailNotifications */ - $mailNotifications = $this->getMockBuilder(MailNotifications::class) - ->setMethods(['getItemSharedWithUser']) - ->setConstructorArgs([ - $this->user, - $this->l10n, - $this->mailer, - $this->config, - $this->logger, - $this->defaults, - $this->urlGenerator, - $this->eventDispatcher - ]) - ->getMock(); - - $recipient = $this->getMockBuilder(IUser::class) - ->disableOriginalConstructor()->getMock(); + $recipient = $this->createMock(IUser::class); $recipient ->expects($this->once()) ->method('getEMailAddress') @@ -564,8 +442,8 @@ public function testSendInternalShareMailNoMail($emptiness) { ->expects($this->once()) ->method('getDisplayName') ->willReturn('No mail 1'); - $recipient2 = $this->getMockBuilder(IUser::class) - ->disableOriginalConstructor()->getMock(); + + $recipient2 = $this->createMock(IUser::class); $recipient2 ->expects($this->once()) ->method('getEMailAddress') @@ -576,27 +454,17 @@ public function testSendInternalShareMailNoMail($emptiness) { ->willReturn('No mail 2'); $recipientList = [$recipient, $recipient2]; - $result = $mailNotifications->sendInternalShareMail($recipientList, '3', 'file'); + $result = $this->mailNotifications->sendInternalShareMail('3', 'file', $recipientList); $this->assertSame(['No mail 1', 'No mail 2'], $result); } public function testPublicLinkNotificationIsTranslated() { - $mailNotifications = new MailNotifications( - $this->user, - $this->l10n, - $this->mailer, - $this->config, - $this->logger, - $this->defaults, - $this->urlGenerator, - $this->eventDispatcher - ); $this->config->expects($this->once()) ->method('getAppValue') ->with('core', 'shareapi_public_notification_lang', null) ->willReturn('ru'); - $message = $this->getMockBuilder(\OC\Mail\Message::class) - ->disableOriginalConstructor()->getMock(); + + $message = $this->createMock(Message::class); $message ->expects($this->once()) ->method('setFrom') @@ -610,7 +478,7 @@ public function testPublicLinkNotificationIsTranslated() { $this->l10n->expects($this->never()) ->method('t'); - $mailNotifications->sendLinkShareMail( + $this->mailNotifications->sendLinkShareMail( 'justin@piper.com', 'MyFile', 'https://owncloud.com/file/?foo=bar', 3600 ); } @@ -619,9 +487,7 @@ public function testPublicLinkNotificationIsTranslated() { * @param string $subject */ protected function setupMailerMock($subject, $to, $exceptionOnSend = true) { - $message = $this->getMockBuilder(Message::class) - ->disableOriginalConstructor()->getMock(); - + $message = $this->createMock(Message::class); $message ->expects($this->once()) ->method('setSubject') @@ -654,13 +520,28 @@ protected function setupMailerMock($subject, $to, $exceptionOnSend = true) { } } + protected function getShareMock(array $shareData) { + try { + $expiration = new \DateTime($shareData['expiration']); + } catch (\Exception $e) { + $expiration = null; + } + $share = $this->createMock(IShare::class); + $share->method('getTarget') + ->willReturn($shareData['file_target']); + $share->method('getNodeId') + ->willReturn($shareData['item_source']); + $share->method('getExpirationDate') + ->willReturn($expiration); + return $share; + } + public function providesLanguages() { return [ ['es', 'en'], ['en', 'en'] ]; } - /** * @dataProvider providesLanguages * @param string $recipientLanguage @@ -668,26 +549,12 @@ public function providesLanguages() { */ public function testSendInternalShareWithRecipientLanguageCode($recipientLanguage, $senderLanguage) { $this->setupMailerMock('TestUser shared ».txt« with you', ['recipient@owncloud.com' => 'Recipient'], false); - $mailNotifications = $this->getMockBuilder('OC\Share\MailNotifications') - ->setMethods(['getItemSharedWithUser']) - ->setConstructorArgs([ - $this->user, - $this->l10n, - $this->mailer, - $this->config, - $this->logger, - $this->defaults, - $this->urlGenerator, - $this->eventDispatcher - ]) - ->getMock(); - - $mailNotifications->method('getItemSharedWithUser') + $shareMock = $this->getShareMock( + ['file_target' => '/.txt', 'item_source' => 123, 'expiration' => '2017-01-01T15:03:01.012345Z'] + ); + $this->shareManager->method('getSharedWith') ->withAnyParameters() - ->willReturn([ - ['file_target' => '/.txt', 'item_source' => 123, 'expiration' => '2017-01-01T15:03:01.012345Z'], - ]); - + ->willReturn([$shareMock]); $recipient = $this->createMock(IUser::class); $recipient->expects($this->once()) ->method('getEMailAddress') @@ -697,15 +564,12 @@ public function testSendInternalShareWithRecipientLanguageCode($recipientLanguag ->willReturn('Recipient'); $recipient->method('getUID') ->willReturn('Recipient'); - $this->config->expects($this->once()) ->method('getUserValue') ->with('Recipient', 'core', 'lang', 'en') ->willReturn($recipientLanguage); - $this->l10n->method('getLanguageCode') ->willReturn($senderLanguage); - $this->urlGenerator->expects($this->once()) ->method('linkToRouteAbsolute') ->with( @@ -714,10 +578,8 @@ public function testSendInternalShareWithRecipientLanguageCode($recipientLanguag 'fileId' => 123, ]) ); - $recipientList = [$recipient]; - - $result = $mailNotifications->sendInternalShareMail($recipientList, '3', 'file'); + $result = $this->mailNotifications->sendInternalShareMail('3', 'file', $recipientList); $this->assertSame([], $result); } }