diff options
Diffstat (limited to 'tests/lib/Share20')
-rw-r--r-- | tests/lib/Share20/DefaultShareProviderTest.php | 683 | ||||
-rw-r--r-- | tests/lib/Share20/LegacyHooksTest.php | 123 | ||||
-rw-r--r-- | tests/lib/Share20/ManagerTest.php | 1911 | ||||
-rw-r--r-- | tests/lib/Share20/ShareByMailProviderTest.php | 296 | ||||
-rw-r--r-- | tests/lib/Share20/ShareHelperTest.php | 51 | ||||
-rw-r--r-- | tests/lib/Share20/ShareTest.php | 52 |
6 files changed, 1908 insertions, 1208 deletions
diff --git a/tests/lib/Share20/DefaultShareProviderTest.php b/tests/lib/Share20/DefaultShareProviderTest.php index 03e1bdb4346..bacf2b61ee3 100644 --- a/tests/lib/Share20/DefaultShareProviderTest.php +++ b/tests/lib/Share20/DefaultShareProviderTest.php @@ -1,28 +1,20 @@ <?php + /** - * @author Roeland Jago Douma <rullzer@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl> - * @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 <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Test\Share20; +use OC\Files\Node\Node; use OC\Share20\DefaultShareProvider; +use OC\Share20\Exception\ProviderException; +use OC\Share20\Share; +use OC\Share20\ShareAttributes; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\Constants; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Defaults; use OCP\Files\File; @@ -38,8 +30,12 @@ use OCP\IUser; use OCP\IUserManager; use OCP\L10N\IFactory; use OCP\Mail\IMailer; +use OCP\Server; +use OCP\Share\Exceptions\ShareNotFound; +use OCP\Share\IManager as IShareManager; use OCP\Share\IShare; use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; /** * Class DefaultShareProviderTest @@ -48,42 +44,48 @@ use PHPUnit\Framework\MockObject\MockObject; * @group DB */ class DefaultShareProviderTest extends \Test\TestCase { - /** @var IDBConnection */ protected $dbConn; - /** @var IUserManager | \PHPUnit\Framework\MockObject\MockObject */ + /** @var IUserManager | MockObject */ protected $userManager; - /** @var IGroupManager | \PHPUnit\Framework\MockObject\MockObject */ + /** @var IGroupManager | MockObject */ protected $groupManager; - /** @var IRootFolder | \PHPUnit\Framework\MockObject\MockObject */ + /** @var IRootFolder | MockObject */ protected $rootFolder; /** @var DefaultShareProvider */ protected $provider; - /** @var \PHPUnit\Framework\MockObject\MockObject|IMailer */ + /** @var MockObject|IMailer */ protected $mailer; /** @var IFactory|MockObject */ protected $l10nFactory; - /** @var \PHPUnit\Framework\MockObject\MockObject|IL10N */ + /** @var MockObject|IL10N */ protected $l10n; - /** @var \PHPUnit\Framework\MockObject\MockObject|Defaults */ + /** @var MockObject|Defaults */ protected $defaults; - /** @var \PHPUnit\Framework\MockObject\MockObject|IURLGenerator */ + /** @var MockObject|IURLGenerator */ protected $urlGenerator; - /** @var IConfig|MockObject */ - protected $config; + /** @var ITimeFactory|MockObject */ + protected $timeFactory; + + /** @var LoggerInterface|MockObject */ + protected $logger; + + protected IConfig&MockObject $config; + + protected IShareManager&MockObject $shareManager; protected function setUp(): void { - $this->dbConn = \OC::$server->getDatabaseConnection(); + $this->dbConn = Server::get(IDBConnection::class); $this->userManager = $this->createMock(IUserManager::class); $this->groupManager = $this->createMock(IGroupManager::class); $this->rootFolder = $this->createMock(IRootFolder::class); @@ -92,9 +94,13 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->l10n = $this->createMock(IL10N::class); $this->defaults = $this->getMockBuilder(Defaults::class)->disableOriginalConstructor()->getMock(); $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->timeFactory = $this->createMock(ITimeFactory::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->shareManager = $this->createMock(IShareManager::class); $this->config = $this->createMock(IConfig::class); $this->userManager->expects($this->any())->method('userExists')->willReturn(true); + $this->timeFactory->expects($this->any())->method('now')->willReturn(new \DateTimeImmutable('2023-05-04 00:00 Europe/Berlin')); //Empty share table $this->dbConn->getQueryBuilder()->delete('share')->execute(); @@ -108,13 +114,16 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->defaults, $this->l10nFactory, $this->urlGenerator, - $this->config + $this->timeFactory, + $this->logger, + $this->shareManager, + $this->config, ); } protected function tearDown(): void { $this->dbConn->getQueryBuilder()->delete('share')->execute(); - $this->dbConn->getQueryBuilder()->delete('filecache')->execute(); + $this->dbConn->getQueryBuilder()->delete('filecache')->runAcrossAllShards()->execute(); $this->dbConn->getQueryBuilder()->delete('storages')->execute(); } @@ -132,8 +141,8 @@ class DefaultShareProviderTest extends \Test\TestCase { * @return int */ private function addShareToDB($shareType, $sharedWith, $sharedBy, $shareOwner, - $itemType, $fileSource, $fileTarget, $permissions, $token, $expiration, - $parent = null) { + $itemType, $fileSource, $fileTarget, $permissions, $token, $expiration, + $parent = null) { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share'); @@ -165,7 +174,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $qb->setValue('token', $qb->expr()->literal($token)); } if ($expiration) { - $qb->setValue('expiration', $qb->createNamedParameter($expiration, IQueryBuilder::PARAM_DATE)); + $qb->setValue('expiration', $qb->createNamedParameter($expiration, IQueryBuilder::PARAM_DATETIME_MUTABLE)); } if ($parent) { $qb->setValue('parent', $qb->expr()->literal($parent)); @@ -178,13 +187,13 @@ class DefaultShareProviderTest extends \Test\TestCase { - public function testGetShareByIdNotExist() { - $this->expectException(\OCP\Share\Exceptions\ShareNotFound::class); + public function testGetShareByIdNotExist(): void { + $this->expectException(ShareNotFound::class); $this->provider->getShareById(1); } - public function testGetShareByIdUserShare() { + public function testGetShareByIdUserShare(): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') @@ -209,7 +218,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $ownerPath = $this->createMock(File::class); $shareOwnerFolder = $this->createMock(Folder::class); - $shareOwnerFolder->method('getById')->with(42)->willReturn([$ownerPath]); + $shareOwnerFolder->method('getFirstNodeById')->with(42)->willReturn($ownerPath); $this->rootFolder ->method('getUserFolder') @@ -231,7 +240,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals('myTarget', $share->getTarget()); } - public function testGetShareByIdLazy() { + public function testGetShareByIdLazy(): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') @@ -266,7 +275,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals('myTarget', $share->getTarget()); } - public function testGetShareByIdLazy2() { + public function testGetShareByIdLazy2(): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') @@ -287,7 +296,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $ownerPath = $this->createMock(File::class); $shareOwnerFolder = $this->createMock(Folder::class); - $shareOwnerFolder->method('getById')->with(42)->willReturn([$ownerPath]); + $shareOwnerFolder->method('getFirstNodeById')->with(42)->willReturn($ownerPath); $this->rootFolder ->method('getUserFolder') @@ -310,7 +319,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals('myTarget', $share->getTarget()); } - public function testGetShareByIdGroupShare() { + public function testGetShareByIdGroupShare(): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') @@ -331,13 +340,13 @@ class DefaultShareProviderTest extends \Test\TestCase { $ownerPath = $this->createMock(Folder::class); $shareOwnerFolder = $this->createMock(Folder::class); - $shareOwnerFolder->method('getById')->with(42)->willReturn([$ownerPath]); + $shareOwnerFolder->method('getFirstNodeById')->with(42)->willReturn($ownerPath); $this->rootFolder - ->method('getUserFolder') - ->willReturnMap([ - ['shareOwner', $shareOwnerFolder], - ]); + ->method('getUserFolder') + ->willReturnMap([ + ['shareOwner', $shareOwnerFolder], + ]); $share = $this->provider->getShareById($id); @@ -353,7 +362,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals('myTarget', $share->getTarget()); } - public function testGetShareByIdUserGroupShare() { + public function testGetShareByIdUserGroupShare(): void { $id = $this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user0', 'user0', 'file', 42, 'myTarget', 31, null, null); $this->addShareToDB(2, 'user1', 'user0', 'user0', 'file', 42, 'userTarget', 0, null, null, $id); @@ -364,12 +373,14 @@ class DefaultShareProviderTest extends \Test\TestCase { $group0 = $this->createMock(IGroup::class); $group0->method('inGroup')->with($user1)->willReturn(true); + $group0->method('getDisplayName')->willReturn('g0-displayname'); $node = $this->createMock(Folder::class); $node->method('getId')->willReturn(42); + $node->method('getName')->willReturn('myTarget'); $this->rootFolder->method('getUserFolder')->with('user0')->willReturnSelf(); - $this->rootFolder->method('getById')->willReturn([$node]); + $this->rootFolder->method('getFirstNodeById')->willReturn($node); $this->userManager->method('get')->willReturnMap([ ['user0', $user0], @@ -391,7 +402,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals('userTarget', $share->getTarget()); } - public function testGetShareByIdLinkShare() { + public function testGetShareByIdLinkShare(): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') @@ -414,13 +425,13 @@ class DefaultShareProviderTest extends \Test\TestCase { $ownerPath = $this->createMock(Folder::class); $shareOwnerFolder = $this->createMock(Folder::class); - $shareOwnerFolder->method('getById')->with(42)->willReturn([$ownerPath]); + $shareOwnerFolder->method('getFirstNodeById')->with(42)->willReturn($ownerPath); $this->rootFolder - ->method('getUserFolder') - ->willReturnMap([ - ['shareOwner', $shareOwnerFolder], - ]); + ->method('getUserFolder') + ->willReturnMap([ + ['shareOwner', $shareOwnerFolder], + ]); $share = $this->provider->getShareById($id); @@ -438,7 +449,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals('myTarget', $share->getTarget()); } - public function testDeleteSingleShare() { + public function testDeleteSingleShare(): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') ->values([ @@ -468,9 +479,12 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->defaults, $this->l10nFactory, $this->urlGenerator, - $this->config + $this->timeFactory, + $this->logger, + $this->shareManager, + $this->config, ]) - ->setMethods(['getShareById']) + ->onlyMethods(['getShareById']) ->getMock(); $provider->delete($share); @@ -486,7 +500,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEmpty($result); } - public function testDeleteSingleShareLazy() { + public function testDeleteSingleShareLazy(): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') ->values([ @@ -519,7 +533,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEmpty($result); } - public function testDeleteGroupShareWithUserGroupShares() { + public function testDeleteGroupShareWithUserGroupShares(): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') ->values([ @@ -563,9 +577,12 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->defaults, $this->l10nFactory, $this->urlGenerator, - $this->config + $this->timeFactory, + $this->logger, + $this->shareManager, + $this->config, ]) - ->setMethods(['getShareById']) + ->onlyMethods(['getShareById']) ->getMock(); $provider->delete($share); @@ -581,7 +598,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEmpty($result); } - public function testGetChildren() { + public function testGetChildren(): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') ->values([ @@ -631,7 +648,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $ownerPath = $this->createMock(Folder::class); $ownerFolder = $this->createMock(Folder::class); - $ownerFolder->method('getById')->willReturn([$ownerPath]); + $ownerFolder->method('getFirstNodeById')->willReturn($ownerPath); $this->rootFolder ->method('getUserFolder') @@ -669,8 +686,8 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals('myTarget2', $children[1]->getTarget()); } - public function testCreateUserShare() { - $share = new \OC\Share20\Share($this->rootFolder, $this->userManager); + public function testCreateUserShare(): void { + $share = new Share($this->rootFolder, $this->userManager); $shareOwner = $this->createMock(IUser::class); $shareOwner->method('getUID')->willReturn('shareOwner'); @@ -688,12 +705,12 @@ class DefaultShareProviderTest extends \Test\TestCase { ['shareOwner', $ownerFolder], ]); - $userFolder->method('getById') + $userFolder->method('getFirstNodeById') ->with(100) - ->willReturn([$path]); - $ownerFolder->method('getById') + ->willReturn($path); + $ownerFolder->method('getFirstNodeById') ->with(100) - ->willReturn([$path]); + ->willReturn($path); $share->setShareType(IShare::TYPE_USER); $share->setSharedWith('sharedWith'); @@ -703,12 +720,17 @@ class DefaultShareProviderTest extends \Test\TestCase { $share->setSharedWithDisplayName('Displayed Name'); $share->setSharedWithAvatar('/path/to/image.svg'); $share->setPermissions(1); + + $attrs = new ShareAttributes(); + $attrs->setAttribute('permissions', 'download', true); + $share->setAttributes($attrs); + $share->setTarget('/target'); $share2 = $this->provider->create($share); $this->assertNotNull($share2->getId()); - $this->assertSame('ocinternal:'.$share2->getId(), $share2->getFullId()); + $this->assertSame('ocinternal:' . $share2->getId(), $share2->getFullId()); $this->assertSame(IShare::TYPE_USER, $share2->getShareType()); $this->assertSame('sharedWith', $share2->getSharedWith()); $this->assertSame('sharedBy', $share2->getSharedBy()); @@ -718,15 +740,26 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertLessThanOrEqual(new \DateTime(), $share2->getShareTime()); $this->assertSame($path, $share2->getNode()); - // nothing from setSharedWithDisplayName/setSharedWithAvatar is saved in DB + // Data is kept after creation $this->assertSame('Displayed Name', $share->getSharedWithDisplayName()); $this->assertSame('/path/to/image.svg', $share->getSharedWithAvatar()); - $this->assertSame(null, $share2->getSharedWithDisplayName()); - $this->assertSame(null, $share2->getSharedWithAvatar()); + $this->assertSame('Displayed Name', $share2->getSharedWithDisplayName()); + $this->assertSame('/path/to/image.svg', $share2->getSharedWithAvatar()); + + $this->assertSame( + [ + [ + 'scope' => 'permissions', + 'key' => 'download', + 'value' => true + ] + ], + $share->getAttributes()->toArray() + ); } - public function testCreateGroupShare() { - $share = new \OC\Share20\Share($this->rootFolder, $this->userManager); + public function testCreateGroupShare(): void { + $share = new Share($this->rootFolder, $this->userManager); $shareOwner = $this->createMock(IUser::class); $shareOwner->method('getUID')->willReturn('shareOwner'); @@ -744,12 +777,12 @@ class DefaultShareProviderTest extends \Test\TestCase { ['shareOwner', $ownerFolder], ]); - $userFolder->method('getById') + $userFolder->method('getFirstNodeById') ->with(100) - ->willReturn([$path]); - $ownerFolder->method('getById') + ->willReturn($path); + $ownerFolder->method('getFirstNodeById') ->with(100) - ->willReturn([$path]); + ->willReturn($path); $share->setShareType(IShare::TYPE_GROUP); $share->setSharedWith('sharedWith'); @@ -760,11 +793,14 @@ class DefaultShareProviderTest extends \Test\TestCase { $share->setSharedWithDisplayName('Displayed Name'); $share->setSharedWithAvatar('/path/to/image.svg'); $share->setTarget('/target'); + $attrs = new ShareAttributes(); + $attrs->setAttribute('permissions', 'download', true); + $share->setAttributes($attrs); $share2 = $this->provider->create($share); $this->assertNotNull($share2->getId()); - $this->assertSame('ocinternal:'.$share2->getId(), $share2->getFullId()); + $this->assertSame('ocinternal:' . $share2->getId(), $share2->getFullId()); $this->assertSame(IShare::TYPE_GROUP, $share2->getShareType()); $this->assertSame('sharedWith', $share2->getSharedWith()); $this->assertSame('sharedBy', $share2->getSharedBy()); @@ -774,15 +810,26 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertLessThanOrEqual(new \DateTime(), $share2->getShareTime()); $this->assertSame($path, $share2->getNode()); - // nothing from setSharedWithDisplayName/setSharedWithAvatar is saved in DB + // Data is kept after creation $this->assertSame('Displayed Name', $share->getSharedWithDisplayName()); $this->assertSame('/path/to/image.svg', $share->getSharedWithAvatar()); - $this->assertSame(null, $share2->getSharedWithDisplayName()); - $this->assertSame(null, $share2->getSharedWithAvatar()); + $this->assertSame('Displayed Name', $share2->getSharedWithDisplayName()); + $this->assertSame('/path/to/image.svg', $share2->getSharedWithAvatar()); + + $this->assertSame( + [ + [ + 'scope' => 'permissions', + 'key' => 'download', + 'value' => true + ] + ], + $share->getAttributes()->toArray() + ); } - public function testCreateLinkShare() { - $share = new \OC\Share20\Share($this->rootFolder, $this->userManager); + public function testCreateLinkShare(): void { + $share = new Share($this->rootFolder, $this->userManager); $shareOwner = $this->createMock(IUser::class); $shareOwner->method('getUID')->willReturn('shareOwner'); @@ -794,18 +841,18 @@ class DefaultShareProviderTest extends \Test\TestCase { $ownerFolder = $this->createMock(Folder::class); $userFolder = $this->createMock(Folder::class); $this->rootFolder - ->method('getUserFolder') - ->willReturnMap([ - ['sharedBy', $userFolder], - ['shareOwner', $ownerFolder], - ]); - - $userFolder->method('getById') - ->with(100) - ->willReturn([$path]); - $ownerFolder->method('getById') - ->with(100) - ->willReturn([$path]); + ->method('getUserFolder') + ->willReturnMap([ + ['sharedBy', $userFolder], + ['shareOwner', $ownerFolder], + ]); + + $userFolder->method('getFirstNodeById') + ->with(100) + ->willReturn($path); + $ownerFolder->method('getFirstNodeById') + ->with(100) + ->willReturn($path); $share->setShareType(IShare::TYPE_LINK); $share->setSharedBy('sharedBy'); @@ -822,7 +869,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $share2 = $this->provider->create($share); $this->assertNotNull($share2->getId()); - $this->assertSame('ocinternal:'.$share2->getId(), $share2->getFullId()); + $this->assertSame('ocinternal:' . $share2->getId(), $share2->getFullId()); $this->assertSame(IShare::TYPE_LINK, $share2->getShareType()); $this->assertSame('sharedBy', $share2->getSharedBy()); $this->assertSame('shareOwner', $share2->getShareOwner()); @@ -836,7 +883,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals($expireDate->getTimestamp(), $share2->getExpirationDate()->getTimestamp()); } - public function testGetShareByToken() { + public function testGetShareByToken(): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') @@ -851,6 +898,7 @@ class DefaultShareProviderTest extends \Test\TestCase { 'file_target' => $qb->expr()->literal('myTarget'), 'permissions' => $qb->expr()->literal(13), 'token' => $qb->expr()->literal('secrettoken'), + 'label' => $qb->expr()->literal('the label'), ]); $qb->execute(); $id = $qb->getLastInsertId(); @@ -858,7 +906,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $file = $this->createMock(File::class); $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf(); - $this->rootFolder->method('getById')->with(42)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file); $share = $this->provider->getShareByToken('secrettoken'); $this->assertEquals($id, $share->getId()); @@ -866,13 +914,46 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertSame('sharedBy', $share->getSharedBy()); $this->assertSame('secrettoken', $share->getToken()); $this->assertSame('password', $share->getPassword()); + $this->assertSame('the label', $share->getLabel()); $this->assertSame(true, $share->getSendPasswordByTalk()); $this->assertSame(null, $share->getSharedWith()); } + /** + * Assert that if no label is provided the label is correctly, + * as types on IShare, a string and not null + */ + public function testGetShareByTokenNullLabel(): void { + $qb = $this->dbConn->getQueryBuilder(); + + $qb->insert('share') + ->values([ + 'share_type' => $qb->expr()->literal(IShare::TYPE_LINK), + 'password' => $qb->expr()->literal('password'), + 'password_by_talk' => $qb->expr()->literal(true), + 'uid_owner' => $qb->expr()->literal('shareOwner'), + 'uid_initiator' => $qb->expr()->literal('sharedBy'), + 'item_type' => $qb->expr()->literal('file'), + 'file_source' => $qb->expr()->literal(42), + 'file_target' => $qb->expr()->literal('myTarget'), + 'permissions' => $qb->expr()->literal(13), + 'token' => $qb->expr()->literal('secrettoken'), + ]); + $qb->executeStatement(); + $id = $qb->getLastInsertId(); + + $file = $this->createMock(File::class); + + $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf(); + $this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file); + + $share = $this->provider->getShareByToken('secrettoken'); + $this->assertEquals($id, $share->getId()); + $this->assertSame('', $share->getLabel()); + } - public function testGetShareByTokenNotFound() { - $this->expectException(\OCP\Share\Exceptions\ShareNotFound::class); + public function testGetShareByTokenNotFound(): void { + $this->expectException(ShareNotFound::class); $this->provider->getShareByToken('invalidtoken'); } @@ -891,16 +972,16 @@ class DefaultShareProviderTest extends \Test\TestCase { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('filecache') ->values([ - 'storage' => $qb->expr()->literal($storage), - 'path' => $qb->expr()->literal($path), - 'path_hash' => $qb->expr()->literal(md5($path)), - 'name' => $qb->expr()->literal(basename($path)), + 'storage' => $qb->createNamedParameter($storage, IQueryBuilder::PARAM_INT), + 'path' => $qb->createNamedParameter($path), + 'path_hash' => $qb->createNamedParameter(md5($path)), + 'name' => $qb->createNamedParameter(basename($path)), ]); $this->assertEquals(1, $qb->execute()); return $qb->getLastInsertId(); } - public function storageAndFileNameProvider() { + public static function storageAndFileNameProvider(): array { return [ // regular file on regular storage ['home::shareOwner', 'files/test.txt', 'files/test2.txt'], @@ -911,10 +992,8 @@ class DefaultShareProviderTest extends \Test\TestCase { ]; } - /** - * @dataProvider storageAndFileNameProvider - */ - public function testGetSharedWithUser($storageStringId, $fileName1, $fileName2) { + #[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')] + public function testGetSharedWithUser($storageStringId, $fileName1, $fileName2): void { $storageId = $this->createTestStorageEntry($storageStringId); $fileId = $this->createTestFileEntry($fileName1, $storageId); $fileId2 = $this->createTestFileEntry($fileName2, $storageId); @@ -949,7 +1028,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $file = $this->createMock(File::class); $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf(); - $this->rootFolder->method('getById')->with($fileId)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with($fileId)->willReturn($file); $share = $this->provider->getSharedWith('sharedWith', IShare::TYPE_USER, null, 1, 0); $this->assertCount(1, $share); @@ -962,10 +1041,8 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals(IShare::TYPE_USER, $share->getShareType()); } - /** - * @dataProvider storageAndFileNameProvider - */ - public function testGetSharedWithGroup($storageStringId, $fileName1, $fileName2) { + #[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')] + public function testGetSharedWithGroup($storageStringId, $fileName1, $fileName2): void { $storageId = $this->createTestStorageEntry($storageStringId); $fileId = $this->createTestFileEntry($fileName1, $storageId); $fileId2 = $this->createTestFileEntry($fileName2, $storageId); @@ -1000,7 +1077,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $groups = []; foreach (range(0, 100) as $i) { - $groups[] = 'group'.$i; + $groups[] = 'group' . $i; } $groups[] = 'sharedWith'; @@ -1017,11 +1094,13 @@ class DefaultShareProviderTest extends \Test\TestCase { ['shareOwner', $owner], ['sharedBy', $initiator], ]); - $this->groupManager->method('getUserGroupIds')->with($user)->willReturn($groups); + $this->groupManager + ->method('getUserGroupIds') + ->willReturnCallback(fn (IUser $user) => ($user->getUID() === 'sharedWith' ? $groups : [])); $file = $this->createMock(File::class); $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf(); - $this->rootFolder->method('getById')->with($fileId)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with($fileId)->willReturn($file); $share = $this->provider->getSharedWith('sharedWith', IShare::TYPE_GROUP, null, 20, 1); $this->assertCount(1, $share); @@ -1034,10 +1113,8 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals(IShare::TYPE_GROUP, $share->getShareType()); } - /** - * @dataProvider storageAndFileNameProvider - */ - public function testGetSharedWithGroupUserModified($storageStringId, $fileName1, $fileName2) { + #[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')] + public function testGetSharedWithGroupUserModified($storageStringId, $fileName1, $fileName2): void { $storageId = $this->createTestStorageEntry($storageStringId); $fileId = $this->createTestFileEntry($fileName1, $storageId); $qb = $this->dbConn->getQueryBuilder(); @@ -1105,11 +1182,13 @@ class DefaultShareProviderTest extends \Test\TestCase { ['shareOwner', $owner], ['sharedBy', $initiator], ]); - $this->groupManager->method('getUserGroupIds')->with($user)->willReturn($groups); + $this->groupManager + ->method('getUserGroupIds') + ->willReturnCallback(fn (IUser $user) => ($user->getUID() === 'user' ? $groups : [])); $file = $this->createMock(File::class); $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf(); - $this->rootFolder->method('getById')->with($fileId)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with($fileId)->willReturn($file); $share = $this->provider->getSharedWith('user', IShare::TYPE_GROUP, null, -1, 0); $this->assertCount(1, $share); @@ -1124,10 +1203,8 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertSame('userTarget', $share->getTarget()); } - /** - * @dataProvider storageAndFileNameProvider - */ - public function testGetSharedWithUserWithNode($storageStringId, $fileName1, $fileName2) { + #[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')] + public function testGetSharedWithUserWithNode($storageStringId, $fileName1, $fileName2): void { $storageId = $this->createTestStorageEntry($storageStringId); $fileId = $this->createTestFileEntry($fileName1, $storageId); $fileId2 = $this->createTestFileEntry($fileName2, $storageId); @@ -1152,7 +1229,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $file->method('getId')->willReturn($fileId2); $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf(); - $this->rootFolder->method('getById')->with($fileId2)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with($fileId2)->willReturn($file); $share = $this->provider->getSharedWith('user0', IShare::TYPE_USER, $file, -1, 0); $this->assertCount(1, $share); @@ -1166,10 +1243,8 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals(IShare::TYPE_USER, $share->getShareType()); } - /** - * @dataProvider storageAndFileNameProvider - */ - public function testGetSharedWithGroupWithNode($storageStringId, $fileName1, $fileName2) { + #[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')] + public function testGetSharedWithGroupWithNode($storageStringId, $fileName1, $fileName2): void { $storageId = $this->createTestStorageEntry($storageStringId); $fileId = $this->createTestFileEntry($fileName1, $storageId); $fileId2 = $this->createTestFileEntry($fileName2, $storageId); @@ -1188,12 +1263,14 @@ class DefaultShareProviderTest extends \Test\TestCase { ['user1', $user1], ]); - $this->groupManager->method('getUserGroupIds')->with($user0)->willReturn(['group0']); + $this->groupManager + ->method('getUserGroupIds') + ->willReturnCallback(fn (IUser $user) => ($user->getUID() === 'user0' ? ['group0'] : [])); $node = $this->createMock(Folder::class); $node->method('getId')->willReturn($fileId2); $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf(); - $this->rootFolder->method('getById')->with($fileId2)->willReturn([$node]); + $this->rootFolder->method('getFirstNodeById')->with($fileId2)->willReturn($node); $share = $this->provider->getSharedWith('user0', IShare::TYPE_GROUP, $node, -1, 0); $this->assertCount(1, $share); @@ -1207,7 +1284,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals(IShare::TYPE_GROUP, $share->getShareType()); } - public function shareTypesProvider() { + public static function shareTypesProvider(): array { return [ [IShare::TYPE_USER, false], [IShare::TYPE_GROUP, false], @@ -1216,10 +1293,8 @@ class DefaultShareProviderTest extends \Test\TestCase { ]; } - /** - * @dataProvider shareTypesProvider - */ - public function testGetSharedWithWithDeletedFile($shareType, $trashed) { + #[\PHPUnit\Framework\Attributes\DataProvider('shareTypesProvider')] + public function testGetSharedWithWithDeletedFile($shareType, $trashed): void { if ($trashed) { // exists in database but is in trash $storageId = $this->createTestStorageEntry('home::shareOwner'); @@ -1244,11 +1319,11 @@ class DefaultShareProviderTest extends \Test\TestCase { $file = $this->createMock(File::class); $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf(); - $this->rootFolder->method('getById')->with($deletedFileId)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with($deletedFileId)->willReturn($file); $groups = []; foreach (range(0, 100) as $i) { - $groups[] = 'group'.$i; + $groups[] = 'group' . $i; } $groups[] = 'sharedWith'; @@ -1265,13 +1340,15 @@ class DefaultShareProviderTest extends \Test\TestCase { ['shareOwner', $owner], ['sharedBy', $initiator], ]); - $this->groupManager->method('getUserGroupIds')->with($user)->willReturn($groups); + $this->groupManager + ->method('getUserGroupIds') + ->willReturnCallback(fn (IUser $user) => ($user->getUID() === 'sharedWith' ? $groups : [])); $share = $this->provider->getSharedWith('sharedWith', $shareType, null, 1, 0); $this->assertCount(0, $share); } - public function testGetSharesBy() { + public function testGetSharesBy(): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') ->values([ @@ -1304,7 +1381,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $file = $this->createMock(File::class); $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf(); - $this->rootFolder->method('getById')->with(42)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file); $share = $this->provider->getSharesBy('sharedBy', IShare::TYPE_USER, null, false, 1, 0); $this->assertCount(1, $share); @@ -1320,7 +1397,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals('myTarget', $share->getTarget()); } - public function testGetSharesNode() { + public function testGetSharesNode(): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') ->values([ @@ -1354,7 +1431,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $file = $this->createMock(File::class); $file->method('getId')->willReturn(42); $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf(); - $this->rootFolder->method('getById')->with(42)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file); $share = $this->provider->getSharesBy('sharedBy', IShare::TYPE_USER, $file, false, 1, 0); $this->assertCount(1, $share); @@ -1370,7 +1447,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals('myTarget', $share->getTarget()); } - public function testGetSharesReshare() { + public function testGetSharesReshare(): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') ->values([ @@ -1404,7 +1481,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $file = $this->createMock(File::class); $file->method('getId')->willReturn(42); $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf(); - $this->rootFolder->method('getById')->with(42)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file); $shares = $this->provider->getSharesBy('shareOwner', IShare::TYPE_USER, null, true, -1, 0); $this->assertCount(2, $shares); @@ -1429,7 +1506,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals('userTarget', $share->getTarget()); } - public function testDeleteFromSelfGroupNoCustomShare() { + public function testDeleteFromSelfGroupNoCustomShare(): void { $qb = $this->dbConn->getQueryBuilder(); $stmt = $qb->insert('share') ->values([ @@ -1457,13 +1534,14 @@ class DefaultShareProviderTest extends \Test\TestCase { $group = $this->createMock(IGroup::class); $group->method('getGID')->willReturn('group'); $group->method('inGroup')->with($user2)->willReturn(true); + $group->method('getDisplayName')->willReturn('group-displayname'); $this->groupManager->method('get')->with('group')->willReturn($group); $file = $this->createMock(File::class); $file->method('getId')->willReturn(1); $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf(); - $this->rootFolder->method('getById')->with(1)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file); $share = $this->provider->getShareById($id); @@ -1485,7 +1563,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals('user2', $share2['share_with']); } - public function testDeleteFromSelfGroupAlreadyCustomShare() { + public function testDeleteFromSelfGroupAlreadyCustomShare(): void { $qb = $this->dbConn->getQueryBuilder(); $stmt = $qb->insert('share') ->values([ @@ -1528,13 +1606,14 @@ class DefaultShareProviderTest extends \Test\TestCase { $group = $this->createMock(IGroup::class); $group->method('getGID')->willReturn('group'); $group->method('inGroup')->with($user2)->willReturn(true); + $group->method('getDisplayName')->willReturn('group-displayname'); $this->groupManager->method('get')->with('group')->willReturn($group); $file = $this->createMock(File::class); $file->method('getId')->willReturn(1); $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf(); - $this->rootFolder->method('getById')->with(1)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file); $share = $this->provider->getShareById($id); @@ -1557,7 +1636,7 @@ class DefaultShareProviderTest extends \Test\TestCase { } - public function testDeleteFromSelfGroupUserNotInGroup() { + public function testDeleteFromSelfGroupUserNotInGroup(): void { $qb = $this->dbConn->getQueryBuilder(); $stmt = $qb->insert('share') ->values([ @@ -1585,13 +1664,14 @@ class DefaultShareProviderTest extends \Test\TestCase { $group = $this->createMock(IGroup::class); $group->method('getGID')->willReturn('group'); $group->method('inGroup')->with($user2)->willReturn(false); + $group->method('getDisplayName')->willReturn('group-displayname'); $this->groupManager->method('get')->with('group')->willReturn($group); $file = $this->createMock(File::class); $file->method('getId')->willReturn(1); $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf(); - $this->rootFolder->method('getById')->with(1)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file); $share = $this->provider->getShareById($id); @@ -1599,8 +1679,8 @@ class DefaultShareProviderTest extends \Test\TestCase { } - public function testDeleteFromSelfGroupDoesNotExist() { - $this->expectException(\OC\Share20\Exception\ProviderException::class); + public function testDeleteFromSelfGroupDoesNotExist(): void { + $this->expectException(ProviderException::class); $this->expectExceptionMessage('Group "group" does not exist'); $qb = $this->dbConn->getQueryBuilder(); @@ -1633,14 +1713,14 @@ class DefaultShareProviderTest extends \Test\TestCase { $file->method('getId')->willReturn(1); $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf(); - $this->rootFolder->method('getById')->with(1)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file); $share = $this->provider->getShareById($id); $this->provider->deleteFromSelf($share, 'user2'); } - public function testDeleteFromSelfUser() { + public function testDeleteFromSelfUser(): void { $qb = $this->dbConn->getQueryBuilder(); $stmt = $qb->insert('share') ->values([ @@ -1671,7 +1751,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $file->method('getId')->willReturn(1); $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf(); - $this->rootFolder->method('getById')->with(1)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file); $share = $this->provider->getShareById($id); @@ -1690,8 +1770,8 @@ class DefaultShareProviderTest extends \Test\TestCase { } - public function testDeleteFromSelfUserNotRecipient() { - $this->expectException(\OC\Share20\Exception\ProviderException::class); + public function testDeleteFromSelfUserNotRecipient(): void { + $this->expectException(ProviderException::class); $this->expectExceptionMessage('Recipient does not match'); $qb = $this->dbConn->getQueryBuilder(); @@ -1725,7 +1805,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $file->method('getId')->willReturn(1); $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf(); - $this->rootFolder->method('getById')->with(1)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file); $share = $this->provider->getShareById($id); @@ -1733,8 +1813,8 @@ class DefaultShareProviderTest extends \Test\TestCase { } - public function testDeleteFromSelfLink() { - $this->expectException(\OC\Share20\Exception\ProviderException::class); + public function testDeleteFromSelfLink(): void { + $this->expectException(ProviderException::class); $this->expectExceptionMessage('Invalid shareType'); $qb = $this->dbConn->getQueryBuilder(); @@ -1762,23 +1842,23 @@ class DefaultShareProviderTest extends \Test\TestCase { $file->method('getId')->willReturn(1); $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf(); - $this->rootFolder->method('getById')->with(1)->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file); $share = $this->provider->getShareById($id); $this->provider->deleteFromSelf($share, $user1); } - public function testUpdateUser() { + public function testUpdateUser(): void { $id = $this->addShareToDB(IShare::TYPE_USER, 'user0', 'user1', 'user2', 'file', 42, 'target', 31, null, null); $users = []; for ($i = 0; $i < 6; $i++) { $user = $this->createMock(IUser::class); - $user->method('getUID')->willReturn('user'.$i); + $user->method('getUID')->willReturn('user' . $i); $user->method('getDisplayName')->willReturn('user' . $i); - $users['user'.$i] = $user; + $users['user' . $i] = $user; } $this->userManager->method('get')->willReturnCallback( @@ -1793,9 +1873,9 @@ class DefaultShareProviderTest extends \Test\TestCase { $file2->method('getId')->willReturn(43); $folder1 = $this->createMock(Folder::class); - $folder1->method('getById')->with(42)->willReturn([$file1]); + $folder1->method('getFirstNodeById')->with(42)->willReturn($file1); $folder2 = $this->createMock(Folder::class); - $folder2->method('getById')->with(43)->willReturn([$file2]); + $folder2->method('getFirstNodeById')->with(43)->willReturn($file2); $this->rootFolder->method('getUserFolder')->willReturnMap([ ['user2', $folder1], @@ -1827,15 +1907,15 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertSame(1, $share2->getPermissions()); } - public function testUpdateLink() { + public function testUpdateLink(): void { $id = $this->addShareToDB(IShare::TYPE_LINK, null, 'user1', 'user2', 'file', 42, 'target', 31, null, null); $users = []; for ($i = 0; $i < 6; $i++) { $user = $this->createMock(IUser::class); - $user->method('getUID')->willReturn('user'.$i); - $users['user'.$i] = $user; + $user->method('getUID')->willReturn('user' . $i); + $users['user' . $i] = $user; } $this->userManager->method('get')->willReturnCallback( @@ -1850,9 +1930,9 @@ class DefaultShareProviderTest extends \Test\TestCase { $file2->method('getId')->willReturn(43); $folder1 = $this->createMock(Folder::class); - $folder1->method('getById')->with(42)->willReturn([$file1]); + $folder1->method('getFirstNodeById')->with(42)->willReturn($file1); $folder2 = $this->createMock(Folder::class); - $folder2->method('getById')->with(43)->willReturn([$file2]); + $folder2->method('getFirstNodeById')->with(43)->willReturn($file2); $this->rootFolder->method('getUserFolder')->willReturnMap([ ['user2', $folder1], @@ -1887,7 +1967,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertSame(1, $share2->getPermissions()); } - public function testUpdateLinkRemovePassword() { + public function testUpdateLinkRemovePassword(): void { $id = $this->addShareToDB(IShare::TYPE_LINK, 'foo', 'user1', 'user2', 'file', 42, 'target', 31, null, null); @@ -1900,8 +1980,8 @@ class DefaultShareProviderTest extends \Test\TestCase { $users = []; for ($i = 0; $i < 6; $i++) { $user = $this->createMock(IUser::class); - $user->method('getUID')->willReturn('user'.$i); - $users['user'.$i] = $user; + $user->method('getUID')->willReturn('user' . $i); + $users['user' . $i] = $user; } $this->userManager->method('get')->willReturnCallback( @@ -1916,9 +1996,9 @@ class DefaultShareProviderTest extends \Test\TestCase { $file2->method('getId')->willReturn(43); $folder1 = $this->createMock(Folder::class); - $folder1->method('getById')->with(42)->willReturn([$file1]); + $folder1->method('getFirstNodeById')->with(42)->willReturn($file1); $folder2 = $this->createMock(Folder::class); - $folder2->method('getById')->with(43)->willReturn([$file2]); + $folder2->method('getFirstNodeById')->with(43)->willReturn($file2); $this->rootFolder->method('getUserFolder')->willReturnMap([ ['user2', $folder1], @@ -1950,15 +2030,15 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertSame(1, $share2->getPermissions()); } - public function testUpdateGroupNoSub() { + public function testUpdateGroupNoSub(): void { $id = $this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user1', 'user2', 'file', 42, 'target', 31, null, null); $users = []; for ($i = 0; $i < 6; $i++) { $user = $this->createMock(IUser::class); - $user->method('getUID')->willReturn('user'.$i); - $users['user'.$i] = $user; + $user->method('getUID')->willReturn('user' . $i); + $users['user' . $i] = $user; } $this->userManager->method('get')->willReturnCallback( @@ -1970,8 +2050,9 @@ class DefaultShareProviderTest extends \Test\TestCase { $groups = []; for ($i = 0; $i < 2; $i++) { $group = $this->createMock(IGroup::class); - $group->method('getGID')->willReturn('group'.$i); - $groups['group'.$i] = $group; + $group->method('getGID')->willReturn('group' . $i); + $group->method('getDisplayName')->willReturn('group-displayname' . $i); + $groups['group' . $i] = $group; } $this->groupManager->method('get')->willReturnCallback( @@ -1986,9 +2067,9 @@ class DefaultShareProviderTest extends \Test\TestCase { $file2->method('getId')->willReturn(43); $folder1 = $this->createMock(Folder::class); - $folder1->method('getById')->with(42)->willReturn([$file1]); + $folder1->method('getFirstNodeById')->with(42)->willReturn($file1); $folder2 = $this->createMock(Folder::class); - $folder2->method('getById')->with(43)->willReturn([$file2]); + $folder2->method('getFirstNodeById')->with(43)->willReturn($file2); $this->rootFolder->method('getUserFolder')->willReturnMap([ ['user2', $folder1], @@ -2022,7 +2103,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertSame(1, $share2->getPermissions()); } - public function testUpdateGroupSubShares() { + public function testUpdateGroupSubShares(): void { $id = $this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user1', 'user2', 'file', 42, 'target', 31, null, null); @@ -2035,8 +2116,8 @@ class DefaultShareProviderTest extends \Test\TestCase { $users = []; for ($i = 0; $i < 6; $i++) { $user = $this->createMock(IUser::class); - $user->method('getUID')->willReturn('user'.$i); - $users['user'.$i] = $user; + $user->method('getUID')->willReturn('user' . $i); + $users['user' . $i] = $user; } $this->userManager->method('get')->willReturnCallback( @@ -2048,8 +2129,9 @@ class DefaultShareProviderTest extends \Test\TestCase { $groups = []; for ($i = 0; $i < 2; $i++) { $group = $this->createMock(IGroup::class); - $group->method('getGID')->willReturn('group'.$i); - $groups['group'.$i] = $group; + $group->method('getGID')->willReturn('group' . $i); + $group->method('getDisplayName')->willReturn('group-displayname' . $i); + $groups['group' . $i] = $group; } $this->groupManager->method('get')->willReturnCallback( @@ -2064,9 +2146,9 @@ class DefaultShareProviderTest extends \Test\TestCase { $file2->method('getId')->willReturn(43); $folder1 = $this->createMock(Folder::class); - $folder1->method('getById')->with(42)->willReturn([$file1]); + $folder1->method('getFirstNodeById')->with(42)->willReturn($file1); $folder2 = $this->createMock(Folder::class); - $folder2->method('getById')->with(43)->willReturn([$file2]); + $folder2->method('getFirstNodeById')->with(43)->willReturn($file2); $this->rootFolder->method('getUserFolder')->willReturnMap([ ['user2', $folder1], @@ -2122,7 +2204,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $stmt->closeCursor(); } - public function testMoveUserShare() { + public function testMoveUserShare(): void { $id = $this->addShareToDB(IShare::TYPE_USER, 'user0', 'user1', 'user1', 'file', 42, 'mytaret', 31, null, null); @@ -2142,7 +2224,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $file->method('getId')->willReturn(42); $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf(); - $this->rootFolder->method('getById')->willReturn([$file]); + $this->rootFolder->method('getFirstNodeById')->willReturn($file); $share = $this->provider->getShareById($id, null); @@ -2153,7 +2235,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertSame('/newTarget', $share->getTarget()); } - public function testMoveGroupShare() { + public function testMoveGroupShare(): void { $id = $this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user1', 'user1', 'file', 42, 'mytaret', 31, null, null); @@ -2165,6 +2247,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $group0 = $this->createMock(IGroup::class); $group0->method('getGID')->willReturn('group0'); $group0->method('inGroup')->with($user0)->willReturn(true); + $group0->method('getDisplayName')->willReturn('group0-displayname'); $this->groupManager->method('get')->with('group0')->willReturn($group0); @@ -2177,7 +2260,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $folder->method('getId')->willReturn(42); $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf(); - $this->rootFolder->method('getById')->willReturn([$folder]); + $this->rootFolder->method('getFirstNodeById')->willReturn($folder); $share = $this->provider->getShareById($id, 'user0'); @@ -2194,7 +2277,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertSame('/ultraNewTarget', $share->getTarget()); } - public function dataDeleteUser() { + public static function dataDeleteUser(): array { return [ [IShare::TYPE_USER, 'a', 'b', 'c', 'a', true], [IShare::TYPE_USER, 'a', 'b', 'c', 'b', false], @@ -2214,7 +2297,6 @@ class DefaultShareProviderTest extends \Test\TestCase { } /** - * @dataProvider dataDeleteUser * * @param int $type The shareType (user/group/link) * @param string $owner The owner of the share (uid) @@ -2223,7 +2305,8 @@ class DefaultShareProviderTest extends \Test\TestCase { * @param string $deletedUser The user that is deleted * @param bool $rowDeleted Is the row deleted in this setup */ - public function testDeleteUser($type, $owner, $initiator, $recipient, $deletedUser, $rowDeleted) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataDeleteUser')] + public function testDeleteUser($type, $owner, $initiator, $recipient, $deletedUser, $rowDeleted): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') ->setValue('share_type', $qb->createNamedParameter($type)) @@ -2252,7 +2335,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertCount($rowDeleted ? 0 : 1, $data); } - public function dataDeleteUserGroup() { + public static function dataDeleteUserGroup(): array { return [ ['a', 'b', 'c', 'a', true, true], ['a', 'b', 'c', 'b', false, false], @@ -2262,7 +2345,6 @@ class DefaultShareProviderTest extends \Test\TestCase { } /** - * @dataProvider dataDeleteUserGroup * * @param string $owner The owner of the share (uid) * @param string $initiator The initiator of the share (uid) @@ -2271,7 +2353,8 @@ class DefaultShareProviderTest extends \Test\TestCase { * @param bool $groupShareDeleted * @param bool $userGroupShareDeleted */ - public function testDeleteUserGroup($owner, $initiator, $recipient, $deletedUser, $groupShareDeleted, $userGroupShareDeleted) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataDeleteUserGroup')] + public function testDeleteUserGroup($owner, $initiator, $recipient, $deletedUser, $groupShareDeleted, $userGroupShareDeleted): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') ->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)) @@ -2321,7 +2404,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertCount($groupShareDeleted ? 0 : 1, $data); } - public function dataGroupDeleted() { + public static function dataGroupDeleted(): array { return [ [ [ @@ -2368,13 +2451,13 @@ class DefaultShareProviderTest extends \Test\TestCase { } /** - * @dataProvider dataGroupDeleted * * @param $shares * @param $groupToDelete * @param $shouldBeDeleted */ - public function testGroupDeleted($shares, $groupToDelete, $shouldBeDeleted) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGroupDeleted')] + public function testGroupDeleted($shares, $groupToDelete, $shouldBeDeleted): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') ->setValue('share_type', $qb->createNamedParameter($shares['type'])) @@ -2415,7 +2498,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertCount($shouldBeDeleted ? 0 : count($ids), $data); } - public function dataUserDeletedFromGroup() { + public static function dataUserDeletedFromGroup(): array { return [ ['group1', 'user1', true], ['group1', 'user2', false], @@ -2428,13 +2511,13 @@ class DefaultShareProviderTest extends \Test\TestCase { * And a user specific group share with 'user1'. * User $user is deleted from group $gid. * - * @dataProvider dataUserDeletedFromGroup * * @param string $group * @param string $user * @param bool $toDelete */ - public function testUserDeletedFromGroup($group, $user, $toDelete) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataUserDeletedFromGroup')] + public function testUserDeletedFromGroup($group, $user, $toDelete): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') ->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)) @@ -2473,10 +2556,10 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertCount($toDelete ? 0 : 1, $data); } - public function testGetSharesInFolder() { - $userManager = \OC::$server->getUserManager(); - $groupManager = \OC::$server->getGroupManager(); - $rootFolder = \OC::$server->getRootFolder(); + public function testGetSharesInFolder(): void { + $userManager = Server::get(IUserManager::class); + $groupManager = Server::get(IGroupManager::class); + $rootFolder = Server::get(IRootFolder::class); $provider = new DefaultShareProvider( $this->dbConn, @@ -2487,7 +2570,10 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->defaults, $this->l10nFactory, $this->urlGenerator, - $this->config + $this->timeFactory, + $this->logger, + $this->shareManager, + $this->config, ); $password = md5(time()); @@ -2503,14 +2589,14 @@ class DefaultShareProviderTest extends \Test\TestCase { $file1 = $folder1->newFile('bar'); $folder2 = $folder1->newFolder('baz'); - $shareManager = \OC::$server->getShareManager(); + $shareManager = Server::get(IShareManager::class); $share1 = $shareManager->newShare(); $share1->setNode($folder1) ->setSharedBy($u1->getUID()) ->setSharedWith($u2->getUID()) ->setShareOwner($u1->getUID()) ->setShareType(IShare::TYPE_USER) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $share1 = $this->provider->create($share1); $share2 = $shareManager->newShare(); @@ -2519,7 +2605,7 @@ class DefaultShareProviderTest extends \Test\TestCase { ->setSharedWith($u3->getUID()) ->setShareOwner($u1->getUID()) ->setShareType(IShare::TYPE_USER) - ->setPermissions(\OCP\Constants::PERMISSION_READ); + ->setPermissions(Constants::PERMISSION_READ); $share2 = $this->provider->create($share2); $share3 = $shareManager->newShare(); @@ -2527,7 +2613,7 @@ class DefaultShareProviderTest extends \Test\TestCase { ->setSharedBy($u2->getUID()) ->setShareOwner($u1->getUID()) ->setShareType(IShare::TYPE_LINK) - ->setPermissions(\OCP\Constants::PERMISSION_READ); + ->setPermissions(Constants::PERMISSION_READ); $share3 = $this->provider->create($share3); $share4 = $shareManager->newShare(); @@ -2536,7 +2622,7 @@ class DefaultShareProviderTest extends \Test\TestCase { ->setSharedWith($g1->getGID()) ->setShareOwner($u1->getUID()) ->setShareType(IShare::TYPE_GROUP) - ->setPermissions(\OCP\Constants::PERMISSION_READ); + ->setPermissions(Constants::PERMISSION_READ); $share4 = $this->provider->create($share4); $result = $provider->getSharesInFolder($u1->getUID(), $folder1, false); @@ -2571,10 +2657,10 @@ class DefaultShareProviderTest extends \Test\TestCase { $g1->delete(); } - public function testGetAccessListNoCurrentAccessRequired() { - $userManager = \OC::$server->getUserManager(); - $groupManager = \OC::$server->getGroupManager(); - $rootFolder = \OC::$server->getRootFolder(); + public function testGetAccessListNoCurrentAccessRequired(): void { + $userManager = Server::get(IUserManager::class); + $groupManager = Server::get(IGroupManager::class); + $rootFolder = Server::get(IRootFolder::class); $provider = new DefaultShareProvider( $this->dbConn, @@ -2585,7 +2671,10 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->defaults, $this->l10nFactory, $this->urlGenerator, - $this->config + $this->timeFactory, + $this->logger, + $this->shareManager, + $this->config, ); $u1 = $userManager->createUser('testShare1', 'test'); @@ -2607,15 +2696,16 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertCount(0, $result['users']); $this->assertFalse($result['public']); - $shareManager = \OC::$server->getShareManager(); + $shareManager = Server::get(IShareManager::class); $share1 = $shareManager->newShare(); $share1->setNode($folder1) ->setSharedBy($u1->getUID()) ->setSharedWith($u2->getUID()) ->setShareOwner($u1->getUID()) ->setShareType(IShare::TYPE_USER) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $share1 = $this->provider->create($share1); + $share1 = $provider->acceptShare($share1, $u2->getUid()); $share2 = $shareManager->newShare(); $share2->setNode($folder2) @@ -2623,17 +2713,20 @@ class DefaultShareProviderTest extends \Test\TestCase { ->setSharedWith($g1->getGID()) ->setShareOwner($u1->getUID()) ->setShareType(IShare::TYPE_GROUP) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $share2 = $this->provider->create($share2); $shareManager->deleteFromSelf($share2, $u4->getUID()); + $share2 = $provider->acceptShare($share2, $u3->getUid()); + $share2 = $provider->acceptShare($share2, $u4->getUid()); + $share3 = $shareManager->newShare(); $share3->setNode($file1) ->setSharedBy($u3->getUID()) ->setShareOwner($u1->getUID()) ->setShareType(IShare::TYPE_LINK) - ->setPermissions(\OCP\Constants::PERMISSION_READ); + ->setPermissions(Constants::PERMISSION_READ); $share3 = $this->provider->create($share3); $share4 = $shareManager->newShare(); @@ -2642,8 +2735,9 @@ class DefaultShareProviderTest extends \Test\TestCase { ->setSharedWith($u5->getUID()) ->setShareOwner($u1->getUID()) ->setShareType(IShare::TYPE_USER) - ->setPermissions(\OCP\Constants::PERMISSION_READ); + ->setPermissions(Constants::PERMISSION_READ); $share4 = $this->provider->create($share4); + $share4 = $provider->acceptShare($share4, $u5->getUid()); $result = $provider->getAccessList([$folder1, $folder2, $file1], false); @@ -2667,10 +2761,10 @@ class DefaultShareProviderTest extends \Test\TestCase { $g1->delete(); } - public function testGetAccessListCurrentAccessRequired() { - $userManager = \OC::$server->getUserManager(); - $groupManager = \OC::$server->getGroupManager(); - $rootFolder = \OC::$server->getRootFolder(); + public function testGetAccessListCurrentAccessRequired(): void { + $userManager = Server::get(IUserManager::class); + $groupManager = Server::get(IGroupManager::class); + $rootFolder = Server::get(IRootFolder::class); $provider = new DefaultShareProvider( $this->dbConn, @@ -2681,7 +2775,10 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->defaults, $this->l10nFactory, $this->urlGenerator, - $this->config + $this->timeFactory, + $this->logger, + $this->shareManager, + $this->config, ); $u1 = $userManager->createUser('testShare1', 'test'); @@ -2703,15 +2800,16 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertCount(0, $result['users']); $this->assertFalse($result['public']); - $shareManager = \OC::$server->getShareManager(); + $shareManager = Server::get(IShareManager::class); $share1 = $shareManager->newShare(); $share1->setNode($folder1) ->setSharedBy($u1->getUID()) ->setSharedWith($u2->getUID()) ->setShareOwner($u1->getUID()) ->setShareType(IShare::TYPE_USER) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $share1 = $this->provider->create($share1); + $share1 = $provider->acceptShare($share1, $u2->getUid()); $share2 = $shareManager->newShare(); $share2->setNode($folder2) @@ -2719,8 +2817,10 @@ class DefaultShareProviderTest extends \Test\TestCase { ->setSharedWith($g1->getGID()) ->setShareOwner($u1->getUID()) ->setShareType(IShare::TYPE_GROUP) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $share2 = $this->provider->create($share2); + $share2 = $provider->acceptShare($share2, $u3->getUid()); + $share2 = $provider->acceptShare($share2, $u4->getUid()); $shareManager->deleteFromSelf($share2, $u4->getUID()); @@ -2729,7 +2829,7 @@ class DefaultShareProviderTest extends \Test\TestCase { ->setSharedBy($u3->getUID()) ->setShareOwner($u1->getUID()) ->setShareType(IShare::TYPE_LINK) - ->setPermissions(\OCP\Constants::PERMISSION_READ); + ->setPermissions(Constants::PERMISSION_READ); $share3 = $this->provider->create($share3); $share4 = $shareManager->newShare(); @@ -2738,8 +2838,9 @@ class DefaultShareProviderTest extends \Test\TestCase { ->setSharedWith($u5->getUID()) ->setShareOwner($u1->getUID()) ->setShareType(IShare::TYPE_USER) - ->setPermissions(\OCP\Constants::PERMISSION_READ); + ->setPermissions(Constants::PERMISSION_READ); $share4 = $this->provider->create($share4); + $share4 = $provider->acceptShare($share4, $u5->getUid()); $result = $provider->getAccessList([$folder1, $folder2, $file1], true); @@ -2762,7 +2863,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $g1->delete(); } - public function testGetAllShares() { + public function testGetAllShares(): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share') @@ -2843,23 +2944,23 @@ class DefaultShareProviderTest extends \Test\TestCase { $ownerPath1 = $this->createMock(File::class); $shareOwner1Folder = $this->createMock(Folder::class); - $shareOwner1Folder->method('getById')->willReturn([$ownerPath1]); + $shareOwner1Folder->method('getFirstNodeById')->willReturn($ownerPath1); $ownerPath2 = $this->createMock(File::class); $shareOwner2Folder = $this->createMock(Folder::class); - $shareOwner2Folder->method('getById')->willReturn([$ownerPath2]); + $shareOwner2Folder->method('getFirstNodeById')->willReturn($ownerPath2); $ownerPath3 = $this->createMock(File::class); $shareOwner3Folder = $this->createMock(Folder::class); - $shareOwner3Folder->method('getById')->willReturn([$ownerPath3]); + $shareOwner3Folder->method('getFirstNodeById')->willReturn($ownerPath3); $ownerPath4 = $this->createMock(File::class); $shareOwner4Folder = $this->createMock(Folder::class); - $shareOwner4Folder->method('getById')->willReturn([$ownerPath4]); + $shareOwner4Folder->method('getFirstNodeById')->willReturn($ownerPath4); $ownerPath5 = $this->createMock(File::class); $shareOwner5Folder = $this->createMock(Folder::class); - $shareOwner5Folder->method('getById')->willReturn([$ownerPath5]); + $shareOwner5Folder->method('getFirstNodeById')->willReturn($ownerPath5); $this->rootFolder ->method('getUserFolder') @@ -2926,4 +3027,88 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertEquals('token5', $share->getToken()); $this->assertEquals('myTarget5', $share->getTarget()); } + + + public function testGetSharesByPath(): void { + $qb = $this->dbConn->getQueryBuilder(); + + $qb->insert('share') + ->values([ + 'share_type' => $qb->expr()->literal(IShare::TYPE_USER), + 'uid_owner' => $qb->expr()->literal('user1'), + 'uid_initiator' => $qb->expr()->literal('user1'), + 'share_with' => $qb->expr()->literal('user2'), + 'item_type' => $qb->expr()->literal('file'), + 'file_source' => $qb->expr()->literal(1), + ]); + $qb->execute(); + + $id1 = $qb->getLastInsertId(); + + $qb->insert('share') + ->values([ + 'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP), + 'uid_owner' => $qb->expr()->literal('user1'), + 'uid_initiator' => $qb->expr()->literal('user1'), + 'share_with' => $qb->expr()->literal('user2'), + 'item_type' => $qb->expr()->literal('file'), + 'file_source' => $qb->expr()->literal(1), + ]); + $qb->execute(); + + $id2 = $qb->getLastInsertId(); + + $qb->insert('share') + ->values([ + 'share_type' => $qb->expr()->literal(IShare::TYPE_LINK), + 'uid_owner' => $qb->expr()->literal('user1'), + 'uid_initiator' => $qb->expr()->literal('user1'), + 'share_with' => $qb->expr()->literal('user2'), + 'item_type' => $qb->expr()->literal('file'), + 'file_source' => $qb->expr()->literal(1), + ]); + $qb->execute(); + + $id3 = $qb->getLastInsertId(); + + $ownerPath1 = $this->createMock(File::class); + $shareOwner1Folder = $this->createMock(Folder::class); + $shareOwner1Folder->method('getFirstNodeById')->willReturn($ownerPath1); + + $ownerPath2 = $this->createMock(File::class); + $shareOwner2Folder = $this->createMock(Folder::class); + $shareOwner2Folder->method('getFirstNodeById')->willReturn($ownerPath2); + + $ownerPath3 = $this->createMock(File::class); + $shareOwner3Folder = $this->createMock(Folder::class); + $shareOwner3Folder->method('getFirstNodeById')->willReturn($ownerPath3); + + $this->rootFolder + ->method('getUserFolder') + ->willReturnMap( + [ + ['shareOwner1', $shareOwner1Folder], + ['shareOwner2', $shareOwner2Folder], + ['shareOwner3', $shareOwner3Folder], + ] + ); + + $node = $this->createMock(Node::class); + $node + ->expects($this->once()) + ->method('getId') + ->willReturn(1); + + $shares = $this->provider->getSharesByPath($node); + $this->assertCount(3, $shares); + + $this->assertEquals($id1, $shares[0]->getId()); + $this->assertEquals(IShare::TYPE_USER, $shares[0]->getShareType()); + + $this->assertEquals($id2, $shares[1]->getId()); + $this->assertEquals(IShare::TYPE_GROUP, $shares[1]->getShareType()); + + $this->assertEquals($id3, $shares[2]->getId()); + $this->assertEquals(IShare::TYPE_LINK, $shares[2]->getShareType()); + } } diff --git a/tests/lib/Share20/LegacyHooksTest.php b/tests/lib/Share20/LegacyHooksTest.php index 5afee588c34..2ce72b3fc1c 100644 --- a/tests/lib/Share20/LegacyHooksTest.php +++ b/tests/lib/Share20/LegacyHooksTest.php @@ -1,44 +1,50 @@ <?php + /** - * @copyright 2017, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Share20; +use OC\EventDispatcher\EventDispatcher; use OC\Share20\LegacyHooks; use OC\Share20\Manager; use OCP\Constants; +use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Cache\ICacheEntry; use OCP\Files\File; +use OCP\IServerContainer; +use OCP\Server; +use OCP\Share\Events\BeforeShareCreatedEvent; +use OCP\Share\Events\BeforeShareDeletedEvent; +use OCP\Share\Events\ShareCreatedEvent; +use OCP\Share\Events\ShareDeletedEvent; +use OCP\Share\Events\ShareDeletedFromSelfEvent; +use OCP\Share\IManager as IShareManager; use OCP\Share\IShare; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\EventDispatcher\GenericEvent; +use OCP\Util; +use Psr\Log\LoggerInterface; use Test\TestCase; -class LegacyHooksTest extends TestCase { +class Dummy { + public function postShare() { + } + public function preShare() { + } + public function postFromSelf() { + } + public function post() { + } + public function pre() { + } +} +class LegacyHooksTest extends TestCase { /** @var LegacyHooks */ private $hooks; - /** @var EventDispatcher */ + /** @var IEventDispatcher */ private $eventDispatcher; /** @var Manager */ @@ -47,12 +53,14 @@ class LegacyHooksTest extends TestCase { protected function setUp(): void { parent::setUp(); - $this->eventDispatcher = new EventDispatcher(); + $symfonyDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher(); + $logger = $this->createMock(LoggerInterface::class); + $this->eventDispatcher = new EventDispatcher($symfonyDispatcher, Server::get(IServerContainer::class), $logger); $this->hooks = new LegacyHooks($this->eventDispatcher); - $this->manager = \OC::$server->getShareManager(); + $this->manager = Server::get(IShareManager::class); } - public function testPreUnshare() { + public function testPreUnshare(): void { $path = $this->createMock(File::class); $path->method('getId')->willReturn(1); @@ -69,8 +77,8 @@ class LegacyHooksTest extends TestCase { ->setTarget('myTarget') ->setNodeCacheEntry($info); - $hookListner = $this->getMockBuilder('Dummy')->setMethods(['pre'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'pre_unshare', $hookListner, 'pre'); + $hookListner = $this->getMockBuilder(Dummy::class)->onlyMethods(['pre'])->getMock(); + Util::connectHook('OCP\Share', 'pre_unshare', $hookListner, 'pre'); $hookListnerExpectsPre = [ 'id' => 42, @@ -89,11 +97,11 @@ class LegacyHooksTest extends TestCase { ->method('pre') ->with($hookListnerExpectsPre); - $event = new GenericEvent($share); - $this->eventDispatcher->dispatch('OCP\Share::preUnshare', $event); + $event = new BeforeShareDeletedEvent($share); + $this->eventDispatcher->dispatchTyped($event); } - public function testPostUnshare() { + public function testPostUnshare(): void { $path = $this->createMock(File::class); $path->method('getId')->willReturn(1); @@ -110,8 +118,8 @@ class LegacyHooksTest extends TestCase { ->setTarget('myTarget') ->setNodeCacheEntry($info); - $hookListner = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_unshare', $hookListner, 'post'); + $hookListner = $this->getMockBuilder(Dummy::class)->onlyMethods(['post'])->getMock(); + Util::connectHook('OCP\Share', 'post_unshare', $hookListner, 'post'); $hookListnerExpectsPost = [ 'id' => 42, @@ -143,12 +151,11 @@ class LegacyHooksTest extends TestCase { ->method('post') ->with($hookListnerExpectsPost); - $event = new GenericEvent($share); - $event->setArgument('deletedShares', [$share]); - $this->eventDispatcher->dispatch('OCP\Share::postUnshare', $event); + $event = new ShareDeletedEvent($share); + $this->eventDispatcher->dispatchTyped($event); } - public function testPostUnshareFromSelf() { + public function testPostUnshareFromSelf(): void { $path = $this->createMock(File::class); $path->method('getId')->willReturn(1); @@ -165,8 +172,8 @@ class LegacyHooksTest extends TestCase { ->setTarget('myTarget') ->setNodeCacheEntry($info); - $hookListner = $this->getMockBuilder('Dummy')->setMethods(['postFromSelf'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_unshareFromSelf', $hookListner, 'postFromSelf'); + $hookListner = $this->getMockBuilder(Dummy::class)->onlyMethods(['postFromSelf'])->getMock(); + Util::connectHook('OCP\Share', 'post_unshareFromSelf', $hookListner, 'postFromSelf'); $hookListnerExpectsPostFromSelf = [ 'id' => 42, @@ -200,11 +207,11 @@ class LegacyHooksTest extends TestCase { ->method('postFromSelf') ->with($hookListnerExpectsPostFromSelf); - $event = new GenericEvent($share); - $this->eventDispatcher->dispatch('OCP\Share::postUnshareFromSelf', $event); + $event = new ShareDeletedFromSelfEvent($share); + $this->eventDispatcher->dispatchTyped($event); } - public function testPreShare() { + public function testPreShare(): void { $path = $this->createMock(File::class); $path->method('getId')->willReturn(1); @@ -222,8 +229,8 @@ class LegacyHooksTest extends TestCase { ->setToken('token'); - $hookListner = $this->getMockBuilder('Dummy')->setMethods(['preShare'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'pre_shared', $hookListner, 'preShare'); + $hookListner = $this->getMockBuilder(Dummy::class)->onlyMethods(['preShare'])->getMock(); + Util::connectHook('OCP\Share', 'pre_shared', $hookListner, 'preShare'); $run = true; $error = ''; @@ -248,11 +255,11 @@ class LegacyHooksTest extends TestCase { ->method('preShare') ->with($expected); - $event = new GenericEvent($share); - $this->eventDispatcher->dispatch('OCP\Share::preShare', $event); + $event = new BeforeShareCreatedEvent($share); + $this->eventDispatcher->dispatchTyped($event); } - public function testPreShareError() { + public function testPreShareError(): void { $path = $this->createMock(File::class); $path->method('getId')->willReturn(1); @@ -270,8 +277,8 @@ class LegacyHooksTest extends TestCase { ->setToken('token'); - $hookListner = $this->getMockBuilder('Dummy')->setMethods(['preShare'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'pre_shared', $hookListner, 'preShare'); + $hookListner = $this->getMockBuilder(Dummy::class)->onlyMethods(['preShare'])->getMock(); + Util::connectHook('OCP\Share', 'pre_shared', $hookListner, 'preShare'); $run = true; $error = ''; @@ -295,19 +302,19 @@ class LegacyHooksTest extends TestCase { ->expects($this->exactly(1)) ->method('preShare') ->with($expected) - ->willReturnCallback(function ($data) { + ->willReturnCallback(function ($data): void { $data['run'] = false; $data['error'] = 'I error'; }); - $event = new GenericEvent($share); - $this->eventDispatcher->dispatch('OCP\Share::preShare', $event); + $event = new BeforeShareCreatedEvent($share); + $this->eventDispatcher->dispatchTyped($event); $this->assertTrue($event->isPropagationStopped()); - $this->assertSame('I error', $event->getArgument('error')); + $this->assertSame('I error', $event->getError()); } - public function testPostShare() { + public function testPostShare(): void { $path = $this->createMock(File::class); $path->method('getId')->willReturn(1); @@ -326,8 +333,8 @@ class LegacyHooksTest extends TestCase { ->setToken('token'); - $hookListner = $this->getMockBuilder('Dummy')->setMethods(['postShare'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_shared', $hookListner, 'postShare'); + $hookListner = $this->getMockBuilder(Dummy::class)->onlyMethods(['postShare'])->getMock(); + Util::connectHook('OCP\Share', 'post_shared', $hookListner, 'postShare'); $expected = [ 'id' => 42, @@ -350,7 +357,7 @@ class LegacyHooksTest extends TestCase { ->method('postShare') ->with($expected); - $event = new GenericEvent($share); - $this->eventDispatcher->dispatch('OCP\Share::postShare', $event); + $event = new ShareCreatedEvent($share); + $this->eventDispatcher->dispatchTyped($event); } } diff --git a/tests/lib/Share20/ManagerTest.php b/tests/lib/Share20/ManagerTest.php index 2ed99519df6..0e37934786a 100644 --- a/tests/lib/Share20/ManagerTest.php +++ b/tests/lib/Share20/ManagerTest.php @@ -1,32 +1,23 @@ <?php + /** - * @author Roeland Jago Douma <rullzer@owncloud.com> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Test\Share20; +use DateTimeZone; use OC\Files\Mount\MoveableMount; +use OC\Files\Utils\PathHelper; use OC\KnownUser\KnownUserService; use OC\Share20\DefaultShareProvider; -use OC\Share20\Exception; +use OC\Share20\Exception\ProviderException; use OC\Share20\Manager; use OC\Share20\Share; +use OC\Share20\ShareDisableChecker; +use OCP\Constants; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\File; @@ -34,10 +25,13 @@ use OCP\Files\Folder; use OCP\Files\IRootFolder; use OCP\Files\Mount\IMountManager; use OCP\Files\Mount\IMountPoint; +use OCP\Files\Mount\IShareOwnerlessMount; use OCP\Files\Node; -use OCP\Files\Storage; +use OCP\Files\Storage\IStorage; use OCP\HintException; +use OCP\IAppConfig; use OCP\IConfig; +use OCP\IDateTimeZone; use OCP\IGroup; use OCP\IGroupManager; use OCP\IL10N; @@ -51,17 +45,30 @@ use OCP\Mail\IMailer; use OCP\Security\Events\ValidatePasswordPolicyEvent; use OCP\Security\IHasher; use OCP\Security\ISecureRandom; +use OCP\Share\Events\BeforeShareCreatedEvent; +use OCP\Share\Events\BeforeShareDeletedEvent; +use OCP\Share\Events\ShareCreatedEvent; +use OCP\Share\Events\ShareDeletedEvent; +use OCP\Share\Events\ShareDeletedFromSelfEvent; use OCP\Share\Exceptions\AlreadySharedException; +use OCP\Share\Exceptions\GenericShareException; use OCP\Share\Exceptions\ShareNotFound; use OCP\Share\IManager; use OCP\Share\IProviderFactory; use OCP\Share\IShare; use OCP\Share\IShareProvider; +use OCP\Share\IShareProviderSupportsAllSharesInFolder; +use OCP\Util; use PHPUnit\Framework\MockObject\MockBuilder; use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\GenericEvent; + +class DummyShareManagerListener { + public function post() { + } + public function listener() { + } +} /** * Class ManagerTest @@ -70,7 +77,6 @@ use Symfony\Component\EventDispatcher\GenericEvent; * @group DB */ class ManagerTest extends \Test\TestCase { - /** @var Manager */ protected $manager; /** @var LoggerInterface|MockObject */ @@ -83,9 +89,9 @@ class ManagerTest extends \Test\TestCase { protected $hasher; /** @var IShareProvider|MockObject */ protected $defaultProvider; - /** @var IMountManager|MockObject */ + /** @var IMountManager|MockObject */ protected $mountManager; - /** @var IGroupManager|MockObject */ + /** @var IGroupManager|MockObject */ protected $groupManager; /** @var IL10N|MockObject */ protected $l; @@ -97,20 +103,25 @@ class ManagerTest extends \Test\TestCase { protected $userManager; /** @var IRootFolder | MockObject */ protected $rootFolder; - /** @var EventDispatcherInterface | MockObject */ - protected $eventDispatcher; /** @var IEventDispatcher|MockObject */ protected $dispatcher; - /** @var IMailer|MockObject */ + /** @var IMailer|MockObject */ protected $mailer; - /** @var IURLGenerator|MockObject */ + /** @var IURLGenerator|MockObject */ protected $urlGenerator; - /** @var \OC_Defaults|MockObject */ + /** @var \OC_Defaults|MockObject */ protected $defaults; - /** @var IUserSession|MockObject */ + /** @var IUserSession|MockObject */ protected $userSession; - /** @var KnownUserService|MockObject */ + /** @var KnownUserService|MockObject */ protected $knownUserService; + /** @var ShareDisableChecker|MockObject */ + protected $shareDisabledChecker; + private DateTimeZone $timezone; + /** @var IDateTimeZone|MockObject */ + protected $dateTimeZone; + /** @var IAppConfig|MockObject */ + protected $appConfig; protected function setUp(): void { $this->logger = $this->createMock(LoggerInterface::class); @@ -121,7 +132,6 @@ class ManagerTest extends \Test\TestCase { $this->groupManager = $this->createMock(IGroupManager::class); $this->userManager = $this->createMock(IUserManager::class); $this->rootFolder = $this->createMock(IRootFolder::class); - $this->eventDispatcher = $this->createMock(EventDispatcherInterface::class); $this->mailer = $this->createMock(IMailer::class); $this->urlGenerator = $this->createMock(IURLGenerator::class); $this->defaults = $this->createMock(\OC_Defaults::class); @@ -129,6 +139,13 @@ class ManagerTest extends \Test\TestCase { $this->userSession = $this->createMock(IUserSession::class); $this->knownUserService = $this->createMock(KnownUserService::class); + $this->shareDisabledChecker = new ShareDisableChecker($this->config, $this->userManager, $this->groupManager); + $this->dateTimeZone = $this->createMock(IDateTimeZone::class); + $this->timezone = new \DateTimeZone('Pacific/Auckland'); + $this->dateTimeZone->method('getTimeZone')->willReturnCallback(fn () => $this->timezone); + + $this->appConfig = $this->createMock(IAppConfig::class); + $this->l10nFactory = $this->createMock(IFactory::class); $this->l = $this->createMock(IL10N::class); $this->l->method('t') @@ -139,33 +156,39 @@ class ManagerTest extends \Test\TestCase { ->willReturnCallback(function ($singular, $plural, $count, $parameters = []) { return vsprintf(str_replace('%n', $count, ($count === 1) ? $singular : $plural), $parameters); }); + $this->l10nFactory->method('get')->willReturn($this->l); $this->factory = new DummyFactory(\OC::$server); - $this->manager = new Manager( + $this->manager = $this->createManager($this->factory); + + $this->defaultProvider = $this->createMock(DefaultShareProvider::class); + $this->defaultProvider->method('identifier')->willReturn('default'); + $this->factory->setProvider($this->defaultProvider); + } + + private function createManager(IProviderFactory $factory): Manager { + return new Manager( $this->logger, $this->config, $this->secureRandom, $this->hasher, $this->mountManager, $this->groupManager, - $this->l, $this->l10nFactory, - $this->factory, + $factory, $this->userManager, $this->rootFolder, - $this->eventDispatcher, $this->mailer, $this->urlGenerator, $this->defaults, $this->dispatcher, $this->userSession, - $this->knownUserService + $this->knownUserService, + $this->shareDisabledChecker, + $this->dateTimeZone, + $this->appConfig, ); - - $this->defaultProvider = $this->createMock(DefaultShareProvider::class); - $this->defaultProvider->method('identifier')->willReturn('default'); - $this->factory->setProvider($this->defaultProvider); } /** @@ -180,23 +203,32 @@ class ManagerTest extends \Test\TestCase { $this->hasher, $this->mountManager, $this->groupManager, - $this->l, $this->l10nFactory, $this->factory, $this->userManager, $this->rootFolder, - $this->eventDispatcher, $this->mailer, $this->urlGenerator, $this->defaults, $this->dispatcher, $this->userSession, - $this->knownUserService + $this->knownUserService, + $this->shareDisabledChecker, + $this->dateTimeZone, + $this->appConfig, ]); } + private function createFolderMock(string $folderPath): MockObject&Folder { + $folder = $this->createMock(Folder::class); + $folder->method('getPath')->willReturn($folderPath); + $folder->method('getRelativePath')->willReturnCallback( + fn (string $path): ?string => PathHelper::getRelativePath($folderPath, $path) + ); + return $folder; + } - public function testDeleteNoShareId() { + public function testDeleteNoShareId(): void { $this->expectException(\InvalidArgumentException::class); $share = $this->manager->newShare(); @@ -204,13 +236,7 @@ class ManagerTest extends \Test\TestCase { $this->manager->deleteShare($share); } - public function dataTestDelete() { - $user = $this->createMock(IUser::class); - $user->method('getUID')->willReturn('sharedWithUser'); - - $group = $this->createMock(IGroup::class); - $group->method('getGID')->willReturn('sharedWithGroup'); - + public static function dataTestDelete(): array { return [ [IShare::TYPE_USER, 'sharedWithUser'], [IShare::TYPE_GROUP, 'sharedWithGroup'], @@ -219,12 +245,10 @@ class ManagerTest extends \Test\TestCase { ]; } - /** - * @dataProvider dataTestDelete - */ - public function testDelete($shareType, $sharedWith) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestDelete')] + public function testDelete($shareType, $sharedWith): void { $manager = $this->createManagerMock() - ->setMethods(['getShareById', 'deleteChildren']) + ->onlyMethods(['getShareById', 'deleteChildren', 'promoteReshares']) ->getMock(); $manager->method('deleteChildren')->willReturn([]); @@ -242,36 +266,31 @@ class ManagerTest extends \Test\TestCase { ->setTarget('myTarget'); $manager->expects($this->once())->method('deleteChildren')->with($share); + $manager->expects($this->once())->method('promoteReshares')->with($share); $this->defaultProvider ->expects($this->once()) ->method('delete') ->with($share); - $this->eventDispatcher->expects($this->at(0)) - ->method('dispatch') - ->with( - 'OCP\Share::preUnshare', - $this->callBack(function (GenericEvent $e) use ($share) { - return $e->getSubject() === $share; - }) - ); - $this->eventDispatcher->expects($this->at(1)) - ->method('dispatch') - ->with( - 'OCP\Share::postUnshare', - $this->callBack(function (GenericEvent $e) use ($share) { - return $e->getSubject() === $share && - $e->getArgument('deletedShares') === [$share]; - }) - ); + $calls = [ + BeforeShareDeletedEvent::class, + ShareDeletedEvent::class, + ]; + $this->dispatcher->expects($this->exactly(2)) + ->method('dispatchTyped') + ->willReturnCallback(function ($event) use (&$calls, $share): void { + $expected = array_shift($calls); + $this->assertInstanceOf($expected, $event); + $this->assertEquals($share, $event->getShare()); + }); $manager->deleteShare($share); } - public function testDeleteLazyShare() { + public function testDeleteLazyShare(): void { $manager = $this->createManagerMock() - ->setMethods(['getShareById', 'deleteChildren']) + ->onlyMethods(['getShareById', 'deleteChildren', 'promoteReshares']) ->getMock(); $manager->method('deleteChildren')->willReturn([]); @@ -290,36 +309,31 @@ class ManagerTest extends \Test\TestCase { $this->rootFolder->expects($this->never())->method($this->anything()); $manager->expects($this->once())->method('deleteChildren')->with($share); + $manager->expects($this->once())->method('promoteReshares')->with($share); $this->defaultProvider ->expects($this->once()) ->method('delete') ->with($share); - $this->eventDispatcher->expects($this->at(0)) - ->method('dispatch') - ->with( - 'OCP\Share::preUnshare', - $this->callBack(function (GenericEvent $e) use ($share) { - return $e->getSubject() === $share; - }) - ); - $this->eventDispatcher->expects($this->at(1)) - ->method('dispatch') - ->with( - 'OCP\Share::postUnshare', - $this->callBack(function (GenericEvent $e) use ($share) { - return $e->getSubject() === $share && - $e->getArgument('deletedShares') === [$share]; - }) - ); + $calls = [ + BeforeShareDeletedEvent::class, + ShareDeletedEvent::class, + ]; + $this->dispatcher->expects($this->exactly(2)) + ->method('dispatchTyped') + ->willReturnCallback(function ($event) use (&$calls, $share): void { + $expected = array_shift($calls); + $this->assertInstanceOf($expected, $event); + $this->assertEquals($share, $event->getShare()); + }); $manager->deleteShare($share); } - public function testDeleteNested() { + public function testDeleteNested(): void { $manager = $this->createManagerMock() - ->setMethods(['getShareById']) + ->onlyMethods(['getShareById', 'promoteReshares']) ->getMock(); $path = $this->createMock(File::class); @@ -361,34 +375,40 @@ class ManagerTest extends \Test\TestCase { [$share3, []], ]); - $this->defaultProvider + $deleteCalls = [ + $share3, + $share2, + $share1, + ]; + $this->defaultProvider->expects($this->exactly(3)) ->method('delete') - ->withConsecutive([$share3], [$share2], [$share1]); + ->willReturnCallback(function ($share) use (&$deleteCalls): void { + $expected = array_shift($deleteCalls); + $this->assertEquals($expected, $share); + }); - $this->eventDispatcher->expects($this->at(0)) - ->method('dispatch') - ->with( - 'OCP\Share::preUnshare', - $this->callBack(function (GenericEvent $e) use ($share1) { - return $e->getSubject() === $share1; - }) - ); - $this->eventDispatcher->expects($this->at(1)) - ->method('dispatch') - ->with( - 'OCP\Share::postUnshare', - $this->callBack(function (GenericEvent $e) use ($share1, $share2, $share3) { - return $e->getSubject() === $share1 && - $e->getArgument('deletedShares') === [$share3, $share2, $share1]; - }) - ); + $dispatchCalls = [ + [BeforeShareDeletedEvent::class, $share1], + [BeforeShareDeletedEvent::class, $share2], + [BeforeShareDeletedEvent::class, $share3], + [ShareDeletedEvent::class, $share3], + [ShareDeletedEvent::class, $share2], + [ShareDeletedEvent::class, $share1], + ]; + $this->dispatcher->expects($this->exactly(6)) + ->method('dispatchTyped') + ->willReturnCallback(function ($event) use (&$dispatchCalls): void { + $expected = array_shift($dispatchCalls); + $this->assertInstanceOf($expected[0], $event); + $this->assertEquals($expected[1]->getId(), $event->getShare()->getId()); + }); $manager->deleteShare($share1); } - public function testDeleteFromSelf() { + public function testDeleteFromSelf(): void { $manager = $this->createManagerMock() - ->setMethods(['getShareById']) + ->onlyMethods(['getShareById']) ->getMock(); $recipientId = 'unshareFrom'; @@ -408,21 +428,20 @@ class ManagerTest extends \Test\TestCase { ->method('deleteFromSelf') ->with($share, $recipientId); - $this->eventDispatcher->expects($this->at(0)) - ->method('dispatch') + $this->dispatcher->expects($this->once()) + ->method('dispatchTyped') ->with( - 'OCP\Share::postUnshareFromSelf', - $this->callBack(function (GenericEvent $e) use ($share) { - return $e->getSubject() === $share; + $this->callBack(function (ShareDeletedFromSelfEvent $e) use ($share) { + return $e->getShare() === $share; }) ); $manager->deleteFromSelf($share, $recipientId); } - public function testDeleteChildren() { + public function testDeleteChildren(): void { $manager = $this->createManagerMock() - ->setMethods(['deleteShare']) + ->onlyMethods(['deleteShare']) ->getMock(); $share = $this->createMock(IShare::class); @@ -451,16 +470,213 @@ class ManagerTest extends \Test\TestCase { return []; }); - $this->defaultProvider - ->expects($this->exactly(3)) + $calls = [ + $child1, + $child2, + $child3, + ]; + $this->defaultProvider->expects($this->exactly(3)) ->method('delete') - ->withConsecutive([$child1], [$child2], [$child3]); + ->willReturnCallback(function ($share) use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals($expected, $share); + }); $result = self::invokePrivate($manager, 'deleteChildren', [$share]); $this->assertSame($shares, $result); } - public function testGetShareById() { + public function testPromoteReshareFile(): void { + $manager = $this->createManagerMock() + ->onlyMethods(['updateShare', 'getSharesInFolder', 'generalCreateChecks']) + ->getMock(); + + $file = $this->createMock(File::class); + + $share = $this->createMock(IShare::class); + $share->method('getShareType')->willReturn(IShare::TYPE_USER); + $share->method('getNodeType')->willReturn('folder'); + $share->method('getSharedWith')->willReturn('userB'); + $share->method('getNode')->willReturn($file); + + $reShare = $this->createMock(IShare::class); + $reShare->method('getShareType')->willReturn(IShare::TYPE_USER); + $reShare->method('getSharedBy')->willReturn('userB'); + $reShare->method('getSharedWith')->willReturn('userC'); + $reShare->method('getNode')->willReturn($file); + + $this->defaultProvider->method('getSharesBy') + ->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare, $file) { + $this->assertEquals($file, $node); + if ($shareType === IShare::TYPE_USER) { + return match($userId) { + 'userB' => [$reShare], + }; + } else { + return []; + } + }); + $manager->method('generalCreateChecks')->willThrowException(new GenericShareException()); + + $manager->expects($this->exactly(1))->method('updateShare')->with($reShare); + + self::invokePrivate($manager, 'promoteReshares', [$share]); + } + + public function testPromoteReshare(): void { + $manager = $this->createManagerMock() + ->onlyMethods(['updateShare', 'getSharesInFolder', 'generalCreateChecks']) + ->getMock(); + + $folder = $this->createFolderMock('/path/to/folder'); + + $subFolder = $this->createFolderMock('/path/to/folder/sub'); + + $otherFolder = $this->createFolderMock('/path/to/otherfolder/'); + + $share = $this->createMock(IShare::class); + $share->method('getShareType')->willReturn(IShare::TYPE_USER); + $share->method('getNodeType')->willReturn('folder'); + $share->method('getSharedWith')->willReturn('userB'); + $share->method('getNode')->willReturn($folder); + + $reShare = $this->createMock(IShare::class); + $reShare->method('getShareType')->willReturn(IShare::TYPE_USER); + $reShare->method('getSharedBy')->willReturn('userB'); + $reShare->method('getSharedWith')->willReturn('userC'); + $reShare->method('getNode')->willReturn($folder); + + $reShareInSubFolder = $this->createMock(IShare::class); + $reShareInSubFolder->method('getShareType')->willReturn(IShare::TYPE_USER); + $reShareInSubFolder->method('getSharedBy')->willReturn('userB'); + $reShareInSubFolder->method('getNode')->willReturn($subFolder); + + $reShareInOtherFolder = $this->createMock(IShare::class); + $reShareInOtherFolder->method('getShareType')->willReturn(IShare::TYPE_USER); + $reShareInOtherFolder->method('getSharedBy')->willReturn('userB'); + $reShareInOtherFolder->method('getNode')->willReturn($otherFolder); + + $this->defaultProvider->method('getSharesBy') + ->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare, $reShareInSubFolder, $reShareInOtherFolder) { + if ($shareType === IShare::TYPE_USER) { + return match($userId) { + 'userB' => [$reShare,$reShareInSubFolder,$reShareInOtherFolder], + }; + } else { + return []; + } + }); + $manager->method('generalCreateChecks')->willThrowException(new GenericShareException()); + + $calls = [ + $reShare, + $reShareInSubFolder, + ]; + $manager->expects($this->exactly(2)) + ->method('updateShare') + ->willReturnCallback(function ($share) use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals($expected, $share); + }); + + self::invokePrivate($manager, 'promoteReshares', [$share]); + } + + public function testPromoteReshareWhenUserHasAnotherShare(): void { + $manager = $this->createManagerMock() + ->onlyMethods(['updateShare', 'getSharesInFolder', 'getSharedWith', 'generalCreateChecks']) + ->getMock(); + + $folder = $this->createFolderMock('/path/to/folder'); + + $share = $this->createMock(IShare::class); + $share->method('getShareType')->willReturn(IShare::TYPE_USER); + $share->method('getNodeType')->willReturn('folder'); + $share->method('getSharedWith')->willReturn('userB'); + $share->method('getNode')->willReturn($folder); + + $reShare = $this->createMock(IShare::class); + $reShare->method('getShareType')->willReturn(IShare::TYPE_USER); + $reShare->method('getNodeType')->willReturn('folder'); + $reShare->method('getSharedBy')->willReturn('userB'); + $reShare->method('getNode')->willReturn($folder); + + $this->defaultProvider->method('getSharesBy')->willReturn([$reShare]); + $manager->method('generalCreateChecks')->willReturn(true); + + /* No share is promoted because generalCreateChecks does not throw */ + $manager->expects($this->never())->method('updateShare'); + + self::invokePrivate($manager, 'promoteReshares', [$share]); + } + + public function testPromoteReshareOfUsersInGroupShare(): void { + $manager = $this->createManagerMock() + ->onlyMethods(['updateShare', 'getSharesInFolder', 'getSharedWith', 'generalCreateChecks']) + ->getMock(); + + $folder = $this->createFolderMock('/path/to/folder'); + + $userA = $this->createMock(IUser::class); + $userA->method('getUID')->willReturn('userA'); + + $share = $this->createMock(IShare::class); + $share->method('getShareType')->willReturn(IShare::TYPE_GROUP); + $share->method('getNodeType')->willReturn('folder'); + $share->method('getSharedWith')->willReturn('Group'); + $share->method('getNode')->willReturn($folder); + $share->method('getShareOwner')->willReturn($userA); + + $reShare1 = $this->createMock(IShare::class); + $reShare1->method('getShareType')->willReturn(IShare::TYPE_USER); + $reShare1->method('getNodeType')->willReturn('folder'); + $reShare1->method('getSharedBy')->willReturn('userB'); + $reShare1->method('getNode')->willReturn($folder); + + $reShare2 = $this->createMock(IShare::class); + $reShare2->method('getShareType')->willReturn(IShare::TYPE_USER); + $reShare2->method('getNodeType')->willReturn('folder'); + $reShare2->method('getSharedBy')->willReturn('userC'); + $reShare2->method('getNode')->willReturn($folder); + + $userB = $this->createMock(IUser::class); + $userB->method('getUID')->willReturn('userB'); + $userC = $this->createMock(IUser::class); + $userC->method('getUID')->willReturn('userC'); + $group = $this->createMock(IGroup::class); + $group->method('getUsers')->willReturn([$userB, $userC]); + $this->groupManager->method('get')->with('Group')->willReturn($group); + + $this->defaultProvider->method('getSharesBy') + ->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare1, $reShare2) { + if ($shareType === IShare::TYPE_USER) { + return match($userId) { + 'userB' => [$reShare1], + 'userC' => [$reShare2], + }; + } else { + return []; + } + }); + $manager->method('generalCreateChecks')->willThrowException(new GenericShareException()); + + $manager->method('getSharedWith')->willReturn([]); + + $calls = [ + $reShare1, + $reShare2, + ]; + $manager->expects($this->exactly(2)) + ->method('updateShare') + ->willReturnCallback(function ($share) use (&$calls): void { + $expected = array_shift($calls); + $this->assertEquals($expected, $share); + }); + + self::invokePrivate($manager, 'promoteReshares', [$share]); + } + + public function testGetShareById(): void { $share = $this->createMock(IShare::class); $this->defaultProvider @@ -473,11 +689,11 @@ class ManagerTest extends \Test\TestCase { } - public function testGetExpiredShareById() { - $this->expectException(\OCP\Share\Exceptions\ShareNotFound::class); + public function testGetExpiredShareById(): void { + $this->expectException(ShareNotFound::class); $manager = $this->createManagerMock() - ->setMethods(['deleteShare']) + ->onlyMethods(['deleteShare']) ->getMock(); $date = new \DateTime(); @@ -500,19 +716,22 @@ class ManagerTest extends \Test\TestCase { } - public function testVerifyPasswordNullButEnforced() { + public function testVerifyPasswordNullButEnforced(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Passwords are enforced for link and mail shares'); $this->config->method('getAppValue')->willReturnMap([ ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], - ['core', 'shareapi_enforce_links_password', 'no', 'yes'], + ]); + + $this->appConfig->method('getValueBool')->willReturnMap([ + ['core', 'shareapi_enforce_links_password', true], ]); self::invokePrivate($this->manager, 'verifyPassword', [null]); } - public function testVerifyPasswordNotEnforcedGroup() { + public function testVerifyPasswordNotEnforcedGroup(): void { $this->config->method('getAppValue')->willReturnMap([ ['core', 'shareapi_enforce_links_password_excluded_groups', '', '["admin"]'], ['core', 'shareapi_enforce_links_password', 'no', 'yes'], @@ -527,7 +746,7 @@ class ManagerTest extends \Test\TestCase { $this->assertNull($result); } - public function testVerifyPasswordNotEnforcedMultipleGroups() { + public function testVerifyPasswordNotEnforcedMultipleGroups(): void { $this->config->method('getAppValue')->willReturnMap([ ['core', 'shareapi_enforce_links_password_excluded_groups', '', '["admin", "special"]'], ['core', 'shareapi_enforce_links_password', 'no', 'yes'], @@ -542,7 +761,7 @@ class ManagerTest extends \Test\TestCase { $this->assertNull($result); } - public function testVerifyPasswordNull() { + public function testVerifyPasswordNull(): void { $this->config->method('getAppValue')->willReturnMap([ ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ['core', 'shareapi_enforce_links_password', 'no', 'no'], @@ -552,26 +771,26 @@ class ManagerTest extends \Test\TestCase { $this->assertNull($result); } - public function testVerifyPasswordHook() { + public function testVerifyPasswordHook(): void { $this->config->method('getAppValue')->willReturnMap([ ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''], ['core', 'shareapi_enforce_links_password', 'no', 'no'], ]); - $this->eventDispatcher->expects($this->once())->method('dispatch') - ->willReturnCallback(function (Event $event) { + $this->dispatcher->expects($this->once())->method('dispatchTyped') + ->willReturnCallback(function (Event $event): void { $this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event); /** @var ValidatePasswordPolicyEvent $event */ $this->assertSame('password', $event->getPassword()); } - ); + ); $result = self::invokePrivate($this->manager, 'verifyPassword', ['password']); $this->assertNull($result); } - public function testVerifyPasswordHookFails() { + public function testVerifyPasswordHookFails(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('password not accepted'); @@ -580,28 +799,32 @@ class ManagerTest extends \Test\TestCase { ['core', 'shareapi_enforce_links_password', 'no', 'no'], ]); - $this->eventDispatcher->expects($this->once())->method('dispatch') - ->willReturnCallback(function (Event $event) { + $this->dispatcher->expects($this->once())->method('dispatchTyped') + ->willReturnCallback(function (Event $event): void { $this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event); /** @var ValidatePasswordPolicyEvent $event */ $this->assertSame('password', $event->getPassword()); - throw new HintException('message', 'password not accepted'); + throw new HintException('password not accepted'); } - ); + ); self::invokePrivate($this->manager, 'verifyPassword', ['password']); } - public function createShare($id, $type, $path, $sharedWith, $sharedBy, $shareOwner, - $permissions, $expireDate = null, $password = null) { + public function createShare($id, $type, $node, $sharedWith, $sharedBy, $shareOwner, + $permissions, $expireDate = null, $password = null, $attributes = null) { $share = $this->createMock(IShare::class); $share->method('getShareType')->willReturn($type); $share->method('getSharedWith')->willReturn($sharedWith); $share->method('getSharedBy')->willReturn($sharedBy); $share->method('getShareOwner')->willReturn($shareOwner); - $share->method('getNode')->willReturn($path); + $share->method('getNode')->willReturn($node); + if ($node && $node->getId()) { + $share->method('getNodeId')->willReturn($node->getId()); + } $share->method('getPermissions')->willReturn($permissions); + $share->method('getAttributes')->willReturn($attributes); $share->method('getExpirationDate')->willReturn($expireDate); $share->method('getPassword')->willReturn($password); @@ -618,43 +841,46 @@ class ManagerTest extends \Test\TestCase { $file = $this->createMock(File::class); $node = $this->createMock(Node::class); - $storage = $this->createMock(Storage\IStorage::class); + $storage = $this->createMock(IStorage::class); $storage->method('instanceOfStorage') ->with('\OCA\Files_Sharing\External\Storage') ->willReturn(false); $file->method('getStorage') ->willReturn($storage); + $file->method('getId')->willReturn(108); $node->method('getStorage') ->willReturn($storage); + $node->method('getId')->willReturn(108); $data = [ - [$this->createShare(null, IShare::TYPE_USER, $file, null, $user0, $user0, 31, null, null), 'SharedWith is not a valid user', true], - [$this->createShare(null, IShare::TYPE_USER, $file, $group0, $user0, $user0, 31, null, null), 'SharedWith is not a valid user', true], - [$this->createShare(null, IShare::TYPE_USER, $file, 'foo@bar.com', $user0, $user0, 31, null, null), 'SharedWith is not a valid user', true], - [$this->createShare(null, IShare::TYPE_GROUP, $file, null, $user0, $user0, 31, null, null), 'SharedWith is not a valid group', true], - [$this->createShare(null, IShare::TYPE_GROUP, $file, $user2, $user0, $user0, 31, null, null), 'SharedWith is not a valid group', true], - [$this->createShare(null, IShare::TYPE_GROUP, $file, 'foo@bar.com', $user0, $user0, 31, null, null), 'SharedWith is not a valid group', true], - [$this->createShare(null, IShare::TYPE_LINK, $file, $user2, $user0, $user0, 31, null, null), 'SharedWith should be empty', true], - [$this->createShare(null, IShare::TYPE_LINK, $file, $group0, $user0, $user0, 31, null, null), 'SharedWith should be empty', true], - [$this->createShare(null, IShare::TYPE_LINK, $file, 'foo@bar.com', $user0, $user0, 31, null, null), 'SharedWith should be empty', true], - [$this->createShare(null, -1, $file, null, $user0, $user0, 31, null, null), 'unknown share type', true], - - [$this->createShare(null, IShare::TYPE_USER, $file, $user2, null, $user0, 31, null, null), 'SharedBy should be set', true], - [$this->createShare(null, IShare::TYPE_GROUP, $file, $group0, null, $user0, 31, null, null), 'SharedBy should be set', true], - [$this->createShare(null, IShare::TYPE_LINK, $file, null, null, $user0, 31, null, null), 'SharedBy should be set', true], + [$this->createShare(null, IShare::TYPE_USER, $file, null, $user0, $user0, 31, null, null), 'Share recipient is not a valid user', true], + [$this->createShare(null, IShare::TYPE_USER, $file, $group0, $user0, $user0, 31, null, null), 'Share recipient is not a valid user', true], + [$this->createShare(null, IShare::TYPE_USER, $file, 'foo@bar.com', $user0, $user0, 31, null, null), 'Share recipient is not a valid user', true], + [$this->createShare(null, IShare::TYPE_GROUP, $file, null, $user0, $user0, 31, null, null), 'Share recipient is not a valid group', true], + [$this->createShare(null, IShare::TYPE_GROUP, $file, $user2, $user0, $user0, 31, null, null), 'Share recipient is not a valid group', true], + [$this->createShare(null, IShare::TYPE_GROUP, $file, 'foo@bar.com', $user0, $user0, 31, null, null), 'Share recipient is not a valid group', true], + [$this->createShare(null, IShare::TYPE_LINK, $file, $user2, $user0, $user0, 31, null, null), 'Share recipient should be empty', true], + [$this->createShare(null, IShare::TYPE_LINK, $file, $group0, $user0, $user0, 31, null, null), 'Share recipient should be empty', true], + [$this->createShare(null, IShare::TYPE_LINK, $file, 'foo@bar.com', $user0, $user0, 31, null, null), 'Share recipient should be empty', true], + [$this->createShare(null, -1, $file, null, $user0, $user0, 31, null, null), 'Unknown share type', true], + + [$this->createShare(null, IShare::TYPE_USER, $file, $user2, null, $user0, 31, null, null), 'Share initiator must be set', true], + [$this->createShare(null, IShare::TYPE_GROUP, $file, $group0, null, $user0, 31, null, null), 'Share initiator must be set', true], + [$this->createShare(null, IShare::TYPE_LINK, $file, null, null, $user0, 31, null, null), 'Share initiator must be set', true], [$this->createShare(null, IShare::TYPE_USER, $file, $user0, $user0, $user0, 31, null, null), 'Cannot share with yourself', true], - [$this->createShare(null, IShare::TYPE_USER, null, $user2, $user0, $user0, 31, null, null), 'Path should be set', true], - [$this->createShare(null, IShare::TYPE_GROUP, null, $group0, $user0, $user0, 31, null, null), 'Path should be set', true], - [$this->createShare(null, IShare::TYPE_LINK, null, null, $user0, $user0, 31, null, null), 'Path should be set', true], + [$this->createShare(null, IShare::TYPE_USER, null, $user2, $user0, $user0, 31, null, null), 'Shared path must be set', true], + [$this->createShare(null, IShare::TYPE_GROUP, null, $group0, $user0, $user0, 31, null, null), 'Shared path must be set', true], + [$this->createShare(null, IShare::TYPE_LINK, null, null, $user0, $user0, 31, null, null), 'Shared path must be set', true], - [$this->createShare(null, IShare::TYPE_USER, $node, $user2, $user0, $user0, 31, null, null), 'Path should be either a file or a folder', true], - [$this->createShare(null, IShare::TYPE_GROUP, $node, $group0, $user0, $user0, 31, null, null), 'Path should be either a file or a folder', true], - [$this->createShare(null, IShare::TYPE_LINK, $node, null, $user0, $user0, 31, null, null), 'Path should be either a file or a folder', true], + [$this->createShare(null, IShare::TYPE_USER, $node, $user2, $user0, $user0, 31, null, null), 'Shared path must be either a file or a folder', true], + [$this->createShare(null, IShare::TYPE_GROUP, $node, $group0, $user0, $user0, 31, null, null), 'Shared path must be either a file or a folder', true], + [$this->createShare(null, IShare::TYPE_LINK, $node, null, $user0, $user0, 31, null, null), 'Shared path must be either a file or a folder', true], ]; $nonShareAble = $this->createMock(Folder::class); + $nonShareAble->method('getId')->willReturn(108); $nonShareAble->method('isShareable')->willReturn(false); $nonShareAble->method('getPath')->willReturn('path'); $nonShareAble->method('getName')->willReturn('name'); @@ -669,7 +895,7 @@ class ManagerTest extends \Test\TestCase { $limitedPermssions = $this->createMock(File::class); $limitedPermssions->method('isShareable')->willReturn(true); - $limitedPermssions->method('getPermissions')->willReturn(\OCP\Constants::PERMISSION_READ); + $limitedPermssions->method('getPermissions')->willReturn(Constants::PERMISSION_READ); $limitedPermssions->method('getId')->willReturn(108); $limitedPermssions->method('getPath')->willReturn('path'); $limitedPermssions->method('getName')->willReturn('name'); @@ -678,44 +904,63 @@ class ManagerTest extends \Test\TestCase { $limitedPermssions->method('getStorage') ->willReturn($storage); - $data[] = [$this->createShare(null, IShare::TYPE_USER, $limitedPermssions, $user2, $user0, $user0, null, null, null), 'A share requires permissions', true]; - $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $limitedPermssions, $group0, $user0, $user0, null, null, null), 'A share requires permissions', true]; - $data[] = [$this->createShare(null, IShare::TYPE_LINK, $limitedPermssions, null, $user0, $user0, null, null, null), 'A share requires permissions', true]; + $data[] = [$this->createShare(null, IShare::TYPE_USER, $limitedPermssions, $user2, $user0, $user0, null, null, null), 'Valid permissions are required for sharing', true]; + $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $limitedPermssions, $group0, $user0, $user0, null, null, null), 'Valid permissions are required for sharing', true]; + $data[] = [$this->createShare(null, IShare::TYPE_LINK, $limitedPermssions, null, $user0, $user0, null, null, null), 'Valid permissions are required for sharing', true]; $mount = $this->createMock(MoveableMount::class); $limitedPermssions->method('getMountPoint')->willReturn($mount); - - $data[] = [$this->createShare(null, IShare::TYPE_USER, $limitedPermssions, $user2, $user0, $user0, 31, null, null), 'Cannot increase permissions of path', true]; + // increase permissions of a re-share $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $limitedPermssions, $group0, $user0, $user0, 17, null, null), 'Cannot increase permissions of path', true]; - $data[] = [$this->createShare(null, IShare::TYPE_LINK, $limitedPermssions, null, $user0, $user0, 3, null, null), 'Cannot increase permissions of path', true]; + $data[] = [$this->createShare(null, IShare::TYPE_USER, $limitedPermssions, $user2, $user0, $user0, 3, null, null), 'Cannot increase permissions of path', true]; + $nonMovableStorage = $this->createMock(IStorage::class); + $nonMovableStorage->method('instanceOfStorage') + ->with('\OCA\Files_Sharing\External\Storage') + ->willReturn(false); + $nonMovableStorage->method('getPermissions')->willReturn(Constants::PERMISSION_ALL); $nonMoveableMountPermssions = $this->createMock(Folder::class); $nonMoveableMountPermssions->method('isShareable')->willReturn(true); - $nonMoveableMountPermssions->method('getPermissions')->willReturn(\OCP\Constants::PERMISSION_READ); + $nonMoveableMountPermssions->method('getPermissions')->willReturn(Constants::PERMISSION_READ); $nonMoveableMountPermssions->method('getId')->willReturn(108); $nonMoveableMountPermssions->method('getPath')->willReturn('path'); $nonMoveableMountPermssions->method('getName')->willReturn('name'); + $nonMoveableMountPermssions->method('getInternalPath')->willReturn(''); $nonMoveableMountPermssions->method('getOwner') ->willReturn($owner); $nonMoveableMountPermssions->method('getStorage') - ->willReturn($storage); + ->willReturn($nonMovableStorage); $data[] = [$this->createShare(null, IShare::TYPE_USER, $nonMoveableMountPermssions, $user2, $user0, $user0, 11, null, null), 'Cannot increase permissions of path', false]; $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $nonMoveableMountPermssions, $group0, $user0, $user0, 11, null, null), 'Cannot increase permissions of path', false]; $rootFolder = $this->createMock(Folder::class); $rootFolder->method('isShareable')->willReturn(true); - $rootFolder->method('getPermissions')->willReturn(\OCP\Constants::PERMISSION_ALL); + $rootFolder->method('getPermissions')->willReturn(Constants::PERMISSION_ALL); $rootFolder->method('getId')->willReturn(42); $data[] = [$this->createShare(null, IShare::TYPE_USER, $rootFolder, $user2, $user0, $user0, 30, null, null), 'You cannot share your root folder', true]; $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $rootFolder, $group0, $user0, $user0, 2, null, null), 'You cannot share your root folder', true]; $data[] = [$this->createShare(null, IShare::TYPE_LINK, $rootFolder, null, $user0, $user0, 16, null, null), 'You cannot share your root folder', true]; + $allPermssionsFiles = $this->createMock(File::class); + $allPermssionsFiles->method('isShareable')->willReturn(true); + $allPermssionsFiles->method('getPermissions')->willReturn(Constants::PERMISSION_ALL); + $allPermssionsFiles->method('getId')->willReturn(187); + $allPermssionsFiles->method('getOwner') + ->willReturn($owner); + $allPermssionsFiles->method('getStorage') + ->willReturn($storage); + + // test invalid CREATE or DELETE permissions + $data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssionsFiles, $user2, $user0, $user0, Constants::PERMISSION_ALL, null, null), 'File shares cannot have create or delete permissions', true]; + $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssionsFiles, $group0, $user0, $user0, Constants::PERMISSION_READ | Constants::PERMISSION_CREATE, null, null), 'File shares cannot have create or delete permissions', true]; + $data[] = [$this->createShare(null, IShare::TYPE_LINK, $allPermssionsFiles, null, $user0, $user0, Constants::PERMISSION_READ | Constants::PERMISSION_DELETE, null, null), 'File shares cannot have create or delete permissions', true]; + $allPermssions = $this->createMock(Folder::class); $allPermssions->method('isShareable')->willReturn(true); - $allPermssions->method('getPermissions')->willReturn(\OCP\Constants::PERMISSION_ALL); + $allPermssions->method('getPermissions')->willReturn(Constants::PERMISSION_ALL); $allPermssions->method('getId')->willReturn(108); $allPermssions->method('getOwner') ->willReturn($owner); @@ -725,18 +970,24 @@ class ManagerTest extends \Test\TestCase { $data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 30, null, null), 'Shares need at least read permissions', true]; $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 2, null, null), 'Shares need at least read permissions', true]; + // test invalid permissions + $data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 32, null, null), 'Valid permissions are required for sharing', true]; + $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 63, null, null), 'Valid permissions are required for sharing', true]; + $data[] = [$this->createShare(null, IShare::TYPE_LINK, $allPermssions, null, $user0, $user0, -1, null, null), 'Valid permissions are required for sharing', true]; + + // working shares $data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 31, null, null), null, false]; $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 3, null, null), null, false]; $data[] = [$this->createShare(null, IShare::TYPE_LINK, $allPermssions, null, $user0, $user0, 17, null, null), null, false]; - $remoteStorage = $this->createMock(Storage\IStorage::class); + $remoteStorage = $this->createMock(IStorage::class); $remoteStorage->method('instanceOfStorage') ->with('\OCA\Files_Sharing\External\Storage') ->willReturn(true); $remoteFile = $this->createMock(Folder::class); $remoteFile->method('isShareable')->willReturn(true); - $remoteFile->method('getPermissions')->willReturn(\OCP\Constants::PERMISSION_READ ^ \OCP\Constants::PERMISSION_UPDATE); + $remoteFile->method('getPermissions')->willReturn(Constants::PERMISSION_READ ^ Constants::PERMISSION_UPDATE); $remoteFile->method('getId')->willReturn(108); $remoteFile->method('getOwner') ->willReturn($owner); @@ -750,13 +1001,13 @@ class ManagerTest extends \Test\TestCase { } /** - * @dataProvider dataGeneralChecks * * @param $share * @param $exceptionMessage * @param $exception */ - public function testGeneralChecks($share, $exceptionMessage, $exception) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGeneralChecks')] + public function testGeneralChecks($share, $exceptionMessage, $exception): void { $thrown = null; $this->userManager->method('userExists')->willReturnMap([ @@ -773,8 +1024,7 @@ class ManagerTest extends \Test\TestCase { ->method('getId') ->willReturn(42); // Id 108 is used in the data to refer to the node of the share. - $userFolder->expects($this->any()) - ->method('getById') + $userFolder->method('getById') ->with(108) ->willReturn([$share->getNode()]); $userFolder->expects($this->any()) @@ -786,7 +1036,7 @@ class ManagerTest extends \Test\TestCase { try { self::invokePrivate($this->manager, 'generalCreateChecks', [$share]); $thrown = false; - } catch (\OCP\Share\Exceptions\GenericShareException $e) { + } catch (GenericShareException $e) { $this->assertEquals($exceptionMessage, $e->getHint()); $thrown = true; } catch (\InvalidArgumentException $e) { @@ -798,7 +1048,7 @@ class ManagerTest extends \Test\TestCase { } - public function testGeneralCheckShareRoot() { + public function testGeneralCheckShareRoot(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('You cannot share your root folder'); @@ -823,15 +1073,13 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'generalCreateChecks', [$share]); } - public function validateExpirationDateInternalProvider() { + public static function validateExpirationDateInternalProvider() { return [[IShare::TYPE_USER], [IShare::TYPE_REMOTE], [IShare::TYPE_REMOTE_GROUP]]; } - /** - * @dataProvider validateExpirationDateInternalProvider - */ - public function testValidateExpirationDateInternalInPast($shareType) { - $this->expectException(\OCP\Share\Exceptions\GenericShareException::class); + #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')] + public function testValidateExpirationDateInternalInPast($shareType): void { + $this->expectException(GenericShareException::class); $this->expectExceptionMessage('Expiration date is in the past'); // Expire date in the past @@ -845,10 +1093,8 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]); } - /** - * @dataProvider validateExpirationDateInternalProvider - */ - public function testValidateExpirationDateInternalEnforceButNotSet($shareType) { + #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')] + public function testValidateExpirationDateInternalEnforceButNotSet($shareType): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Expiration date is enforced'); @@ -872,10 +1118,8 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]); } - /** - * @dataProvider validateExpirationDateInternalProvider - */ - public function testValidateExpirationDateInternalEnforceButNotEnabledAndNotSet($shareType) { + #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')] + public function testValidateExpirationDateInternalEnforceButNotEnabledAndNotSet($shareType): void { $share = $this->manager->newShare(); $share->setProviderId('foo')->setId('bar'); $share->setShareType($shareType); @@ -897,10 +1141,8 @@ class ManagerTest extends \Test\TestCase { $this->assertNull($share->getExpirationDate()); } - /** - * @dataProvider validateExpirationDateInternalProvider - */ - public function testValidateExpirationDateInternalEnforceButNotSetNewShare($shareType) { + #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')] + public function testValidateExpirationDateInternalEnforceButNotSetNewShare($shareType): void { $share = $this->manager->newShare(); $share->setShareType($shareType); @@ -922,7 +1164,7 @@ class ManagerTest extends \Test\TestCase { ]); } - $expected = new \DateTime(); + $expected = new \DateTime('now', $this->timezone); $expected->setTime(0, 0, 0); $expected->add(new \DateInterval('P3D')); @@ -932,10 +1174,8 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals($expected, $share->getExpirationDate()); } - /** - * @dataProvider validateExpirationDateInternalProvider - */ - public function testValidateExpirationDateInternalEnforceRelaxedDefaultButNotSetNewShare($shareType) { + #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')] + public function testValidateExpirationDateInternalEnforceRelaxedDefaultButNotSetNewShare($shareType): void { $share = $this->manager->newShare(); $share->setShareType($shareType); @@ -957,7 +1197,7 @@ class ManagerTest extends \Test\TestCase { ]); } - $expected = new \DateTime(); + $expected = new \DateTime('now', $this->timezone); $expected->setTime(0, 0, 0); $expected->add(new \DateInterval('P1D')); @@ -967,11 +1207,9 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals($expected, $share->getExpirationDate()); } - /** - * @dataProvider validateExpirationDateInternalProvider - */ - public function testValidateExpirationDateInternalEnforceTooFarIntoFuture($shareType) { - $this->expectException(\OCP\Share\Exceptions\GenericShareException::class); + #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')] + public function testValidateExpirationDateInternalEnforceTooFarIntoFuture($shareType): void { + $this->expectException(GenericShareException::class); $this->expectExceptionMessage('Cannot set expiration date more than 3 days in the future'); $future = new \DateTime(); @@ -1000,11 +1238,9 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]); } - /** - * @dataProvider validateExpirationDateInternalProvider - */ - public function testValidateExpirationDateInternalEnforceValid($shareType) { - $future = new \DateTime(); + #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')] + public function testValidateExpirationDateInternalEnforceValid($shareType): void { + $future = new \DateTime('now', $this->dateTimeZone->getTimeZone()); $future->add(new \DateInterval('P2D')); $future->setTime(1, 2, 3); @@ -1031,8 +1267,8 @@ class ManagerTest extends \Test\TestCase { ]); } - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock(); - \OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($future) { return $data['expirationDate'] == $future; })); @@ -1042,11 +1278,9 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals($expected, $share->getExpirationDate()); } - /** - * @dataProvider validateExpirationDateInternalProvider - */ - public function testValidateExpirationDateInternalNoDefault($shareType) { - $date = new \DateTime(); + #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')] + public function testValidateExpirationDateInternalNoDefault($shareType): void { + $date = new \DateTime('now', $this->dateTimeZone->getTimeZone()); $date->add(new \DateInterval('P5D')); $date->setTime(1, 2, 3); @@ -1057,8 +1291,8 @@ class ManagerTest extends \Test\TestCase { $share->setShareType($shareType); $share->setExpirationDate($date); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock(); - \OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) { return $data['expirationDate'] == $expected && $data['passwordSet'] === false; })); @@ -1068,12 +1302,10 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals($expected, $share->getExpirationDate()); } - /** - * @dataProvider validateExpirationDateInternalProvider - */ - public function testValidateExpirationDateInternalNoDateNoDefault($shareType) { - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock(); - \OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); + #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')] + public function testValidateExpirationDateInternalNoDateNoDefault($shareType): void { + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) { return $data['expirationDate'] === null && $data['passwordSet'] === true; })); @@ -1087,16 +1319,15 @@ class ManagerTest extends \Test\TestCase { $this->assertNull($share->getExpirationDate()); } - /** - * @dataProvider validateExpirationDateInternalProvider - */ - public function testValidateExpirationDateInternalNoDateDefault($shareType) { + #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')] + public function testValidateExpirationDateInternalNoDateDefault($shareType): void { $share = $this->manager->newShare(); $share->setShareType($shareType); - $expected = new \DateTime(); + $expected = new \DateTime('now', $this->timezone); + $expected->setTime(0, 0); $expected->add(new \DateInterval('P3D')); - $expected->setTime(0, 0, 0); + $expected->setTimezone(new \DateTimeZone(date_default_timezone_get())); if ($shareType === IShare::TYPE_USER) { $this->config->method('getAppValue') @@ -1114,8 +1345,8 @@ class ManagerTest extends \Test\TestCase { ]); } - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock(); - \OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) { return $data['expirationDate'] == $expected; })); @@ -1125,16 +1356,14 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals($expected, $share->getExpirationDate()); } - /** - * @dataProvider validateExpirationDateInternalProvider - */ - public function testValidateExpirationDateInternalDefault($shareType) { - $future = new \DateTime(); + #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')] + public function testValidateExpirationDateInternalDefault($shareType): void { + $future = new \DateTime('now', $this->timezone); $future->add(new \DateInterval('P5D')); $future->setTime(1, 2, 3); $expected = clone $future; - $expected->setTime(0, 0, 0); + $expected->setTime(0, 0); $share = $this->manager->newShare(); $share->setShareType($shareType); @@ -1156,8 +1385,8 @@ class ManagerTest extends \Test\TestCase { ]); } - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock(); - \OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) { return $data['expirationDate'] == $expected; })); @@ -1167,19 +1396,17 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals($expected, $share->getExpirationDate()); } - /** - * @dataProvider validateExpirationDateInternalProvider - */ - public function testValidateExpirationDateInternalHookModification($shareType) { - $nextWeek = new \DateTime(); + #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')] + public function testValidateExpirationDateInternalHookModification($shareType): void { + $nextWeek = new \DateTime('now', $this->timezone); $nextWeek->add(new \DateInterval('P7D')); $nextWeek->setTime(0, 0, 0); $save = clone $nextWeek; - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock(); - \OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); - $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data) { + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); + $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void { $data['expirationDate']->sub(new \DateInterval('P2D')); }); @@ -1193,10 +1420,8 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals($save, $share->getExpirationDate()); } - /** - * @dataProvider validateExpirationDateInternalProvider - */ - public function testValidateExpirationDateInternalHookException($shareType) { + #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')] + public function testValidateExpirationDateInternalHookException($shareType): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('Invalid date!'); @@ -1208,9 +1433,9 @@ class ManagerTest extends \Test\TestCase { $share->setShareType($shareType); $share->setExpirationDate($nextWeek); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock(); - \OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); - $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data) { + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); + $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void { $data['accepted'] = false; $data['message'] = 'Invalid date!'; }); @@ -1218,10 +1443,8 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]); } - /** - * @dataProvider validateExpirationDateInternalProvider - */ - public function testValidateExpirationDateInternalExistingShareNoDefault($shareType) { + #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')] + public function testValidateExpirationDateInternalExistingShareNoDefault($shareType): void { $share = $this->manager->newShare(); $share->setShareType($shareType); $share->setId('42')->setProviderId('foo'); @@ -1245,8 +1468,8 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals(null, $share->getExpirationDate()); } - public function testValidateExpirationDateInPast() { - $this->expectException(\OCP\Share\Exceptions\GenericShareException::class); + public function testValidateExpirationDateInPast(): void { + $this->expectException(GenericShareException::class); $this->expectExceptionMessage('Expiration date is in the past'); // Expire date in the past @@ -1259,7 +1482,7 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]); } - public function testValidateExpirationDateEnforceButNotSet() { + public function testValidateExpirationDateEnforceButNotSet(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Expiration date is enforced'); @@ -1275,7 +1498,7 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]); } - public function testValidateExpirationDateEnforceButNotEnabledAndNotSet() { + public function testValidateExpirationDateEnforceButNotEnabledAndNotSet(): void { $share = $this->manager->newShare(); $share->setProviderId('foo')->setId('bar'); @@ -1289,7 +1512,7 @@ class ManagerTest extends \Test\TestCase { $this->assertNull($share->getExpirationDate()); } - public function testValidateExpirationDateEnforceButNotSetNewShare() { + public function testValidateExpirationDateEnforceButNotSetNewShare(): void { $share = $this->manager->newShare(); $this->config->method('getAppValue') @@ -1297,10 +1520,10 @@ class ManagerTest extends \Test\TestCase { ['core', 'shareapi_enforce_expire_date', 'no', 'yes'], ['core', 'shareapi_expire_after_n_days', '7', '3'], ['core', 'shareapi_default_expire_date', 'no', 'yes'], - ['core', 'link_defaultExpDays', 3, '3'], + ['core', 'link_defaultExpDays', '3', '3'], ]); - $expected = new \DateTime(); + $expected = new \DateTime('now', $this->timezone); $expected->setTime(0, 0, 0); $expected->add(new \DateInterval('P3D')); @@ -1310,7 +1533,7 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals($expected, $share->getExpirationDate()); } - public function testValidateExpirationDateEnforceRelaxedDefaultButNotSetNewShare() { + public function testValidateExpirationDateEnforceRelaxedDefaultButNotSetNewShare(): void { $share = $this->manager->newShare(); $this->config->method('getAppValue') @@ -1318,10 +1541,10 @@ class ManagerTest extends \Test\TestCase { ['core', 'shareapi_enforce_expire_date', 'no', 'yes'], ['core', 'shareapi_expire_after_n_days', '7', '3'], ['core', 'shareapi_default_expire_date', 'no', 'yes'], - ['core', 'link_defaultExpDays', 3, '1'], + ['core', 'link_defaultExpDays', '3', '1'], ]); - $expected = new \DateTime(); + $expected = new \DateTime('now', $this->timezone); $expected->setTime(0, 0, 0); $expected->add(new \DateInterval('P1D')); @@ -1331,8 +1554,8 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals($expected, $share->getExpirationDate()); } - public function testValidateExpirationDateEnforceTooFarIntoFuture() { - $this->expectException(\OCP\Share\Exceptions\GenericShareException::class); + public function testValidateExpirationDateEnforceTooFarIntoFuture(): void { + $this->expectException(GenericShareException::class); $this->expectExceptionMessage('Cannot set expiration date more than 3 days in the future'); $future = new \DateTime(); @@ -1351,8 +1574,8 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]); } - public function testValidateExpirationDateEnforceValid() { - $future = new \DateTime(); + public function testValidateExpirationDateEnforceValid(): void { + $future = new \DateTime('now', $this->timezone); $future->add(new \DateInterval('P2D')); $future->setTime(1, 2, 3); @@ -1369,8 +1592,8 @@ class ManagerTest extends \Test\TestCase { ['core', 'shareapi_default_expire_date', 'no', 'yes'], ]); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock(); - \OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($future) { return $data['expirationDate'] == $future; })); @@ -1380,19 +1603,20 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals($expected, $share->getExpirationDate()); } - public function testValidateExpirationDateNoDefault() { - $date = new \DateTime(); + public function testValidateExpirationDateNoDefault(): void { + $date = new \DateTime('now', $this->timezone); $date->add(new \DateInterval('P5D')); $date->setTime(1, 2, 3); $expected = clone $date; - $expected->setTime(0, 0, 0); + $expected->setTime(0, 0); + $expected->setTimezone(new \DateTimeZone(date_default_timezone_get())); $share = $this->manager->newShare(); $share->setExpirationDate($date); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock(); - \OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) { return $data['expirationDate'] == $expected && $data['passwordSet'] === false; })); @@ -1402,9 +1626,9 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals($expected, $share->getExpirationDate()); } - public function testValidateExpirationDateNoDateNoDefault() { - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock(); - \OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); + public function testValidateExpirationDateNoDateNoDefault(): void { + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) { return $data['expirationDate'] === null && $data['passwordSet'] === true; })); @@ -1417,22 +1641,23 @@ class ManagerTest extends \Test\TestCase { $this->assertNull($share->getExpirationDate()); } - public function testValidateExpirationDateNoDateDefault() { + public function testValidateExpirationDateNoDateDefault(): void { $share = $this->manager->newShare(); - $expected = new \DateTime(); + $expected = new \DateTime('now', $this->timezone); $expected->add(new \DateInterval('P3D')); - $expected->setTime(0, 0, 0); + $expected->setTime(0, 0); + $expected->setTimezone(new \DateTimeZone(date_default_timezone_get())); $this->config->method('getAppValue') ->willReturnMap([ ['core', 'shareapi_default_expire_date', 'no', 'yes'], ['core', 'shareapi_expire_after_n_days', '7', '3'], - ['core', 'link_defaultExpDays', 3, '3'], + ['core', 'link_defaultExpDays', '3', '3'], ]); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock(); - \OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) { return $data['expirationDate'] == $expected; })); @@ -1442,13 +1667,14 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals($expected, $share->getExpirationDate()); } - public function testValidateExpirationDateDefault() { - $future = new \DateTime(); + public function testValidateExpirationDateDefault(): void { + $future = new \DateTime('now', $this->timezone); $future->add(new \DateInterval('P5D')); $future->setTime(1, 2, 3); $expected = clone $future; - $expected->setTime(0, 0, 0); + $expected->setTime(0, 0); + $expected->setTimezone(new \DateTimeZone(date_default_timezone_get())); $share = $this->manager->newShare(); $share->setExpirationDate($future); @@ -1457,11 +1683,11 @@ class ManagerTest extends \Test\TestCase { ->willReturnMap([ ['core', 'shareapi_default_expire_date', 'no', 'yes'], ['core', 'shareapi_expire_after_n_days', '7', '3'], - ['core', 'link_defaultExpDays', 3, '1'], + ['core', 'link_defaultExpDays', '3', '1'], ]); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock(); - \OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) { return $data['expirationDate'] == $expected; })); @@ -1471,16 +1697,49 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals($expected, $share->getExpirationDate()); } - public function testValidateExpirationDateHookModification() { - $nextWeek = new \DateTime(); + public function testValidateExpirationNegativeOffsetTimezone(): void { + $this->timezone = new \DateTimeZone('Pacific/Tahiti'); + $future = new \DateTime(); + $future->add(new \DateInterval('P5D')); + + $expected = clone $future; + $expected->setTimezone($this->timezone); + $expected->setTime(0, 0); + $expected->setTimezone(new \DateTimeZone(date_default_timezone_get())); + + $share = $this->manager->newShare(); + $share->setExpirationDate($future); + + $this->config->method('getAppValue') + ->willReturnMap([ + ['core', 'shareapi_default_expire_date', 'no', 'yes'], + ['core', 'shareapi_expire_after_n_days', '7', '3'], + ['core', 'link_defaultExpDays', '3', '1'], + ]); + + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); + $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) { + return $data['expirationDate'] == $expected; + })); + + self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]); + + $this->assertEquals($expected, $share->getExpirationDate()); + } + + public function testValidateExpirationDateHookModification(): void { + $nextWeek = new \DateTime('now', $this->timezone); $nextWeek->add(new \DateInterval('P7D')); - $nextWeek->setTime(0, 0, 0); $save = clone $nextWeek; + $save->setTime(0, 0); + $save->sub(new \DateInterval('P2D')); + $save->setTimezone(new \DateTimeZone(date_default_timezone_get())); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock(); - \OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); - $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data) { + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); + $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void { $data['expirationDate']->sub(new \DateInterval('P2D')); }); @@ -1489,11 +1748,10 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]); - $save->sub(new \DateInterval('P2D')); $this->assertEquals($save, $share->getExpirationDate()); } - public function testValidateExpirationDateHookException() { + public function testValidateExpirationDateHookException(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('Invalid date!'); @@ -1504,9 +1762,9 @@ class ManagerTest extends \Test\TestCase { $share = $this->manager->newShare(); $share->setExpirationDate($nextWeek); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['listener'])->getMock(); - \OCP\Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); - $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data) { + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener'); + $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void { $data['accepted'] = false; $data['message'] = 'Invalid date!'; }); @@ -1514,7 +1772,7 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]); } - public function testValidateExpirationDateExistingShareNoDefault() { + public function testValidateExpirationDateExistingShareNoDefault(): void { $share = $this->manager->newShare(); $share->setId('42')->setProviderId('foo'); @@ -1530,7 +1788,7 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals(null, $share->getExpirationDate()); } - public function testUserCreateChecksShareWithGroupMembersOnlyDifferentGroups() { + public function testUserCreateChecksShareWithGroupMembersOnlyDifferentGroups(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('Sharing is only allowed with group members'); @@ -1558,12 +1816,13 @@ class ManagerTest extends \Test\TestCase { ->method('getAppValue') ->willReturnMap([ ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'], + ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'], ]); self::invokePrivate($this->manager, 'userCreateChecks', [$share]); } - public function testUserCreateChecksShareWithGroupMembersOnlySharedGroup() { + public function testUserCreateChecksShareWithGroupMembersOnlySharedGroup(): void { $share = $this->manager->newShare(); $sharedBy = $this->createMock(IUser::class); @@ -1591,6 +1850,7 @@ class ManagerTest extends \Test\TestCase { ->method('getAppValue') ->willReturnMap([ ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'], + ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'], ]); $this->defaultProvider @@ -1603,9 +1863,9 @@ class ManagerTest extends \Test\TestCase { } - public function testUserCreateChecksIdenticalShareExists() { + public function testUserCreateChecksIdenticalShareExists(): void { $this->expectException(AlreadySharedException::class); - $this->expectExceptionMessage('Sharing name.txt failed, because this item is already shared with user user'); + $this->expectExceptionMessage('Sharing name.txt failed, because this item is already shared with the account user'); $share = $this->manager->newShare(); $share->setSharedWithDisplayName('user'); @@ -1632,9 +1892,9 @@ class ManagerTest extends \Test\TestCase { } - public function testUserCreateChecksIdenticalPathSharedViaGroup() { + public function testUserCreateChecksIdenticalPathSharedViaGroup(): void { $this->expectException(AlreadySharedException::class); - $this->expectExceptionMessage('Sharing name2.txt failed, because this item is already shared with user userName'); + $this->expectExceptionMessage('Sharing name2.txt failed, because this item is already shared with the account userName'); $share = $this->manager->newShare(); @@ -1677,7 +1937,7 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'userCreateChecks', [$share]); } - public function testUserCreateChecksIdenticalPathSharedViaDeletedGroup() { + public function testUserCreateChecksIdenticalPathSharedViaDeletedGroup(): void { $share = $this->manager->newShare(); $sharedWith = $this->createMock(IUser::class); @@ -1710,7 +1970,7 @@ class ManagerTest extends \Test\TestCase { $this->assertNull($this->invokePrivate($this->manager, 'userCreateChecks', [$share])); } - public function testUserCreateChecksIdenticalPathNotSharedWithUser() { + public function testUserCreateChecksIdenticalPathNotSharedWithUser(): void { $share = $this->manager->newShare(); $sharedWith = $this->createMock(IUser::class); $path = $this->createMock(Node::class); @@ -1747,7 +2007,7 @@ class ManagerTest extends \Test\TestCase { } - public function testGroupCreateChecksShareWithGroupMembersGroupSharingNotAllowed() { + public function testGroupCreateChecksShareWithGroupMembersGroupSharingNotAllowed(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('Group sharing is now allowed'); @@ -1763,7 +2023,7 @@ class ManagerTest extends \Test\TestCase { } - public function testGroupCreateChecksShareWithGroupMembersOnlyNotInGroup() { + public function testGroupCreateChecksShareWithGroupMembersOnlyNotInGroup(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('Sharing is only allowed within your own groups'); @@ -1783,13 +2043,14 @@ class ManagerTest extends \Test\TestCase { ->willReturnMap([ ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'], ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'], + ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'], ]); self::invokePrivate($this->manager, 'groupCreateChecks', [$share]); } - public function testGroupCreateChecksShareWithGroupMembersOnlyNullGroup() { + public function testGroupCreateChecksShareWithGroupMembersOnlyNullGroup(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('Sharing is only allowed within your own groups'); @@ -1806,12 +2067,13 @@ class ManagerTest extends \Test\TestCase { ->willReturnMap([ ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'], ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'], + ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'], ]); $this->assertNull($this->invokePrivate($this->manager, 'groupCreateChecks', [$share])); } - public function testGroupCreateChecksShareWithGroupMembersOnlyInGroup() { + public function testGroupCreateChecksShareWithGroupMembersOnlyInGroup(): void { $share = $this->manager->newShare(); $user = $this->createMock(IUser::class); @@ -1835,6 +2097,7 @@ class ManagerTest extends \Test\TestCase { ->willReturnMap([ ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'], ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'], + ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'], ]); self::invokePrivate($this->manager, 'groupCreateChecks', [$share]); @@ -1842,7 +2105,7 @@ class ManagerTest extends \Test\TestCase { } - public function testGroupCreateChecksPathAlreadySharedWithSameGroup() { + public function testGroupCreateChecksPathAlreadySharedWithSameGroup(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('Path is already shared with this group'); @@ -1872,7 +2135,7 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'groupCreateChecks', [$share]); } - public function testGroupCreateChecksPathAlreadySharedWithDifferentGroup() { + public function testGroupCreateChecksPathAlreadySharedWithDifferentGroup(): void { $share = $this->manager->newShare(); $share->setSharedWith('sharedWith'); @@ -1898,7 +2161,7 @@ class ManagerTest extends \Test\TestCase { } - public function testLinkCreateChecksNoLinkSharesAllowed() { + public function testLinkCreateChecksNoLinkSharesAllowed(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('Link sharing is not allowed'); @@ -1914,13 +2177,31 @@ class ManagerTest extends \Test\TestCase { } - public function testLinkCreateChecksNoPublicUpload() { + public function testFileLinkCreateChecksNoPublicUpload(): void { + $share = $this->manager->newShare(); + + $share->setPermissions(Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE); + $share->setNodeType('file'); + + $this->config + ->method('getAppValue') + ->willReturnMap([ + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['core', 'shareapi_allow_public_upload', 'yes', 'no'] + ]); + + self::invokePrivate($this->manager, 'linkCreateChecks', [$share]); + $this->addToAssertionCount(1); + } + + public function testFolderLinkCreateChecksNoPublicUpload(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('Public upload is not allowed'); $share = $this->manager->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE); + $share->setPermissions(Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE); + $share->setNodeType('folder'); $this->config ->method('getAppValue') @@ -1932,10 +2213,13 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'linkCreateChecks', [$share]); } - public function testLinkCreateChecksPublicUpload() { + public function testLinkCreateChecksPublicUpload(): void { $share = $this->manager->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE); + $share->setPermissions(Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE); + $share->setSharedWith('sharedWith'); + $folder = $this->createMock(\OC\Files\Node\Folder::class); + $share->setNode($folder); $this->config ->method('getAppValue') @@ -1948,10 +2232,13 @@ class ManagerTest extends \Test\TestCase { $this->addToAssertionCount(1); } - public function testLinkCreateChecksReadOnly() { + public function testLinkCreateChecksReadOnly(): void { $share = $this->manager->newShare(); - $share->setPermissions(\OCP\Constants::PERMISSION_READ); + $share->setPermissions(Constants::PERMISSION_READ); + $share->setSharedWith('sharedWith'); + $folder = $this->createMock(\OC\Files\Node\Folder::class); + $share->setNode($folder); $this->config ->method('getAppValue') @@ -1965,15 +2252,15 @@ class ManagerTest extends \Test\TestCase { } - public function testPathCreateChecksContainsSharedMount() { + public function testPathCreateChecksContainsSharedMount(): void { $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('Path contains files shared with you'); + $this->expectExceptionMessage('You cannot share a folder that contains other shares'); $path = $this->createMock(Folder::class); $path->method('getPath')->willReturn('path'); $mount = $this->createMock(IMountPoint::class); - $storage = $this->createMock(Storage::class); + $storage = $this->createMock(IStorage::class); $mount->method('getStorage')->willReturn($storage); $storage->method('instanceOfStorage')->with('\OCA\Files_Sharing\ISharedStorage')->willReturn(true); @@ -1982,12 +2269,12 @@ class ManagerTest extends \Test\TestCase { self::invokePrivate($this->manager, 'pathCreateChecks', [$path]); } - public function testPathCreateChecksContainsNoSharedMount() { + public function testPathCreateChecksContainsNoSharedMount(): void { $path = $this->createMock(Folder::class); $path->method('getPath')->willReturn('path'); $mount = $this->createMock(IMountPoint::class); - $storage = $this->createMock(Storage::class); + $storage = $this->createMock(IStorage::class); $mount->method('getStorage')->willReturn($storage); $storage->method('instanceOfStorage')->with('\OCA\Files_Sharing\ISharedStorage')->willReturn(false); @@ -1997,45 +2284,51 @@ class ManagerTest extends \Test\TestCase { $this->addToAssertionCount(1); } - public function testPathCreateChecksContainsNoFolder() { + public function testPathCreateChecksContainsNoFolder(): void { $path = $this->createMock(File::class); self::invokePrivate($this->manager, 'pathCreateChecks', [$path]); $this->addToAssertionCount(1); } - public function dataIsSharingDisabledForUser() { + public static function dataIsSharingDisabledForUser() { $data = []; // No exclude groups $data[] = ['no', null, null, [], false]; - // empty exclude list, user no groups + // empty exclude / allow list, user no groups $data[] = ['yes', '', json_encode(['']), [], false]; + $data[] = ['allow', '', json_encode(['']), [], true]; - // empty exclude list, user groups + // empty exclude / allow list, user groups $data[] = ['yes', '', json_encode(['']), ['group1', 'group2'], false]; + $data[] = ['allow', '', json_encode(['']), ['group1', 'group2'], true]; // Convert old list to json $data[] = ['yes', 'group1,group2', json_encode(['group1', 'group2']), [], false]; + $data[] = ['allow', 'group1,group2', json_encode(['group1', 'group2']), [], true]; // Old list partly groups in common $data[] = ['yes', 'group1,group2', json_encode(['group1', 'group2']), ['group1', 'group3'], false]; + $data[] = ['allow', 'group1,group2', json_encode(['group1', 'group2']), ['group1', 'group3'], false]; // Old list only groups in common $data[] = ['yes', 'group1,group2', json_encode(['group1', 'group2']), ['group1'], true]; + $data[] = ['allow', 'group1,group2', json_encode(['group1', 'group2']), ['group1'], false]; // New list partly in common $data[] = ['yes', json_encode(['group1', 'group2']), null, ['group1', 'group3'], false]; + $data[] = ['allow', json_encode(['group1', 'group2']), null, ['group1', 'group3'], false]; // New list only groups in common $data[] = ['yes', json_encode(['group1', 'group2']), null, ['group2'], true]; + $data[] = ['allow', json_encode(['group1', 'group2']), null, ['group2'], false]; return $data; } /** - * @dataProvider dataIsSharingDisabledForUser * * @param string $excludeGroups * @param string $groupList @@ -2043,7 +2336,8 @@ class ManagerTest extends \Test\TestCase { * @param string[] $groupIds * @param bool $expected */ - public function testIsSharingDisabledForUser($excludeGroups, $groupList, $setList, $groupIds, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataIsSharingDisabledForUser')] + public function testIsSharingDisabledForUser($excludeGroups, $groupList, $setList, $groupIds, $expected): void { $user = $this->createMock(IUser::class); $this->config->method('getAppValue') @@ -2071,7 +2365,7 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals($expected, $res); } - public function dataCanShare() { + public static function dataCanShare() { $data = []; /* @@ -2087,20 +2381,20 @@ class ManagerTest extends \Test\TestCase { } /** - * @dataProvider dataCanShare * * @param bool $expected * @param string $sharingEnabled * @param bool $disabledForUser */ - public function testCanShare($expected, $sharingEnabled, $disabledForUser) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataCanShare')] + public function testCanShare($expected, $sharingEnabled, $disabledForUser): void { $this->config->method('getAppValue') ->willReturnMap([ ['core', 'shareapi_enabled', 'yes', $sharingEnabled], ]); $manager = $this->createManagerMock() - ->setMethods(['sharingDisabledForUser']) + ->onlyMethods(['sharingDisabledForUser']) ->getMock(); $manager->method('sharingDisabledForUser') @@ -2120,15 +2414,16 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals($expected, !$exception); } - public function testCreateShareUser() { + public function testCreateShareUser(): void { + /** @var Manager&MockObject $manager */ $manager = $this->createManagerMock() - ->setMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks']) + ->onlyMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks']) ->getMock(); $shareOwner = $this->createMock(IUser::class); $shareOwner->method('getUID')->willReturn('shareOwner'); - $storage = $this->createMock(Storage::class); + $storage = $this->createMock(IStorage::class); $path = $this->createMock(File::class); $path->method('getOwner')->willReturn($shareOwner); $path->method('getName')->willReturn('target'); @@ -2141,7 +2436,7 @@ class ManagerTest extends \Test\TestCase { 'sharedWith', 'sharedBy', null, - \OCP\Constants::PERMISSION_ALL); + Constants::PERMISSION_ALL); $manager->expects($this->once()) ->method('canShare') @@ -2175,15 +2470,15 @@ class ManagerTest extends \Test\TestCase { $manager->createShare($share); } - public function testCreateShareGroup() { + public function testCreateShareGroup(): void { $manager = $this->createManagerMock() - ->setMethods(['canShare', 'generalCreateChecks', 'groupCreateChecks', 'pathCreateChecks']) + ->onlyMethods(['canShare', 'generalCreateChecks', 'groupCreateChecks', 'pathCreateChecks']) ->getMock(); $shareOwner = $this->createMock(IUser::class); $shareOwner->method('getUID')->willReturn('shareOwner'); - $storage = $this->createMock(Storage::class); + $storage = $this->createMock(IStorage::class); $path = $this->createMock(File::class); $path->method('getOwner')->willReturn($shareOwner); $path->method('getName')->willReturn('target'); @@ -2196,7 +2491,7 @@ class ManagerTest extends \Test\TestCase { 'sharedWith', 'sharedBy', null, - \OCP\Constants::PERMISSION_ALL); + Constants::PERMISSION_ALL); $manager->expects($this->once()) ->method('canShare') @@ -2230,9 +2525,9 @@ class ManagerTest extends \Test\TestCase { $manager->createShare($share); } - public function testCreateShareLink() { + public function testCreateShareLink(): void { $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'generalCreateChecks', 'linkCreateChecks', @@ -2246,7 +2541,7 @@ class ManagerTest extends \Test\TestCase { $shareOwner = $this->createMock(IUser::class); $shareOwner->method('getUID')->willReturn('shareOwner'); - $storage = $this->createMock(Storage::class); + $storage = $this->createMock(IStorage::class); $path = $this->createMock(File::class); $path->method('getOwner')->willReturn($shareOwner); $path->method('getName')->willReturn('target'); @@ -2259,7 +2554,7 @@ class ManagerTest extends \Test\TestCase { $share->setShareType(IShare::TYPE_LINK) ->setNode($path) ->setSharedBy('sharedBy') - ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setPermissions(Constants::PERMISSION_ALL) ->setExpirationDate($date) ->setPassword('password'); @@ -2305,45 +2600,30 @@ class ManagerTest extends \Test\TestCase { return $share->setId(42); }); - // Pre share - $this->eventDispatcher->expects($this->at(0)) - ->method('dispatch') - ->with( - $this->equalTo('OCP\Share::preShare'), - $this->callback(function (GenericEvent $e) use ($path, $date) { - /** @var IShare $share */ - $share = $e->getSubject(); - - return $share->getShareType() === IShare::TYPE_LINK && - $share->getNode() === $path && - $share->getSharedBy() === 'sharedBy' && - $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && - $share->getExpirationDate() === $date && - $share->getPassword() === 'hashed' && - $share->getToken() === 'token'; - }) - ); - - // Post share - $this->eventDispatcher->expects($this->at(1)) - ->method('dispatch') - ->with( - $this->equalTo('OCP\Share::postShare'), - $this->callback(function (GenericEvent $e) use ($path, $date) { - /** @var IShare $share */ - $share = $e->getSubject(); - - return $share->getShareType() === IShare::TYPE_LINK && - $share->getNode() === $path && - $share->getSharedBy() === 'sharedBy' && - $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && - $share->getExpirationDate() === $date && - $share->getPassword() === 'hashed' && - $share->getToken() === 'token' && - $share->getId() === '42' && - $share->getTarget() === '/target'; - }) - ); + $calls = [ + BeforeShareCreatedEvent::class, + ShareCreatedEvent::class, + ]; + $this->dispatcher->expects($this->exactly(2)) + ->method('dispatchTyped') + ->willReturnCallback(function ($event) use (&$calls, $date, $path): void { + $expected = array_shift($calls); + $this->assertInstanceOf($expected, $event); + $share = $event->getShare(); + + $this->assertEquals(IShare::TYPE_LINK, $share->getShareType(), 'getShareType'); + $this->assertEquals($path, $share->getNode(), 'getNode'); + $this->assertEquals('sharedBy', $share->getSharedBy(), 'getSharedBy'); + $this->assertEquals(Constants::PERMISSION_ALL, $share->getPermissions(), 'getPermissions'); + $this->assertEquals($date, $share->getExpirationDate(), 'getExpirationDate'); + $this->assertEquals('hashed', $share->getPassword(), 'getPassword'); + $this->assertEquals('token', $share->getToken(), 'getToken'); + + if ($expected === ShareCreatedEvent::class) { + $this->assertEquals('42', $share->getId(), 'getId'); + $this->assertEquals('/target', $share->getTarget(), 'getTarget'); + } + }); /** @var IShare $share */ $share = $manager->createShare($share); @@ -2355,9 +2635,9 @@ class ManagerTest extends \Test\TestCase { $this->assertEquals('hashed', $share->getPassword()); } - public function testCreateShareMail() { + public function testCreateShareMail(): void { $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'generalCreateChecks', 'linkCreateChecks', @@ -2371,7 +2651,7 @@ class ManagerTest extends \Test\TestCase { $shareOwner = $this->createMock(IUser::class); $shareOwner->method('getUID')->willReturn('shareOwner'); - $storage = $this->createMock(Storage::class); + $storage = $this->createMock(IStorage::class); $path = $this->createMock(File::class); $path->method('getOwner')->willReturn($shareOwner); $path->method('getName')->willReturn('target'); @@ -2382,7 +2662,7 @@ class ManagerTest extends \Test\TestCase { $share->setShareType(IShare::TYPE_EMAIL) ->setNode($path) ->setSharedBy('sharedBy') - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $manager->expects($this->once()) ->method('canShare') @@ -2417,45 +2697,30 @@ class ManagerTest extends \Test\TestCase { return $share->setId(42); }); - // Pre share - $this->eventDispatcher->expects($this->at(0)) - ->method('dispatch') - ->with( - $this->equalTo('OCP\Share::preShare'), - $this->callback(function (GenericEvent $e) use ($path) { - /** @var IShare $share */ - $share = $e->getSubject(); - - return $share->getShareType() === IShare::TYPE_EMAIL && - $share->getNode() === $path && - $share->getSharedBy() === 'sharedBy' && - $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && - $share->getExpirationDate() === null && - $share->getPassword() === null && - $share->getToken() === 'token'; - }) - ); - - // Post share - $this->eventDispatcher->expects($this->at(1)) - ->method('dispatch') - ->with( - $this->equalTo('OCP\Share::postShare'), - $this->callback(function (GenericEvent $e) use ($path) { - /** @var IShare $share */ - $share = $e->getSubject(); - - return $share->getShareType() === IShare::TYPE_EMAIL && - $share->getNode() === $path && - $share->getSharedBy() === 'sharedBy' && - $share->getPermissions() === \OCP\Constants::PERMISSION_ALL && - $share->getExpirationDate() === null && - $share->getPassword() === null && - $share->getToken() === 'token' && - $share->getId() === '42' && - $share->getTarget() === '/target'; - }) - ); + $calls = [ + BeforeShareCreatedEvent::class, + ShareCreatedEvent::class, + ]; + $this->dispatcher->expects($this->exactly(2)) + ->method('dispatchTyped') + ->willReturnCallback(function ($event) use (&$calls, $path): void { + $expected = array_shift($calls); + $this->assertInstanceOf($expected, $event); + $share = $event->getShare(); + + $this->assertEquals(IShare::TYPE_EMAIL, $share->getShareType(), 'getShareType'); + $this->assertEquals($path, $share->getNode(), 'getNode'); + $this->assertEquals('sharedBy', $share->getSharedBy(), 'getSharedBy'); + $this->assertEquals(Constants::PERMISSION_ALL, $share->getPermissions(), 'getPermissions'); + $this->assertNull($share->getExpirationDate(), 'getExpirationDate'); + $this->assertNull($share->getPassword(), 'getPassword'); + $this->assertEquals('token', $share->getToken(), 'getToken'); + + if ($expected === ShareCreatedEvent::class) { + $this->assertEquals('42', $share->getId(), 'getId'); + $this->assertEquals('/target', $share->getTarget(), 'getTarget'); + } + }); /** @var IShare $share */ $share = $manager->createShare($share); @@ -2466,12 +2731,12 @@ class ManagerTest extends \Test\TestCase { } - public function testCreateShareHookError() { + public function testCreateShareHookError(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('I won\'t let you share'); $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'generalCreateChecks', 'userCreateChecks', @@ -2482,7 +2747,7 @@ class ManagerTest extends \Test\TestCase { $shareOwner = $this->createMock(IUser::class); $shareOwner->method('getUID')->willReturn('shareOwner'); - $storage = $this->createMock(Storage::class); + $storage = $this->createMock(IStorage::class); $path = $this->createMock(File::class); $path->method('getOwner')->willReturn($shareOwner); $path->method('getName')->willReturn('target'); @@ -2495,7 +2760,7 @@ class ManagerTest extends \Test\TestCase { 'sharedWith', 'sharedBy', null, - \OCP\Constants::PERMISSION_ALL); + Constants::PERMISSION_ALL); $manager->expects($this->once()) ->method('canShare') @@ -2521,13 +2786,12 @@ class ManagerTest extends \Test\TestCase { ->with('/target'); // Pre share - $this->eventDispatcher->expects($this->once()) - ->method('dispatch') + $this->dispatcher->expects($this->once()) + ->method('dispatchTyped') ->with( - $this->equalTo('OCP\Share::preShare'), - $this->isInstanceOf(GenericEvent::class) - )->willReturnCallback(function ($name, GenericEvent $e) { - $e->setArgument('error', 'I won\'t let you share!'); + $this->isInstanceOf(BeforeShareCreatedEvent::class) + )->willReturnCallback(function (BeforeShareCreatedEvent $e): void { + $e->setError('I won\'t let you share!'); $e->stopPropagation(); } ); @@ -2535,20 +2799,20 @@ class ManagerTest extends \Test\TestCase { $manager->createShare($share); } - public function testCreateShareOfIncomingFederatedShare() { + public function testCreateShareOfIncomingFederatedShare(): void { $manager = $this->createManagerMock() - ->setMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks']) + ->onlyMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks']) ->getMock(); $shareOwner = $this->createMock(IUser::class); $shareOwner->method('getUID')->willReturn('shareOwner'); - $storage = $this->createMock(Storage::class); + $storage = $this->createMock(IStorage::class); $storage->method('instanceOfStorage') ->with('OCA\Files_Sharing\External\Storage') ->willReturn(true); - $storage2 = $this->createMock(Storage::class); + $storage2 = $this->createMock(IStorage::class); $storage2->method('instanceOfStorage') ->with('OCA\Files_Sharing\External\Storage') ->willReturn(false); @@ -2575,7 +2839,7 @@ class ManagerTest extends \Test\TestCase { 'sharedWith', 'sharedBy', null, - \OCP\Constants::PERMISSION_ALL); + Constants::PERMISSION_ALL); $manager->expects($this->once()) ->method('canShare') @@ -2609,7 +2873,7 @@ class ManagerTest extends \Test\TestCase { $manager->createShare($share); } - public function testGetSharesBy() { + public function testGetSharesBy(): void { $share = $this->manager->newShare(); $node = $this->createMock(Folder::class); @@ -2631,6 +2895,31 @@ class ManagerTest extends \Test\TestCase { $this->assertSame($share, $shares[0]); } + public function testGetSharesByOwnerless(): void { + $mount = $this->createMock(IShareOwnerlessMount::class); + + $node = $this->createMock(Folder::class); + $node + ->expects($this->once()) + ->method('getMountPoint') + ->willReturn($mount); + + $share = $this->manager->newShare(); + $share->setNode($node); + $share->setShareType(IShare::TYPE_USER); + + $this->defaultProvider + ->expects($this->once()) + ->method('getSharesByPath') + ->with($this->equalTo($node)) + ->willReturn([$share]); + + $shares = $this->manager->getSharesBy('user', IShare::TYPE_USER, $node, true, 1, 1); + + $this->assertCount(1, $shares); + $this->assertSame($share, $shares[0]); + } + /** * Test to ensure we correctly remove expired link shares * @@ -2639,12 +2928,12 @@ class ManagerTest extends \Test\TestCase { * have received share 1,2 and 7. And from the manager. Share 3-6 should be * deleted (as they are evaluated). but share 8 should still be there. */ - public function testGetSharesByExpiredLinkShares() { + public function testGetSharesByExpiredLinkShares(): void { $manager = $this->createManagerMock() - ->setMethods(['deleteShare']) + ->onlyMethods(['deleteShare']) ->getMock(); - /** @var \OCP\Share\IShare[] $shares */ + /** @var IShare[] $shares */ $shares = []; /* @@ -2667,7 +2956,7 @@ class ManagerTest extends \Test\TestCase { $shares[4]->setExpirationDate($today); $shares[5]->setExpirationDate($today); - /** @var \OCP\Share\IShare[] $i */ + /** @var IShare[] $i */ $shares2 = []; for ($i = 0; $i < 8; $i++) { $shares2[] = clone $shares[$i]; @@ -2688,7 +2977,7 @@ class ManagerTest extends \Test\TestCase { * Simulate the deleteShare call. */ $manager->method('deleteShare') - ->willReturnCallback(function ($share) use (&$shares2) { + ->willReturnCallback(function ($share) use (&$shares2): void { for ($i = 0; $i < count($shares2); $i++) { if ($shares2[$i]->getId() === $share->getId()) { array_splice($shares2, $i, 1); @@ -2712,35 +3001,18 @@ class ManagerTest extends \Test\TestCase { $this->assertSame($today, $shares[3]->getExpirationDate()); } - public function testGetShareByToken() { + public function testGetShareByToken(): void { $this->config - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getAppValue') - ->with('core', 'shareapi_allow_links', 'yes') - ->willReturn('yes'); + ->willReturnMap([ + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'], + ]); $factory = $this->createMock(IProviderFactory::class); - $manager = new Manager( - $this->logger, - $this->config, - $this->secureRandom, - $this->hasher, - $this->mountManager, - $this->groupManager, - $this->l, - $this->l10nFactory, - $factory, - $this->userManager, - $this->rootFolder, - $this->eventDispatcher, - $this->mailer, - $this->urlGenerator, - $this->defaults, - $this->dispatcher, - $this->userSession, - $this->knownUserService - ); + $manager = $this->createManager($factory); $share = $this->createMock(IShare::class); @@ -2758,35 +3030,18 @@ class ManagerTest extends \Test\TestCase { $this->assertSame($share, $ret); } - public function testGetShareByTokenRoom() { + public function testGetShareByTokenRoom(): void { $this->config - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getAppValue') - ->with('core', 'shareapi_allow_links', 'yes') - ->willReturn('no'); + ->willReturnMap([ + ['core', 'shareapi_allow_links', 'yes', 'no'], + ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'], + ]); $factory = $this->createMock(IProviderFactory::class); - $manager = new Manager( - $this->logger, - $this->config, - $this->secureRandom, - $this->hasher, - $this->mountManager, - $this->groupManager, - $this->l, - $this->l10nFactory, - $factory, - $this->userManager, - $this->rootFolder, - $this->eventDispatcher, - $this->mailer, - $this->urlGenerator, - $this->defaults, - $this->dispatcher, - $this->userSession, - $this->knownUserService - ); + $manager = $this->createManager($factory); $share = $this->createMock(IShare::class); @@ -2796,7 +3051,7 @@ class ManagerTest extends \Test\TestCase { ->method('getProviderForType') ->willReturnCallback(function ($shareType) use ($roomShareProvider) { if ($shareType !== IShare::TYPE_ROOM) { - throw new Exception\ProviderException(); + throw new ProviderException(); } return $roomShareProvider; @@ -2811,63 +3066,103 @@ class ManagerTest extends \Test\TestCase { $this->assertSame($share, $ret); } - public function testGetShareByTokenWithException() { + public function testGetShareByTokenWithException(): void { $this->config - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getAppValue') - ->with('core', 'shareapi_allow_links', 'yes') - ->willReturn('yes'); + ->willReturnMap([ + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'], + ]); $factory = $this->createMock(IProviderFactory::class); - $manager = new Manager( - $this->logger, - $this->config, - $this->secureRandom, - $this->hasher, - $this->mountManager, - $this->groupManager, - $this->l, - $this->l10nFactory, - $factory, - $this->userManager, - $this->rootFolder, - $this->eventDispatcher, - $this->mailer, - $this->urlGenerator, - $this->defaults, - $this->dispatcher, - $this->userSession, - $this->knownUserService - ); + $manager = $this->createManager($factory); $share = $this->createMock(IShare::class); - $factory->expects($this->at(0)) - ->method('getProviderForType') - ->with(IShare::TYPE_LINK) - ->willReturn($this->defaultProvider); - $factory->expects($this->at(1)) + $calls = [ + [IShare::TYPE_LINK], + [IShare::TYPE_REMOTE], + ]; + $factory->expects($this->exactly(2)) ->method('getProviderForType') - ->with(IShare::TYPE_REMOTE) - ->willReturn($this->defaultProvider); + ->willReturnCallback(function () use (&$calls) { + $expected = array_shift($calls); + $this->assertEquals($expected, func_get_args()); + return $this->defaultProvider; + }); - $this->defaultProvider->expects($this->at(0)) + $this->defaultProvider->expects($this->exactly(2)) ->method('getShareByToken') ->with('token') - ->will($this->throwException(new ShareNotFound())); - $this->defaultProvider->expects($this->at(1)) - ->method('getShareByToken') - ->with('token') - ->willReturn($share); + ->willReturnOnConsecutiveCalls( + $this->throwException(new ShareNotFound()), + $share + ); $ret = $manager->getShareByToken('token'); $this->assertSame($share, $ret); } - public function testGetShareByTokenExpired() { - $this->expectException(\OCP\Share\Exceptions\ShareNotFound::class); + public function testGetShareByTokenHideDisabledUser(): void { + $this->expectException(ShareNotFound::class); + $this->expectExceptionMessage('The requested share comes from a disabled user'); + + $this->config + ->expects($this->exactly(2)) + ->method('getAppValue') + ->willReturnMap([ + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['files_sharing', 'hide_disabled_user_shares', 'no', 'yes'], + ]); + + $this->l->expects($this->once()) + ->method('t') + ->willReturnArgument(0); + + $manager = $this->createManagerMock() + ->onlyMethods(['deleteShare']) + ->getMock(); + + $date = new \DateTime(); + $date->setTime(0, 0, 0); + $date->add(new \DateInterval('P2D')); + $share = $this->manager->newShare(); + $share->setExpirationDate($date); + $share->setShareOwner('owner'); + $share->setSharedBy('sharedBy'); + + $sharedBy = $this->createMock(IUser::class); + $owner = $this->createMock(IUser::class); + + $this->userManager->method('get')->willReturnMap([ + ['sharedBy', $sharedBy], + ['owner', $owner], + ]); + + $owner->expects($this->once()) + ->method('isEnabled') + ->willReturn(true); + $sharedBy->expects($this->once()) + ->method('isEnabled') + ->willReturn(false); + + $this->defaultProvider->expects($this->once()) + ->method('getShareByToken') + ->with('expiredToken') + ->willReturn($share); + + $manager->expects($this->never()) + ->method('deleteShare'); + + $manager->getShareByToken('expiredToken'); + } + + + public function testGetShareByTokenExpired(): void { + $this->expectException(ShareNotFound::class); $this->expectExceptionMessage('The requested share does not exist anymore'); $this->config @@ -2881,7 +3176,7 @@ class ManagerTest extends \Test\TestCase { ->willReturnArgument(0); $manager = $this->createManagerMock() - ->setMethods(['deleteShare']) + ->onlyMethods(['deleteShare']) ->getMock(); $date = new \DateTime(); @@ -2901,12 +3196,14 @@ class ManagerTest extends \Test\TestCase { $manager->getShareByToken('expiredToken'); } - public function testGetShareByTokenNotExpired() { + public function testGetShareByTokenNotExpired(): void { $this->config - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getAppValue') - ->with('core', 'shareapi_allow_links', 'yes') - ->willReturn('yes'); + ->willReturnMap([ + ['core', 'shareapi_allow_links', 'yes', 'yes'], + ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'], + ]); $date = new \DateTime(); $date->setTime(0, 0, 0); @@ -2925,8 +3222,8 @@ class ManagerTest extends \Test\TestCase { } - public function testGetShareByTokenWithPublicLinksDisabled() { - $this->expectException(\OCP\Share\Exceptions\ShareNotFound::class); + public function testGetShareByTokenWithPublicLinksDisabled(): void { + $this->expectException(ShareNotFound::class); $this->config ->expects($this->once()) @@ -2936,24 +3233,23 @@ class ManagerTest extends \Test\TestCase { $this->manager->getShareByToken('validToken'); } - public function testGetShareByTokenPublicUploadDisabled() { - $this->config - ->expects($this->at(0)) - ->method('getAppValue') - ->with('core', 'shareapi_allow_links', 'yes') - ->willReturn('yes'); - - $share = $this->manager->newShare(); - $share->setShareType(IShare::TYPE_LINK) - ->setPermissions(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE); - + public function testGetShareByTokenPublicUploadDisabled(): void { $this->config - ->expects($this->at(1)) + ->expects($this->exactly(3)) ->method('getAppValue') ->willReturnMap([ + ['core', 'shareapi_allow_links', 'yes', 'yes'], ['core', 'shareapi_allow_public_upload', 'yes', 'no'], + ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'], ]); + $share = $this->manager->newShare(); + $share->setShareType(IShare::TYPE_LINK) + ->setPermissions(Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE); + $share->setSharedWith('sharedWith'); + $folder = $this->createMock(\OC\Files\Node\Folder::class); + $share->setNode($folder); + $this->defaultProvider->expects($this->once()) ->method('getShareByToken') ->willReturn('validToken') @@ -2961,16 +3257,16 @@ class ManagerTest extends \Test\TestCase { $res = $this->manager->getShareByToken('validToken'); - $this->assertSame(\OCP\Constants::PERMISSION_READ, $res->getPermissions()); + $this->assertSame(Constants::PERMISSION_READ, $res->getPermissions()); } - public function testCheckPasswordNoLinkShare() { + public function testCheckPasswordNoLinkShare(): void { $share = $this->createMock(IShare::class); $share->method('getShareType')->willReturn(IShare::TYPE_USER); $this->assertFalse($this->manager->checkPassword($share, 'password')); } - public function testCheckPasswordNoPassword() { + public function testCheckPasswordNoPassword(): void { $share = $this->createMock(IShare::class); $share->method('getShareType')->willReturn(IShare::TYPE_LINK); $this->assertFalse($this->manager->checkPassword($share, 'password')); @@ -2979,7 +3275,7 @@ class ManagerTest extends \Test\TestCase { $this->assertFalse($this->manager->checkPassword($share, null)); } - public function testCheckPasswordInvalidPassword() { + public function testCheckPasswordInvalidPassword(): void { $share = $this->createMock(IShare::class); $share->method('getShareType')->willReturn(IShare::TYPE_LINK); $share->method('getPassword')->willReturn('password'); @@ -2989,7 +3285,7 @@ class ManagerTest extends \Test\TestCase { $this->assertFalse($this->manager->checkPassword($share, 'invalidpassword')); } - public function testCheckPasswordValidPassword() { + public function testCheckPasswordValidPassword(): void { $share = $this->createMock(IShare::class); $share->method('getShareType')->willReturn(IShare::TYPE_LINK); $share->method('getPassword')->willReturn('passwordHash'); @@ -2999,7 +3295,7 @@ class ManagerTest extends \Test\TestCase { $this->assertTrue($this->manager->checkPassword($share, 'password')); } - public function testCheckPasswordUpdateShare() { + public function testCheckPasswordUpdateShare(): void { $share = $this->manager->newShare(); $share->setShareType(IShare::TYPE_LINK) ->setPassword('passwordHash'); @@ -3013,7 +3309,7 @@ class ManagerTest extends \Test\TestCase { $this->defaultProvider->expects($this->once()) ->method('update') - ->with($this->callback(function (\OCP\Share\IShare $share) { + ->with($this->callback(function (IShare $share) { return $share->getPassword() === 'newHash'; })); @@ -3021,12 +3317,12 @@ class ManagerTest extends \Test\TestCase { } - public function testUpdateShareCantChangeShareType() { + public function testUpdateShareCantChangeShareType(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('Cannot change share type'); $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById' ]) @@ -3039,6 +3335,8 @@ class ManagerTest extends \Test\TestCase { $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare); $share = $this->manager->newShare(); + $attrs = $this->manager->newShare()->newAttributes(); + $attrs->setAttribute('app1', 'perm1', true); $share->setProviderId('foo') ->setId('42') ->setShareType(IShare::TYPE_USER); @@ -3047,12 +3345,12 @@ class ManagerTest extends \Test\TestCase { } - public function testUpdateShareCantChangeRecipientForGroupShare() { + public function testUpdateShareCantChangeRecipientForGroupShare(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('Can only update recipient on user shares'); $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById' ]) @@ -3075,12 +3373,12 @@ class ManagerTest extends \Test\TestCase { } - public function testUpdateShareCantShareWithOwner() { + public function testUpdateShareCantShareWithOwner(): void { $this->expectException(\Exception::class); $this->expectExceptionMessage('Cannot share with the share owner'); $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById' ]) @@ -3103,11 +3401,11 @@ class ManagerTest extends \Test\TestCase { $manager->updateShare($share); } - public function testUpdateShareUser() { + public function testUpdateShareUser(): void { $this->userManager->expects($this->any())->method('userExists')->willReturn(true); $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById', 'generalCreateChecks', @@ -3129,6 +3427,8 @@ class ManagerTest extends \Test\TestCase { $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare); $share = $this->manager->newShare(); + $attrs = $this->manager->newShare()->newAttributes(); + $attrs->setAttribute('app1', 'perm1', true); $share->setProviderId('foo') ->setId('42') ->setShareType(IShare::TYPE_USER) @@ -3136,6 +3436,7 @@ class ManagerTest extends \Test\TestCase { ->setShareOwner('newUser') ->setSharedBy('sharer') ->setPermissions(31) + ->setAttributes($attrs) ->setNode($node); $this->defaultProvider->expects($this->once()) @@ -3143,15 +3444,15 @@ class ManagerTest extends \Test\TestCase { ->with($share) ->willReturn($share); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); $hookListener->expects($this->never())->method('post'); $this->rootFolder->method('getUserFolder')->with('newUser')->willReturnSelf(); $this->rootFolder->method('getRelativePath')->with('/newUser/files/myPath')->willReturn('/myPath'); - $hookListener2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener2, 'post'); + $hookListener2 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener2, 'post'); $hookListener2->expects($this->once())->method('post')->with([ 'itemType' => 'file', 'itemSource' => 100, @@ -3160,14 +3461,15 @@ class ManagerTest extends \Test\TestCase { 'uidOwner' => 'sharer', 'permissions' => 31, 'path' => '/myPath', + 'attributes' => $attrs->toArray(), ]); $manager->updateShare($share); } - public function testUpdateShareGroup() { + public function testUpdateShareGroup(): void { $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById', 'generalCreateChecks', @@ -3200,20 +3502,20 @@ class ManagerTest extends \Test\TestCase { ->with($share) ->willReturn($share); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); $hookListener->expects($this->never())->method('post'); - $hookListener2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener2, 'post'); + $hookListener2 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener2, 'post'); $hookListener2->expects($this->never())->method('post'); $manager->updateShare($share); } - public function testUpdateShareLink() { + public function testUpdateShareLink(): void { $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById', 'generalCreateChecks', @@ -3262,8 +3564,8 @@ class ManagerTest extends \Test\TestCase { ->with($share) ->willReturn($share); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); $hookListener->expects($this->once())->method('post')->with([ 'itemType' => 'file', 'itemSource' => 100, @@ -3271,8 +3573,8 @@ class ManagerTest extends \Test\TestCase { 'uidOwner' => 'owner', ]); - $hookListener2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); + $hookListener2 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); $hookListener2->expects($this->once())->method('post')->with([ 'itemType' => 'file', 'itemSource' => 100, @@ -3281,20 +3583,20 @@ class ManagerTest extends \Test\TestCase { 'disabled' => false, ]); - $hookListener3 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); + $hookListener3 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); $hookListener3->expects($this->never())->method('post'); $manager->updateShare($share); } - public function testUpdateShareLinkEnableSendPasswordByTalkWithNoPassword() { + public function testUpdateShareLinkEnableSendPasswordByTalkWithNoPassword(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password'); $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById', 'generalCreateChecks', @@ -3343,24 +3645,24 @@ class ManagerTest extends \Test\TestCase { $this->defaultProvider->expects($this->never()) ->method('update'); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); $hookListener->expects($this->never())->method('post'); - $hookListener2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); + $hookListener2 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); $hookListener2->expects($this->never())->method('post'); - $hookListener3 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); + $hookListener3 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); $hookListener3->expects($this->never())->method('post'); $manager->updateShare($share); } - public function testUpdateShareMail() { + public function testUpdateShareMail(): void { $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById', 'generalCreateChecks', @@ -3373,7 +3675,7 @@ class ManagerTest extends \Test\TestCase { $originalShare = $this->manager->newShare(); $originalShare->setShareType(IShare::TYPE_EMAIL) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $tomorrow = new \DateTime(); $tomorrow->setTime(0, 0, 0); @@ -3392,7 +3694,7 @@ class ManagerTest extends \Test\TestCase { ->setPassword('password') ->setExpirationDate($tomorrow) ->setNode($file) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $manager->expects($this->once())->method('canShare')->willReturn(true); $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare); @@ -3412,8 +3714,8 @@ class ManagerTest extends \Test\TestCase { ->with($share, 'password') ->willReturn($share); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); $hookListener->expects($this->once())->method('post')->with([ 'itemType' => 'file', 'itemSource' => 100, @@ -3421,8 +3723,8 @@ class ManagerTest extends \Test\TestCase { 'uidOwner' => 'owner', ]); - $hookListener2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); + $hookListener2 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); $hookListener2->expects($this->once())->method('post')->with([ 'itemType' => 'file', 'itemSource' => 100, @@ -3431,16 +3733,16 @@ class ManagerTest extends \Test\TestCase { 'disabled' => false, ]); - $hookListener3 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); + $hookListener3 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); $hookListener3->expects($this->never())->method('post'); $manager->updateShare($share); } - public function testUpdateShareMailEnableSendPasswordByTalk() { + public function testUpdateShareMailEnableSendPasswordByTalk(): void { $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById', 'generalCreateChecks', @@ -3453,7 +3755,7 @@ class ManagerTest extends \Test\TestCase { $originalShare = $this->manager->newShare(); $originalShare->setShareType(IShare::TYPE_EMAIL) - ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setPermissions(Constants::PERMISSION_ALL) ->setPassword(null) ->setSendPasswordByTalk(false); @@ -3475,7 +3777,7 @@ class ManagerTest extends \Test\TestCase { ->setSendPasswordByTalk(true) ->setExpirationDate($tomorrow) ->setNode($file) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $manager->expects($this->once())->method('canShare')->willReturn(true); $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare); @@ -3495,8 +3797,8 @@ class ManagerTest extends \Test\TestCase { ->with($share, 'password') ->willReturn($share); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); $hookListener->expects($this->once())->method('post')->with([ 'itemType' => 'file', 'itemSource' => 100, @@ -3504,8 +3806,8 @@ class ManagerTest extends \Test\TestCase { 'uidOwner' => 'owner', ]); - $hookListener2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); + $hookListener2 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); $hookListener2->expects($this->once())->method('post')->with([ 'itemType' => 'file', 'itemSource' => 100, @@ -3514,16 +3816,16 @@ class ManagerTest extends \Test\TestCase { 'disabled' => false, ]); - $hookListener3 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); + $hookListener3 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); $hookListener3->expects($this->never())->method('post'); $manager->updateShare($share); } - public function testUpdateShareMailEnableSendPasswordByTalkWithDifferentPassword() { + public function testUpdateShareMailEnableSendPasswordByTalkWithDifferentPassword(): void { $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById', 'generalCreateChecks', @@ -3536,7 +3838,7 @@ class ManagerTest extends \Test\TestCase { $originalShare = $this->manager->newShare(); $originalShare->setShareType(IShare::TYPE_EMAIL) - ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setPermissions(Constants::PERMISSION_ALL) ->setPassword('anotherPasswordHash') ->setSendPasswordByTalk(false); @@ -3558,7 +3860,7 @@ class ManagerTest extends \Test\TestCase { ->setSendPasswordByTalk(true) ->setExpirationDate($tomorrow) ->setNode($file) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $manager->expects($this->once())->method('canShare')->willReturn(true); $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare); @@ -3583,8 +3885,8 @@ class ManagerTest extends \Test\TestCase { ->with($share, 'password') ->willReturn($share); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); $hookListener->expects($this->once())->method('post')->with([ 'itemType' => 'file', 'itemSource' => 100, @@ -3592,8 +3894,8 @@ class ManagerTest extends \Test\TestCase { 'uidOwner' => 'owner', ]); - $hookListener2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); + $hookListener2 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); $hookListener2->expects($this->once())->method('post')->with([ 'itemType' => 'file', 'itemSource' => 100, @@ -3602,19 +3904,19 @@ class ManagerTest extends \Test\TestCase { 'disabled' => false, ]); - $hookListener3 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); + $hookListener3 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); $hookListener3->expects($this->never())->method('post'); $manager->updateShare($share); } - public function testUpdateShareMailEnableSendPasswordByTalkWithNoPassword() { + public function testUpdateShareMailEnableSendPasswordByTalkWithNoPassword(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password'); $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById', 'generalCreateChecks', @@ -3627,7 +3929,7 @@ class ManagerTest extends \Test\TestCase { $originalShare = $this->manager->newShare(); $originalShare->setShareType(IShare::TYPE_EMAIL) - ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setPermissions(Constants::PERMISSION_ALL) ->setPassword(null) ->setSendPasswordByTalk(false); @@ -3649,7 +3951,7 @@ class ManagerTest extends \Test\TestCase { ->setSendPasswordByTalk(true) ->setExpirationDate($tomorrow) ->setNode($file) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $manager->expects($this->once())->method('canShare')->willReturn(true); $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare); @@ -3666,28 +3968,28 @@ class ManagerTest extends \Test\TestCase { $this->defaultProvider->expects($this->never()) ->method('update'); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); $hookListener->expects($this->never())->method('post'); - $hookListener2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); + $hookListener2 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); $hookListener2->expects($this->never())->method('post'); - $hookListener3 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); + $hookListener3 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); $hookListener3->expects($this->never())->method('post'); $manager->updateShare($share); } - public function testUpdateShareMailEnableSendPasswordByTalkRemovingPassword() { + public function testUpdateShareMailEnableSendPasswordByTalkRemovingPassword(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password'); $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById', 'generalCreateChecks', @@ -3700,7 +4002,7 @@ class ManagerTest extends \Test\TestCase { $originalShare = $this->manager->newShare(); $originalShare->setShareType(IShare::TYPE_EMAIL) - ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setPermissions(Constants::PERMISSION_ALL) ->setPassword('passwordHash') ->setSendPasswordByTalk(false); @@ -3722,7 +4024,7 @@ class ManagerTest extends \Test\TestCase { ->setSendPasswordByTalk(true) ->setExpirationDate($tomorrow) ->setNode($file) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $manager->expects($this->once())->method('canShare')->willReturn(true); $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare); @@ -3739,28 +4041,28 @@ class ManagerTest extends \Test\TestCase { $this->defaultProvider->expects($this->never()) ->method('update'); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); $hookListener->expects($this->never())->method('post'); - $hookListener2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); + $hookListener2 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); $hookListener2->expects($this->never())->method('post'); - $hookListener3 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); + $hookListener3 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); $hookListener3->expects($this->never())->method('post'); $manager->updateShare($share); } - public function testUpdateShareMailEnableSendPasswordByTalkRemovingPasswordWithEmptyString() { + public function testUpdateShareMailEnableSendPasswordByTalkRemovingPasswordWithEmptyString(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password'); $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById', 'generalCreateChecks', @@ -3773,7 +4075,7 @@ class ManagerTest extends \Test\TestCase { $originalShare = $this->manager->newShare(); $originalShare->setShareType(IShare::TYPE_EMAIL) - ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setPermissions(Constants::PERMISSION_ALL) ->setPassword('passwordHash') ->setSendPasswordByTalk(false); @@ -3795,7 +4097,7 @@ class ManagerTest extends \Test\TestCase { ->setSendPasswordByTalk(true) ->setExpirationDate($tomorrow) ->setNode($file) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $manager->expects($this->once())->method('canShare')->willReturn(true); $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare); @@ -3812,28 +4114,28 @@ class ManagerTest extends \Test\TestCase { $this->defaultProvider->expects($this->never()) ->method('update'); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); $hookListener->expects($this->never())->method('post'); - $hookListener2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); + $hookListener2 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); $hookListener2->expects($this->never())->method('post'); - $hookListener3 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); + $hookListener3 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); $hookListener3->expects($this->never())->method('post'); $manager->updateShare($share); } - public function testUpdateShareMailEnableSendPasswordByTalkWithPreviousPassword() { + public function testUpdateShareMailEnableSendPasswordByTalkWithPreviousPassword(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Cannot enable sending the password by Talk without setting a new password'); $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById', 'generalCreateChecks', @@ -3846,7 +4148,7 @@ class ManagerTest extends \Test\TestCase { $originalShare = $this->manager->newShare(); $originalShare->setShareType(IShare::TYPE_EMAIL) - ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setPermissions(Constants::PERMISSION_ALL) ->setPassword('password') ->setSendPasswordByTalk(false); @@ -3868,7 +4170,7 @@ class ManagerTest extends \Test\TestCase { ->setSendPasswordByTalk(true) ->setExpirationDate($tomorrow) ->setNode($file) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $manager->expects($this->once())->method('canShare')->willReturn(true); $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare); @@ -3887,27 +4189,27 @@ class ManagerTest extends \Test\TestCase { $this->defaultProvider->expects($this->never()) ->method('update'); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); $hookListener->expects($this->never())->method('post'); - $hookListener2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); + $hookListener2 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); $hookListener2->expects($this->never())->method('post'); - $hookListener3 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); + $hookListener3 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); $hookListener3->expects($this->never())->method('post'); $manager->updateShare($share); } - public function testUpdateShareMailDisableSendPasswordByTalkWithPreviousPassword() { + public function testUpdateShareMailDisableSendPasswordByTalkWithPreviousPassword(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Cannot disable sending the password by Talk without setting a new password'); $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById', 'generalCreateChecks', @@ -3920,7 +4222,7 @@ class ManagerTest extends \Test\TestCase { $originalShare = $this->manager->newShare(); $originalShare->setShareType(IShare::TYPE_EMAIL) - ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setPermissions(Constants::PERMISSION_ALL) ->setPassword('passwordHash') ->setSendPasswordByTalk(true); @@ -3942,7 +4244,7 @@ class ManagerTest extends \Test\TestCase { ->setSendPasswordByTalk(false) ->setExpirationDate($tomorrow) ->setNode($file) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $manager->expects($this->once())->method('canShare')->willReturn(true); $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare); @@ -3961,27 +4263,27 @@ class ManagerTest extends \Test\TestCase { $this->defaultProvider->expects($this->never()) ->method('update'); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); $hookListener->expects($this->never())->method('post'); - $hookListener2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); + $hookListener2 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); $hookListener2->expects($this->never())->method('post'); - $hookListener3 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); + $hookListener3 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); $hookListener3->expects($this->never())->method('post'); $manager->updateShare($share); } - public function testUpdateShareMailDisableSendPasswordByTalkWithoutChangingPassword() { + public function testUpdateShareMailDisableSendPasswordByTalkWithoutChangingPassword(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Cannot disable sending the password by Talk without setting a new password'); $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'canShare', 'getShareById', 'generalCreateChecks', @@ -3994,7 +4296,7 @@ class ManagerTest extends \Test\TestCase { $originalShare = $this->manager->newShare(); $originalShare->setShareType(IShare::TYPE_EMAIL) - ->setPermissions(\OCP\Constants::PERMISSION_ALL) + ->setPermissions(Constants::PERMISSION_ALL) ->setPassword('passwordHash') ->setSendPasswordByTalk(true); @@ -4016,7 +4318,7 @@ class ManagerTest extends \Test\TestCase { ->setSendPasswordByTalk(false) ->setExpirationDate($tomorrow) ->setNode($file) - ->setPermissions(\OCP\Constants::PERMISSION_ALL); + ->setPermissions(Constants::PERMISSION_ALL); $manager->expects($this->once())->method('canShare')->willReturn(true); $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare); @@ -4035,22 +4337,22 @@ class ManagerTest extends \Test\TestCase { $this->defaultProvider->expects($this->never()) ->method('update'); - $hookListener = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); + $hookListener = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post'); $hookListener->expects($this->never())->method('post'); - $hookListener2 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); + $hookListener2 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post'); $hookListener2->expects($this->never())->method('post'); - $hookListener3 = $this->getMockBuilder('Dummy')->setMethods(['post'])->getMock(); - \OCP\Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); + $hookListener3 = $this->createMock(DummyShareManagerListener::class); + Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post'); $hookListener3->expects($this->never())->method('post'); $manager->updateShare($share); } - public function testMoveShareLink() { + public function testMoveShareLink(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Cannot change target of link share'); @@ -4063,9 +4365,9 @@ class ManagerTest extends \Test\TestCase { } - public function testMoveShareUserNotRecipient() { + public function testMoveShareUserNotRecipient(): void { $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('Invalid recipient'); + $this->expectExceptionMessage('Invalid share recipient'); $share = $this->manager->newShare(); $share->setShareType(IShare::TYPE_USER); @@ -4075,7 +4377,7 @@ class ManagerTest extends \Test\TestCase { $this->manager->moveShare($share, 'recipient'); } - public function testMoveShareUser() { + public function testMoveShareUser(): void { $share = $this->manager->newShare(); $share->setShareType(IShare::TYPE_USER) ->setId('42') @@ -4090,9 +4392,9 @@ class ManagerTest extends \Test\TestCase { } - public function testMoveShareGroupNotRecipient() { + public function testMoveShareGroupNotRecipient(): void { $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('Invalid recipient'); + $this->expectExceptionMessage('Invalid share recipient'); $share = $this->manager->newShare(); $share->setShareType(IShare::TYPE_GROUP); @@ -4110,7 +4412,7 @@ class ManagerTest extends \Test\TestCase { } - public function testMoveShareGroupNull() { + public function testMoveShareGroupNull(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Group "shareWith" does not exist'); @@ -4126,7 +4428,7 @@ class ManagerTest extends \Test\TestCase { $this->manager->moveShare($share, 'recipient'); } - public function testMoveShareGroup() { + public function testMoveShareGroup(): void { $share = $this->manager->newShare(); $share->setShareType(IShare::TYPE_GROUP) ->setId('42') @@ -4147,74 +4449,34 @@ class ManagerTest extends \Test\TestCase { $this->addToAssertionCount(1); } - /** - * @dataProvider dataTestShareProviderExists - */ - public function testShareProviderExists($shareType, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestShareProviderExists')] + public function testShareProviderExists($shareType, $expected): void { $factory = $this->getMockBuilder('OCP\Share\IProviderFactory')->getMock(); $factory->expects($this->any())->method('getProviderForType') ->willReturnCallback(function ($id) { if ($id === IShare::TYPE_USER) { return true; } - throw new Exception\ProviderException(); + throw new ProviderException(); }); - $manager = new Manager( - $this->logger, - $this->config, - $this->secureRandom, - $this->hasher, - $this->mountManager, - $this->groupManager, - $this->l, - $this->l10nFactory, - $factory, - $this->userManager, - $this->rootFolder, - $this->eventDispatcher, - $this->mailer, - $this->urlGenerator, - $this->defaults, - $this->dispatcher, - $this->userSession, - $this->knownUserService - ); + $manager = $this->createManager($factory); $this->assertSame($expected, $manager->shareProviderExists($shareType) ); } - public function dataTestShareProviderExists() { + public static function dataTestShareProviderExists() { return [ [IShare::TYPE_USER, true], [42, false], ]; } - public function testGetSharesInFolder() { + public function testGetSharesInFolder(): void { $factory = new DummyFactory2($this->createMock(IServerContainer::class)); - $manager = new Manager( - $this->logger, - $this->config, - $this->secureRandom, - $this->hasher, - $this->mountManager, - $this->groupManager, - $this->l, - $this->l10nFactory, - $factory, - $this->userManager, - $this->rootFolder, - $this->eventDispatcher, - $this->mailer, - $this->urlGenerator, - $this->defaults, - $this->dispatcher, - $this->userSession, - $this->knownUserService - ); + $manager = $this->createManager($factory); $factory->setProvider($this->defaultProvider); $extraProvider = $this->createMock(IShareProvider::class); @@ -4258,29 +4520,45 @@ class ManagerTest extends \Test\TestCase { $this->assertSame($expects, $result); } - public function testGetAccessList() { + public function testGetSharesInFolderOwnerless(): void { $factory = new DummyFactory2($this->createMock(IServerContainer::class)); - $manager = new Manager( - $this->logger, - $this->config, - $this->secureRandom, - $this->hasher, - $this->mountManager, - $this->groupManager, - $this->l, - $this->l10nFactory, - $factory, - $this->userManager, - $this->rootFolder, - $this->eventDispatcher, - $this->mailer, - $this->urlGenerator, - $this->defaults, - $this->dispatcher, - $this->userSession, - $this->knownUserService - ); + $manager = $this->createManager($factory); + + $factory->setProvider($this->defaultProvider); + $extraProvider = $this->createMock(IShareProviderSupportsAllSharesInFolder::class); + $factory->setSecondProvider($extraProvider); + + $share1 = $this->createMock(IShare::class); + $share2 = $this->createMock(IShare::class); + + $mount = $this->createMock(IShareOwnerlessMount::class); + + $folder = $this->createMock(Folder::class); + $folder + ->method('getMountPoint') + ->willReturn($mount); + + $this->defaultProvider + ->method('getAllSharesInFolder') + ->with($folder) + ->willReturn([1 => [$share1]]); + + $extraProvider + ->method('getAllSharesInFolder') + ->with($folder) + ->willReturn([1 => [$share2]]); + + $this->assertSame([ + 1 => [$share1, $share2], + ], $manager->getSharesInFolder('user', $folder)); + } + + + public function testGetAccessList(): void { + $factory = new DummyFactory2($this->createMock(IServerContainer::class)); + + $manager = $this->createManager($factory); $factory->setProvider($this->defaultProvider); $extraProvider = $this->createMock(IShareProvider::class); @@ -4319,9 +4597,9 @@ class ManagerTest extends \Test\TestCase { ->willReturn($userFolder); $folder->method('getPath') ->willReturn('/owner/files/folder'); - $userFolder->method('getById') + $userFolder->method('getFirstNodeById') ->with($this->equalTo(42)) - ->willReturn([12 => $file]); + ->willReturn($file); $userFolder->method('getPath') ->willReturn('/user1/files'); @@ -4376,29 +4654,10 @@ class ManagerTest extends \Test\TestCase { $this->assertSame($expected['users'], $result['users']); } - public function testGetAccessListWithCurrentAccess() { + public function testGetAccessListWithCurrentAccess(): void { $factory = new DummyFactory2($this->createMock(IServerContainer::class)); - $manager = new Manager( - $this->logger, - $this->config, - $this->secureRandom, - $this->hasher, - $this->mountManager, - $this->groupManager, - $this->l, - $this->l10nFactory, - $factory, - $this->userManager, - $this->rootFolder, - $this->eventDispatcher, - $this->mailer, - $this->urlGenerator, - $this->defaults, - $this->dispatcher, - $this->userSession, - $this->knownUserService - ); + $manager = $this->createManager($factory); $factory->setProvider($this->defaultProvider); $extraProvider = $this->createMock(IShareProvider::class); @@ -4437,9 +4696,9 @@ class ManagerTest extends \Test\TestCase { ->willReturn($userFolder); $folder->method('getPath') ->willReturn('/owner/files/folder'); - $userFolder->method('getById') + $userFolder->method('getFirstNodeById') ->with($this->equalTo(42)) - ->willReturn([42 => $file]); + ->willReturn($file); $userFolder->method('getPath') ->willReturn('/user1/files'); @@ -4503,29 +4762,10 @@ class ManagerTest extends \Test\TestCase { $this->assertSame($expected['users'], $result['users']); } - public function testGetAllShares() { + public function testGetAllShares(): void { $factory = new DummyFactory2($this->createMock(IServerContainer::class)); - $manager = new Manager( - $this->logger, - $this->config, - $this->secureRandom, - $this->hasher, - $this->mountManager, - $this->groupManager, - $this->l, - $this->l10nFactory, - $factory, - $this->userManager, - $this->rootFolder, - $this->eventDispatcher, - $this->mailer, - $this->urlGenerator, - $this->defaults, - $this->dispatcher, - $this->userSession, - $this->knownUserService - ); + $manager = $this->createManager($factory); $factory->setProvider($this->defaultProvider); $extraProvider = $this->createMock(IShareProvider::class); @@ -4557,7 +4797,7 @@ class ManagerTest extends \Test\TestCase { $this->assertSame($expects, $result); } - public function dataCurrentUserCanEnumerateTargetUser(): array { + public static function dataCurrentUserCanEnumerateTargetUser(): array { return [ 'Full match guest' => [true, true, false, false, false, false, false, true], 'Full match user' => [false, true, false, false, false, false, false, true], @@ -4580,19 +4820,19 @@ class ManagerTest extends \Test\TestCase { } /** - * @dataProvider dataCurrentUserCanEnumerateTargetUser * @param bool $expected */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataCurrentUserCanEnumerateTargetUser')] public function testCurrentUserCanEnumerateTargetUser(bool $currentUserIsGuest, bool $allowEnumerationFullMatch, bool $allowEnumeration, bool $limitEnumerationToPhone, bool $limitEnumerationToGroups, bool $isKnownToUser, bool $haveCommonGroup, bool $expected): void { /** @var IManager|MockObject $manager */ $manager = $this->createManagerMock() - ->setMethods([ + ->onlyMethods([ 'allowEnumerationFullMatch', 'allowEnumeration', 'limitEnumerationToPhone', 'limitEnumerationToGroups', ]) - ->getMock(); + ->getMock(); $manager->method('allowEnumerationFullMatch') ->willReturn($allowEnumerationFullMatch); @@ -4636,11 +4876,10 @@ class ManagerTest extends \Test\TestCase { } class DummyFactory implements IProviderFactory { - /** @var IShareProvider */ protected $provider; - public function __construct(\OCP\IServerContainer $serverContainer) { + public function __construct(IServerContainer $serverContainer) { } /** diff --git a/tests/lib/Share20/ShareByMailProviderTest.php b/tests/lib/Share20/ShareByMailProviderTest.php new file mode 100644 index 00000000000..de4dc1a820c --- /dev/null +++ b/tests/lib/Share20/ShareByMailProviderTest.php @@ -0,0 +1,296 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace Test\Share20; + +use OC\Files\Node\Node; +use OCA\ShareByMail\Settings\SettingsManager; +use OCA\ShareByMail\ShareByMailProvider; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\Defaults; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\IRootFolder; +use OCP\IConfig; +use OCP\IDBConnection; +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\IUserManager; +use OCP\Mail\IMailer; +use OCP\Security\IHasher; +use OCP\Security\ISecureRandom; +use OCP\Server; +use OCP\Share\IShare; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; +use Test\TestCase; + +/** + * Class ShareByMailProviderTest + * + * @package Test\Share20 + * @group DB + */ +class ShareByMailProviderTest extends TestCase { + /** @var IDBConnection */ + protected $dbConn; + + /** @var IUserManager | \PHPUnit\Framework\MockObject\MockObject */ + protected $userManager; + + /** @var IRootFolder | \PHPUnit\Framework\MockObject\MockObject */ + protected $rootFolder; + + /** @var ShareByMailProvider */ + protected $provider; + + /** @var \PHPUnit\Framework\MockObject\MockObject|IMailer */ + protected $mailer; + + /** @var \PHPUnit\Framework\MockObject\MockObject|IL10N */ + protected $l10n; + + /** @var \PHPUnit\Framework\MockObject\MockObject|Defaults */ + protected $defaults; + + /** @var \PHPUnit\Framework\MockObject\MockObject|IURLGenerator */ + protected $urlGenerator; + + /** @var IConfig|MockObject */ + protected $config; + + /** @var LoggerInterface|MockObject */ + private $logger; + + /** @var IHasher|MockObject */ + private $hasher; + + /** @var \OCP\Activity\IManager|MockObject */ + private $activityManager; + + /** @var IEventDispatcher|MockObject */ + private $eventDispatcher; + + /** @var \OCP\Share\IManager|MockObject */ + private $shareManager; + + /** @var ISecureRandom|MockObject */ + private $secureRandom; + + /** @var SettingsManager|MockObject */ + private $settingsManager; + + protected function setUp(): void { + $this->dbConn = Server::get(IDBConnection::class); + $this->userManager = $this->createMock(IUserManager::class); + $this->rootFolder = $this->createMock(IRootFolder::class); + $this->mailer = $this->createMock(IMailer::class); + $this->l10n = $this->createMock(IL10N::class); + $this->defaults = $this->getMockBuilder(Defaults::class)->disableOriginalConstructor()->getMock(); + $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->activityManager = $this->createMock(\OCP\Activity\IManager::class); + $this->settingsManager = $this->createMock(SettingsManager::class); + $this->hasher = $this->createMock(IHasher::class); + $this->eventDispatcher = $this->createMock(IEventDispatcher::class); + $this->shareManager = $this->createMock(\OCP\Share\IManager::class); + $this->secureRandom = $this->createMock(ISecureRandom::class); + $this->config = $this->createMock(IConfig::class); + + // Empty share table + $this->dbConn->getQueryBuilder()->delete('share')->execute(); + + $this->provider = new ShareByMailProvider( + $this->config, + $this->dbConn, + $this->secureRandom, + $this->userManager, + $this->rootFolder, + $this->l10n, + $this->logger, + $this->mailer, + $this->urlGenerator, + $this->activityManager, + $this->settingsManager, + $this->defaults, + $this->hasher, + $this->eventDispatcher, + $this->shareManager, + ); + } + + protected function tearDown(): void { + $this->dbConn->getQueryBuilder()->delete('share')->execute(); + $this->dbConn->getQueryBuilder()->delete('filecache')->runAcrossAllShards()->execute(); + $this->dbConn->getQueryBuilder()->delete('storages')->execute(); + } + + /** + * @param int $shareType + * @param string $sharedWith + * @param string $sharedBy + * @param string $shareOwner + * @param string $itemType + * @param int $fileSource + * @param string $fileTarget + * @param int $permissions + * @param $token + * @param $expiration + * @param $parent + * @return int + * + * @throws \OCP\DB\Exception + */ + private function addShareToDB($shareType, $sharedWith, $sharedBy, $shareOwner, + $itemType, $fileSource, $fileTarget, $permissions, $token, $expiration, + $parent) { + $qb = $this->dbConn->getQueryBuilder(); + $qb->insert('share'); + + if ($shareType) { + $qb->setValue('share_type', $qb->expr()->literal($shareType)); + } + if ($sharedWith) { + $qb->setValue('share_with', $qb->expr()->literal($sharedWith)); + } + if ($sharedBy) { + $qb->setValue('uid_initiator', $qb->expr()->literal($sharedBy)); + } + if ($shareOwner) { + $qb->setValue('uid_owner', $qb->expr()->literal($shareOwner)); + } + if ($itemType) { + $qb->setValue('item_type', $qb->expr()->literal($itemType)); + } + if ($fileSource) { + $qb->setValue('file_source', $qb->expr()->literal($fileSource)); + } + if ($fileTarget) { + $qb->setValue('file_target', $qb->expr()->literal($fileTarget)); + } + if ($permissions) { + $qb->setValue('permissions', $qb->expr()->literal($permissions)); + } + if ($token) { + $qb->setValue('token', $qb->expr()->literal($token)); + } + if ($expiration) { + $qb->setValue('expiration', $qb->createNamedParameter($expiration, IQueryBuilder::PARAM_DATETIME_MUTABLE)); + } + if ($parent) { + $qb->setValue('parent', $qb->expr()->literal($parent)); + } + + $this->assertEquals(1, $qb->execute()); + return $qb->getLastInsertId(); + } + + public function testGetSharesByWithResharesAndNoNode(): void { + $this->addShareToDB( + IShare::TYPE_EMAIL, + 'external.one@domain.tld', + 'user1', + 'user1', + 'folder', + 42, + null, + 17, + 'foobar', + null, + null, + ); + $this->addShareToDB( + IShare::TYPE_EMAIL, + 'external.two@domain.tld', + 'user2', + 'user2', + 'folder', + 42, + null, + 17, + 'barfoo', + null, + null, + ); + + // Return own shares only if not asked for a specific node + /** @var IShare[] $actual */ + $actual = $this->provider->getSharesBy( + 'user1', + IShare::TYPE_EMAIL, + null, + true, + -1, + 0, + ); + + $this->assertCount(1, $actual); + + $this->assertEquals(IShare::TYPE_EMAIL, $actual[0]->getShareType()); + $this->assertEquals('user1', $actual[0]->getSharedBy()); + $this->assertEquals('user1', $actual[0]->getShareOwner()); + $this->assertEquals('external.one@domain.tld', $actual[0]->getSharedWith()); + } + + public function testGetSharesByWithResharesAndNode(): void { + $this->addShareToDB( + IShare::TYPE_EMAIL, + 'external.one@domain.tld', + 'user1', + 'user1', + 'folder', + 42, + null, + 17, + 'foobar', + null, + null, + ); + $this->addShareToDB( + IShare::TYPE_EMAIL, + 'external.two@domain.tld', + 'user2', + 'user2', + 'folder', + 42, + null, + 17, + 'barfoo', + null, + null, + ); + + $node = $this->createMock(Node::class); + $node->expects($this->once()) + ->method('getId') + ->willReturn(42); + + // Return all shares if asked for specific node + /** @var IShare[] $actual */ + $actual = $this->provider->getSharesBy( + 'user1', + IShare::TYPE_EMAIL, + $node, + true, + -1, + 0, + ); + + $this->assertCount(2, $actual); + + $this->assertEquals(IShare::TYPE_EMAIL, $actual[0]->getShareType()); + $this->assertEquals('user1', $actual[0]->getSharedBy()); + $this->assertEquals('user1', $actual[0]->getShareOwner()); + $this->assertEquals('external.one@domain.tld', $actual[0]->getSharedWith()); + + $this->assertEquals(IShare::TYPE_EMAIL, $actual[1]->getShareType()); + $this->assertEquals('user2', $actual[1]->getSharedBy()); + $this->assertEquals('user2', $actual[1]->getShareOwner()); + $this->assertEquals('external.two@domain.tld', $actual[1]->getSharedWith()); + } +} diff --git a/tests/lib/Share20/ShareHelperTest.php b/tests/lib/Share20/ShareHelperTest.php index b3e76735aaa..3928843cf7d 100644 --- a/tests/lib/Share20/ShareHelperTest.php +++ b/tests/lib/Share20/ShareHelperTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright 2017, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace Test\Share20; @@ -30,7 +14,6 @@ use OCP\Share\IManager; use Test\TestCase; class ShareHelperTest extends TestCase { - /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */ private $manager; @@ -45,7 +28,7 @@ class ShareHelperTest extends TestCase { $this->helper = new ShareHelper($this->manager); } - public function dataGetPathsForAccessList() { + public static function dataGetPathsForAccessList(): array { return [ [[], [], false, [], [], false, [ 'users' => [], @@ -66,10 +49,8 @@ class ShareHelperTest extends TestCase { ]; } - /** - * @dataProvider dataGetPathsForAccessList - */ - public function testGetPathsForAccessList(array $userList, array $userMap, $resolveUsers, array $remoteList, array $remoteMap, $resolveRemotes, array $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetPathsForAccessList')] + public function testGetPathsForAccessList(array $userList, array $userMap, $resolveUsers, array $remoteList, array $remoteMap, $resolveRemotes, array $expected): void { $this->manager->expects($this->once()) ->method('getAccessList') ->willReturn([ @@ -82,7 +63,7 @@ class ShareHelperTest extends TestCase { /** @var ShareHelper|\PHPUnit\Framework\MockObject\MockObject $helper */ $helper = $this->getMockBuilder(ShareHelper::class) ->setConstructorArgs([$this->manager]) - ->setMethods(['getPathsForUsers', 'getPathsForRemotes']) + ->onlyMethods(['getPathsForUsers', 'getPathsForRemotes']) ->getMock(); $helper->expects($resolveUsers ? $this->once() : $this->never()) @@ -98,7 +79,7 @@ class ShareHelperTest extends TestCase { $this->assertSame($expected, $helper->getPathsForAccessList($node)); } - public function dataGetPathsForUsers() { + public static function dataGetPathsForUsers(): array { return [ [[], [23 => 'TwentyThree', 42 => 'FortyTwo'], []], [ @@ -119,13 +100,13 @@ class ShareHelperTest extends TestCase { } /** - * @dataProvider dataGetPathsForUsers * * @param array $users * @param array $nodes * @param array $expected */ - public function testGetPathsForUsers(array $users, array $nodes, array $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetPathsForUsers')] + public function testGetPathsForUsers(array $users, array $nodes, array $expected): void { $lastNode = null; foreach ($nodes as $nodeId => $nodeName) { /** @var Node|\PHPUnit\Framework\MockObject\MockObject $node */ @@ -151,7 +132,7 @@ class ShareHelperTest extends TestCase { $this->assertEquals($expected, self::invokePrivate($this->helper, 'getPathsForUsers', [$lastNode, $users])); } - public function dataGetPathsForRemotes() { + public static function dataGetPathsForRemotes(): array { return [ [[], [23 => 'TwentyThree', 42 => 'FortyTwo'], []], [ @@ -176,13 +157,13 @@ class ShareHelperTest extends TestCase { } /** - * @dataProvider dataGetPathsForRemotes * * @param array $remotes * @param array $nodes * @param array $expected */ - public function testGetPathsForRemotes(array $remotes, array $nodes, array $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetPathsForRemotes')] + public function testGetPathsForRemotes(array $remotes, array $nodes, array $expected): void { $lastNode = null; foreach ($nodes as $nodeId => $nodePath) { /** @var Node|\PHPUnit\Framework\MockObject\MockObject $node */ @@ -208,7 +189,7 @@ class ShareHelperTest extends TestCase { $this->assertEquals($expected, self::invokePrivate($this->helper, 'getPathsForRemotes', [$lastNode, $remotes])); } - public function dataGetMountedPath() { + public static function dataGetMountedPath(): array { return [ ['/admin/files/foobar', '/foobar'], ['/admin/files/foo/bar', '/foo/bar'], @@ -216,11 +197,11 @@ class ShareHelperTest extends TestCase { } /** - * @dataProvider dataGetMountedPath * @param string $path * @param string $expected */ - public function testGetMountedPath($path, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetMountedPath')] + public function testGetMountedPath($path, $expected): void { /** @var Node|\PHPUnit\Framework\MockObject\MockObject $node */ $node = $this->createMock(Node::class); $node->expects($this->once()) diff --git a/tests/lib/Share20/ShareTest.php b/tests/lib/Share20/ShareTest.php index 7d4dc6de2d6..f15fbb860db 100644 --- a/tests/lib/Share20/ShareTest.php +++ b/tests/lib/Share20/ShareTest.php @@ -1,28 +1,19 @@ <?php + /** - * @author Roeland Jago Douma <rullzer@owncloud.com> - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace Test\Share20; +use OC\Share20\Share; use OCP\Files\IRootFolder; use OCP\IUserManager; +use OCP\Share\Exceptions\IllegalIDChangeException; +use OCP\Share\IShare; +use PHPUnit\Framework\MockObject\MockObject; /** * Class ShareTest @@ -30,40 +21,41 @@ use OCP\IUserManager; * @package Test\Share20 */ class ShareTest extends \Test\TestCase { - - /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */ + /** @var IRootFolder|MockObject */ protected $rootFolder; - /** @var \OCP\Share\IShare */ + /** @var IUserManager|MockObject */ + protected $userManager; + /** @var IShare */ protected $share; protected function setUp(): void { $this->rootFolder = $this->createMock(IRootFolder::class); $this->userManager = $this->createMock(IUserManager::class); - $this->share = new \OC\Share20\Share($this->rootFolder, $this->userManager); + $this->share = new Share($this->rootFolder, $this->userManager); } - public function testSetIdInvalid() { + public function testSetIdInvalid(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('String expected.'); $this->share->setId(1.2); } - public function testSetIdInt() { + public function testSetIdInt(): void { $this->share->setId(42); $this->assertEquals('42', $this->share->getId()); } - public function testSetIdString() { + public function testSetIdString(): void { $this->share->setId('foo'); $this->assertEquals('foo', $this->share->getId()); } - public function testSetIdOnce() { - $this->expectException(\OCP\Share\Exceptions\IllegalIDChangeException::class); + public function testSetIdOnce(): void { + $this->expectException(IllegalIDChangeException::class); $this->expectExceptionMessage('Not allowed to assign a new internal id to a share'); $this->share->setId('foo'); @@ -71,7 +63,7 @@ class ShareTest extends \Test\TestCase { } - public function testSetProviderIdInt() { + public function testSetProviderIdInt(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('String expected.'); @@ -79,15 +71,15 @@ class ShareTest extends \Test\TestCase { } - public function testSetProviderIdString() { + public function testSetProviderIdString(): void { $this->share->setProviderId('foo'); $this->share->setId('bar'); $this->assertEquals('foo:bar', $this->share->getFullId()); } - public function testSetProviderIdOnce() { - $this->expectException(\OCP\Share\Exceptions\IllegalIDChangeException::class); + public function testSetProviderIdOnce(): void { + $this->expectException(IllegalIDChangeException::class); $this->expectExceptionMessage('Not allowed to assign a new provider id to a share'); $this->share->setProviderId('foo'); |