diff options
author | Anna Larch <anna@nextcloud.com> | 2024-01-30 18:35:44 +0100 |
---|---|---|
committer | Anna Larch <anna@nextcloud.com> | 2024-02-15 18:01:12 +0100 |
commit | dce69154ba335b610d70094f9daaded3b642f8cb (patch) | |
tree | a9ef54384367de8b48c30fb4babd798fc14533be /apps/dav/tests | |
parent | 1f0cba5f991a3c12d230284b3d96f91fb50312fd (diff) | |
download | nextcloud-server-dce69154ba335b610d70094f9daaded3b642f8cb.tar.gz nextcloud-server-dce69154ba335b610d70094f9daaded3b642f8cb.zip |
enh(sharing): enable unsharing for sharees for DAV shares (addressbooks and calendars)
Signed-off-by: Anna Larch <anna@nextcloud.com>
Diffstat (limited to 'apps/dav/tests')
-rw-r--r-- | apps/dav/tests/integration/DAV/Sharing/SharingMapperTest.php | 109 | ||||
-rw-r--r-- | apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php | 46 | ||||
-rw-r--r-- | apps/dav/tests/unit/CalDAV/CalDavBackendTest.php | 31 | ||||
-rw-r--r-- | apps/dav/tests/unit/CalDAV/CalendarTest.php | 4 | ||||
-rw-r--r-- | apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php | 6 | ||||
-rw-r--r-- | apps/dav/tests/unit/CardDAV/CardDavBackendTest.php | 49 | ||||
-rw-r--r-- | apps/dav/tests/unit/DAV/Sharing/BackendTest.php | 427 | ||||
-rw-r--r-- | apps/dav/tests/unit/DAV/Sharing/SharingServiceTest.php | 72 |
8 files changed, 694 insertions, 50 deletions
diff --git a/apps/dav/tests/integration/DAV/Sharing/SharingMapperTest.php b/apps/dav/tests/integration/DAV/Sharing/SharingMapperTest.php new file mode 100644 index 00000000000..249f11c3780 --- /dev/null +++ b/apps/dav/tests/integration/DAV/Sharing/SharingMapperTest.php @@ -0,0 +1,109 @@ +<?php + +declare(strict_types=1); + +/* + * @copyright 2024 Anna Larch <anna.larch@gmx.net> + * + * @author Anna Larch <anna.larch@gmx.net> + * + * @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/>. + */ + +use OCA\DAV\DAV\Sharing\SharingMapper; +use OCP\IDBConnection; +use OCP\Server; +use Test\TestCase; + +/** + * @group DB + */ +class SharingMapperTest extends TestCase { + + private SharingMapper $mapper; + private IDBConnection $db; + + protected function setUp(): void { + parent::setUp(); + + $this->db = Server::get(IDBConnection::class); + $this->mapper = new SharingMapper($this->db); + $qb = $this->db->getQueryBuilder(); + $qb->delete('dav_shares')->executeStatement(); + } + + public function testShareAndGet(): void { + $resourceId = 42; + $resourceType = 'calendar'; + $access = 3; + $principal = 'principals/users/bob'; + $this->mapper->share($resourceId, $resourceType, $access, $principal); + $shares = $this->mapper->getSharesForId($resourceId, $resourceType); + $this->assertCount(1, $shares); + } + + public function testShareDelete(): void { + $resourceId = 42; + $resourceType = 'calendar'; + $access = 3; + $principal = 'principals/users/bob'; + $this->mapper->share($resourceId, $resourceType, $access, $principal); + $this->mapper->deleteShare($resourceId, $resourceType, $principal); + $shares = $this->mapper->getSharesForId($resourceId, $resourceType); + $this->assertEmpty($shares); + } + + public function testShareUnshare(): void { + $resourceId = 42; + $resourceType = 'calendar'; + $access = 3; + $principal = 'principals/groups/alicegroup'; + $userPrincipal = 'principals/users/alice'; + $this->mapper->share($resourceId, $resourceType, $access, $principal); + $this->mapper->unshare($resourceId, $resourceType, $userPrincipal); + $shares = $this->mapper->getSharesForId($resourceId, $resourceType); + $this->assertCount(1, $shares); + } + + public function testShareDeleteAll(): void { + $resourceId = 42; + $resourceType = 'calendar'; + $access = 3; + $principal = 'principals/groups/alicegroup'; + $userPrincipal = 'principals/users/alice'; + $this->mapper->share($resourceId, $resourceType, $access, $principal); + $this->mapper->unshare($resourceId, $resourceType, $userPrincipal); + $shares = $this->mapper->getSharesForId($resourceId, $resourceType); + $this->assertCount(1, $shares); + $this->mapper->deleteAllShares($resourceId, $resourceType); + $shares = $this->mapper->getSharesForId($resourceId, $resourceType); + $this->assertEmpty($shares); + } + + public function testShareDeleteAllForUser(): void { + $resourceId = 42; + $resourceType = 'calendar'; + $access = 3; + $principal = 'principals/groups/alicegroup'; + $this->mapper->share($resourceId, $resourceType, $access, $principal); + $shares = $this->mapper->getSharesForId($resourceId, $resourceType); + $this->assertCount(1, $shares); + $this->mapper->deleteAllSharesByUser($principal, $resourceType); + $shares = $this->mapper->getSharesForId($resourceId, $resourceType); + $this->assertEmpty($shares); + } + +} diff --git a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php index 4dd61c6e307..dbed804ea41 100644 --- a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php +++ b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php @@ -30,10 +30,14 @@ namespace OCA\DAV\Tests\unit\CalDAV; use OC\KnownUser\KnownUserService; use OCA\DAV\CalDAV\CalDavBackend; use OCA\DAV\CalDAV\Proxy\ProxyMapper; +use OCA\DAV\CalDAV\Sharing\Backend as SharingBackend; +use OCA\DAV\CalDAV\Sharing\Service; use OCA\DAV\Connector\Sabre\Principal; +use OCA\DAV\DAV\Sharing\SharingMapper; use OCP\Accounts\IAccountManager; use OCP\App\IAppManager; use OCP\EventDispatcher\IEventDispatcher; +use OCP\ICacheFactory; use OCP\IConfig; use OCP\IGroupManager; use OCP\IUserManager; @@ -56,26 +60,16 @@ use Test\TestCase; */ abstract class AbstractCalDavBackend extends TestCase { - /** @var CalDavBackend */ - protected $backend; - - /** @var Principal | MockObject */ - protected $principal; - /** @var IUserManager|MockObject */ - protected $userManager; - /** @var IGroupManager|MockObject */ - protected $groupManager; - /** @var IEventDispatcher|MockObject */ - protected $dispatcher; - - - /** @var IConfig | MockObject */ - private $config; - /** @var ISecureRandom */ - private $random; - /** @var LoggerInterface*/ - private $logger; + protected CalDavBackend $backend; + protected Principal|MockObject $principal; + protected IUserManager|MockObject $userManager; + protected IGroupManager|MockObject $groupManager; + protected IEventDispatcher|MockObject $dispatcher; + private LoggerInterface|MockObject $logger; + private IConfig|MockObject $config; + private ISecureRandom $random; + protected SharingBackend $sharingBackend; public const UNIT_TEST_USER = 'principals/users/caldav-unit-test'; public const UNIT_TEST_USER1 = 'principals/users/caldav-unit-test1'; public const UNIT_TEST_GROUP = 'principals/groups/caldav-unit-test-group'; @@ -100,7 +94,7 @@ abstract class AbstractCalDavBackend extends TestCase { $this->createMock(IConfig::class), $this->createMock(IFactory::class) ]) - ->setMethods(['getPrincipalByPath', 'getGroupMembership']) + ->setMethods(['getPrincipalByPath', 'getGroupMembership', 'findByUri']) ->getMock(); $this->principal->expects($this->any())->method('getPrincipalByPath') ->willReturn([ @@ -115,15 +109,23 @@ abstract class AbstractCalDavBackend extends TestCase { $this->random = \OC::$server->getSecureRandom(); $this->logger = $this->createMock(LoggerInterface::class); $this->config = $this->createMock(IConfig::class); + $this->sharingBackend = new SharingBackend( + $this->userManager, + $this->groupManager, + $this->principal, + $this->createMock(ICacheFactory::class), + new Service(new SharingMapper($db)), + $this->logger); $this->backend = new CalDavBackend( $db, $this->principal, $this->userManager, - $this->groupManager, $this->random, $this->logger, $this->dispatcher, - $this->config + $this->config, + $this->sharingBackend, + false, ); $this->cleanUpBackend(); diff --git a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php index b23091275ef..112786eb987 100644 --- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php +++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php @@ -93,6 +93,9 @@ class CalDavBackendTest extends AbstractCalDavBackend { 'href' => 'principal:' . self::UNIT_TEST_GROUP, 'readOnly' => true ] + ], [ + self::UNIT_TEST_USER1, + self::UNIT_TEST_GROUP, ]], [true, true, true, false, [ [ @@ -103,6 +106,9 @@ class CalDavBackendTest extends AbstractCalDavBackend { 'href' => 'principal:' . self::UNIT_TEST_GROUP2, 'readOnly' => false, ], + ], [ + self::UNIT_TEST_GROUP, + self::UNIT_TEST_GROUP2, ]], [true, true, true, true, [ [ @@ -113,12 +119,17 @@ class CalDavBackendTest extends AbstractCalDavBackend { 'href' => 'principal:' . self::UNIT_TEST_GROUP2, 'readOnly' => true, ], + ], [ + self::UNIT_TEST_GROUP, + self::UNIT_TEST_GROUP2, ]], [true, false, false, false, [ [ 'href' => 'principal:' . self::UNIT_TEST_USER1, 'readOnly' => true ], + ], [ + self::UNIT_TEST_USER1, ]], ]; @@ -127,27 +138,26 @@ class CalDavBackendTest extends AbstractCalDavBackend { /** * @dataProvider providesSharingData */ - public function testCalendarSharing($userCanRead, $userCanWrite, $groupCanRead, $groupCanWrite, $add): void { - /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject $l10n */ + public function testCalendarSharing($userCanRead, $userCanWrite, $groupCanRead, $groupCanWrite, $add, $principals): void { + $logger = $this->createMock(\Psr\Log\LoggerInterface::class); + $config = $this->createMock(IConfig::class); + /** @var IL10N|MockObject $l10n */ $l10n = $this->createMock(IL10N::class); - $l10n - ->expects($this->any()) + $l10n->expects($this->any()) ->method('t') ->willReturnCallback(function ($text, $parameters = []) { return vsprintf($text, $parameters); }); - $logger = $this->createMock(\Psr\Log\LoggerInterface::class); - - $config = $this->createMock(IConfig::class); - $this->userManager->expects($this->any()) ->method('userExists') ->willReturn(true); - $this->groupManager->expects($this->any()) ->method('groupExists') ->willReturn(true); + $this->principal->expects(self::atLeastOnce()) + ->method('findByUri') + ->willReturnOnConsecutiveCalls(...$principals); $calendarId = $this->createTestCalendar(); $calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER); @@ -1250,6 +1260,9 @@ EOD; $this->groupManager->expects($this->any()) ->method('groupExists') ->willReturn(true); + $this->principal->expects(self::atLeastOnce()) + ->method('findByUri') + ->willReturn(self::UNIT_TEST_USER); $me = self::UNIT_TEST_USER; $sharer = self::UNIT_TEST_USER1; diff --git a/apps/dav/tests/unit/CalDAV/CalendarTest.php b/apps/dav/tests/unit/CalDAV/CalendarTest.php index d61e4b58478..68e6e5ef251 100644 --- a/apps/dav/tests/unit/CalDAV/CalendarTest.php +++ b/apps/dav/tests/unit/CalDAV/CalendarTest.php @@ -83,11 +83,9 @@ class CalendarTest extends TestCase { public function testDeleteFromGroup(): void { - $this->expectException(\Sabre\DAV\Exception\Forbidden::class); - /** @var MockObject | CalDavBackend $backend */ $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock(); - $backend->expects($this->never())->method('updateShares'); + $backend->expects($this->once())->method('updateShares'); $backend->expects($this->any())->method('getShares')->willReturn([ ['href' => 'principal:group2'] ]); diff --git a/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php b/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php index 6634a602e74..3460c548de4 100644 --- a/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php +++ b/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php @@ -84,6 +84,7 @@ class PublicCalendarRootTest extends TestCase { $this->logger = $this->createMock(LoggerInterface::class); $dispatcher = $this->createMock(IEventDispatcher::class); $config = $this->createMock(IConfig::class); + $sharingBackend = $this->createMock(\OCA\DAV\CalDAV\Sharing\Backend::class); $this->principal->expects($this->any())->method('getGroupMembership') ->withAnyParameters() @@ -97,11 +98,12 @@ class PublicCalendarRootTest extends TestCase { $db, $this->principal, $this->userManager, - $this->groupManager, $this->random, $this->logger, $dispatcher, - $config + $config, + $sharingBackend, + false, ); $this->l10n = $this->getMockBuilder(IL10N::class) ->disableOriginalConstructor()->getMock(); diff --git a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php index 425e7c44ba7..ea80187f554 100644 --- a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php +++ b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php @@ -37,11 +37,15 @@ use OC\KnownUser\KnownUserService; use OCA\DAV\CalDAV\Proxy\ProxyMapper; use OCA\DAV\CardDAV\AddressBook; use OCA\DAV\CardDAV\CardDavBackend; +use OCA\DAV\CardDAV\Sharing\Backend; +use OCA\DAV\CardDAV\Sharing\Service; use OCA\DAV\Connector\Sabre\Principal; +use OCA\DAV\DAV\Sharing\SharingMapper; use OCP\Accounts\IAccountManager; use OCP\App\IAppManager; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\EventDispatcher\IEventDispatcher; +use OCP\ICacheFactory; use OCP\IConfig; use OCP\IDBConnection; use OCP\IGroupManager; @@ -50,6 +54,7 @@ use OCP\IUserManager; use OCP\IUserSession; use OCP\L10N\IFactory; use OCP\Share\IManager as ShareManager; +use Psr\Log\LoggerInterface; use Sabre\DAV\Exception\BadRequest; use Sabre\DAV\PropPatch; use Sabre\VObject\Component\VCard; @@ -78,7 +83,7 @@ class CardDavBackendTest extends TestCase { /** @var IEventDispatcher|MockObject */ private $dispatcher; - + private Backend $sharingBackend; /** @var IDBConnection */ private $db; @@ -141,7 +146,7 @@ class CardDavBackendTest extends TestCase { $this->createMock(IConfig::class), $this->createMock(IFactory::class) ]) - ->setMethods(['getPrincipalByPath', 'getGroupMembership']) + ->setMethods(['getPrincipalByPath', 'getGroupMembership', 'findByUri']) ->getMock(); $this->principal->method('getPrincipalByPath') ->willReturn([ @@ -154,8 +159,20 @@ class CardDavBackendTest extends TestCase { $this->dispatcher = $this->createMock(IEventDispatcher::class); $this->db = \OC::$server->getDatabaseConnection(); - - $this->backend = new CardDavBackend($this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher); + $this->sharingBackend = new Backend($this->userManager, + $this->groupManager, + $this->principal, + $this->createMock(ICacheFactory::class), + new Service(new SharingMapper($this->db)), + $this->createMock(LoggerInterface::class) + ); + + $this->backend = new CardDavBackend($this->db, + $this->principal, + $this->userManager, + $this->dispatcher, + $this->sharingBackend, + ); // start every test with a empty cards_properties and cards table $query = $this->db->getQueryBuilder(); $query->delete('cards_properties')->execute(); @@ -213,10 +230,12 @@ class CardDavBackendTest extends TestCase { $this->userManager->expects($this->any()) ->method('userExists') ->willReturn(true); - $this->groupManager->expects($this->any()) ->method('groupExists') ->willReturn(true); + $this->principal->expects(self::atLeastOnce()) + ->method('findByUri') + ->willReturnOnConsecutiveCalls(self::UNIT_TEST_USER1, self::UNIT_TEST_GROUP); $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); @@ -243,7 +262,7 @@ class CardDavBackendTest extends TestCase { public function testCardOperations(): void { /** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject $backend */ $backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend]) ->onlyMethods(['updateProperties', 'purgeProperties'])->getMock(); // create a new address book @@ -298,7 +317,7 @@ class CardDavBackendTest extends TestCase { public function testMultiCard(): void { $this->backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend]) ->setMethods(['updateProperties'])->getMock(); // create a new address book @@ -351,7 +370,7 @@ class CardDavBackendTest extends TestCase { public function testMultipleUIDOnDifferentAddressbooks(): void { $this->backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend]) ->onlyMethods(['updateProperties'])->getMock(); // create 2 new address books @@ -373,7 +392,7 @@ class CardDavBackendTest extends TestCase { public function testMultipleUIDDenied(): void { $this->backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend]) ->setMethods(['updateProperties'])->getMock(); // create a new address book @@ -394,7 +413,7 @@ class CardDavBackendTest extends TestCase { public function testNoValidUID(): void { $this->backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend]) ->setMethods(['updateProperties'])->getMock(); // create a new address book @@ -411,7 +430,7 @@ class CardDavBackendTest extends TestCase { public function testDeleteWithoutCard(): void { $this->backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend]) ->onlyMethods([ 'getCardId', 'addChange', @@ -451,7 +470,7 @@ class CardDavBackendTest extends TestCase { public function testSyncSupport(): void { $this->backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend]) ->setMethods(['updateProperties'])->getMock(); // create a new address book @@ -477,10 +496,12 @@ class CardDavBackendTest extends TestCase { $this->userManager->expects($this->any()) ->method('userExists') ->willReturn(true); - $this->groupManager->expects($this->any()) ->method('groupExists') ->willReturn(true); + $this->principal->expects(self::any()) + ->method('findByUri') + ->willReturn(self::UNIT_TEST_USER1); $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []); $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER); @@ -517,7 +538,7 @@ class CardDavBackendTest extends TestCase { $cardId = 2; $backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend]) ->onlyMethods(['getCardId'])->getMock(); $backend->expects($this->any())->method('getCardId')->willReturn($cardId); diff --git a/apps/dav/tests/unit/DAV/Sharing/BackendTest.php b/apps/dav/tests/unit/DAV/Sharing/BackendTest.php new file mode 100644 index 00000000000..eaa8f3805a1 --- /dev/null +++ b/apps/dav/tests/unit/DAV/Sharing/BackendTest.php @@ -0,0 +1,427 @@ +<?php + +declare(strict_types=1); +/* + * @copyright 2024 Anna Larch <anna.larch@gmx.net> + * + * @author Anna Larch <anna.larch@gmx.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library 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 library. If not, see <http://www.gnu.org/licenses/>. + */ +namespace OCA\DAV\Tests\unit\DAV\Sharing; + +use OCA\DAV\CalDAV\Sharing\Backend as CalendarSharingBackend; +use OCA\DAV\CalDAV\Sharing\Service; +use OCA\DAV\CardDAV\Sharing\Backend as ContactsSharingBackend; +use OCA\DAV\Connector\Sabre\Principal; +use OCA\DAV\DAV\Sharing\Backend; +use OCA\DAV\DAV\Sharing\IShareable; +use OCP\ICache; +use OCP\ICacheFactory; +use OCP\IDBConnection; +use OCP\IGroupManager; +use OCP\IUserManager; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; +use Test\TestCase; + +class BackendTest extends TestCase { + + private IDBConnection|MockObject $db; + private IUserManager|MockObject $userManager; + private IGroupManager|MockObject $groupManager; + private MockObject|Principal $principalBackend; + private MockObject|ICache $shareCache; + private LoggerInterface|MockObject $logger; + private MockObject|ICacheFactory $cacheFactory; + private Service|MockObject $calendarService; + private CalendarSharingBackend $backend; + + protected function setUp(): void { + parent::setUp(); + $this->db = $this->createMock(IDBConnection::class); + $this->userManager = $this->createMock(IUserManager::class); + $this->groupManager = $this->createMock(IGroupManager::class); + $this->principalBackend = $this->createMock(Principal::class); + $this->cacheFactory = $this->createMock(ICacheFactory::class); + $this->shareCache = $this->createMock(ICache::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->calendarService = $this->createMock(Service::class); + $this->cacheFactory->expects(self::any()) + ->method('createInMemory') + ->willReturn($this->shareCache); + + $this->backend = new CalendarSharingBackend( + $this->userManager, + $this->groupManager, + $this->principalBackend, + $this->cacheFactory, + $this->calendarService, + $this->logger, + ); + } + + public function testUpdateShareCalendarBob(): void { + $shareable = $this->createConfiguredMock(IShareable::class, [ + 'getOwner' => 'principals/users/alice', + 'getResourceId' => 42, + ]); + $add = [ + [ + 'href' => 'principal:principals/users/bob', + 'readOnly' => true, + ] + ]; + $principal = 'principals/users/bob'; + + $this->shareCache->expects(self::once()) + ->method('clear'); + $this->principalBackend->expects(self::once()) + ->method('findByUri') + ->willReturn($principal); + $this->userManager->expects(self::once()) + ->method('userExists') + ->willReturn(true); + $this->groupManager->expects(self::never()) + ->method('groupExists'); + $this->calendarService->expects(self::once()) + ->method('shareWith') + ->with($shareable->getResourceId(), $principal, Backend::ACCESS_READ); + + $this->backend->updateShares($shareable, $add, []); + } + + public function testUpdateShareCalendarGroup(): void { + $shareable = $this->createConfiguredMock(IShareable::class, [ + 'getOwner' => 'principals/users/alice', + 'getResourceId' => 42, + ]); + $add = [ + [ + 'href' => 'principal:principals/groups/bob', + 'readOnly' => true, + ] + ]; + $principal = 'principals/groups/bob'; + + $this->shareCache->expects(self::once()) + ->method('clear'); + $this->principalBackend->expects(self::once()) + ->method('findByUri') + ->willReturn($principal); + $this->userManager->expects(self::never()) + ->method('userExists'); + $this->groupManager->expects(self::once()) + ->method('groupExists') + ->willReturn(true); + $this->calendarService->expects(self::once()) + ->method('shareWith') + ->with($shareable->getResourceId(), $principal, Backend::ACCESS_READ); + + $this->backend->updateShares($shareable, $add, []); + } + + public function testUpdateShareContactsBob(): void { + $shareable = $this->createConfiguredMock(IShareable::class, [ + 'getOwner' => 'principals/users/alice', + 'getResourceId' => 42, + ]); + $add = [ + [ + 'href' => 'principal:principals/users/bob', + 'readOnly' => true, + ] + ]; + $principal = 'principals/users/bob'; + + $this->shareCache->expects(self::once()) + ->method('clear'); + $this->principalBackend->expects(self::once()) + ->method('findByUri') + ->willReturn($principal); + $this->userManager->expects(self::once()) + ->method('userExists') + ->willReturn(true); + $this->groupManager->expects(self::never()) + ->method('groupExists'); + $this->calendarService->expects(self::once()) + ->method('shareWith') + ->with($shareable->getResourceId(), $principal, Backend::ACCESS_READ); + + $this->backend->updateShares($shareable, $add, []); + } + + public function testUpdateShareContactsGroup(): void { + $shareable = $this->createConfiguredMock(IShareable::class, [ + 'getOwner' => 'principals/users/alice', + 'getResourceId' => 42, + ]); + $add = [ + [ + 'href' => 'principal:principals/groups/bob', + 'readOnly' => true, + ] + ]; + $principal = 'principals/groups/bob'; + + $this->shareCache->expects(self::once()) + ->method('clear'); + $this->principalBackend->expects(self::once()) + ->method('findByUri') + ->willReturn($principal); + $this->userManager->expects(self::never()) + ->method('userExists'); + $this->groupManager->expects(self::once()) + ->method('groupExists') + ->willReturn(true); + $this->calendarService->expects(self::once()) + ->method('shareWith') + ->with($shareable->getResourceId(), $principal, Backend::ACCESS_READ); + + $this->backend->updateShares($shareable, $add, []); + } + + public function testUpdateShareCircle(): void { + $shareable = $this->createConfiguredMock(IShareable::class, [ + 'getOwner' => 'principals/users/alice', + 'getResourceId' => 42, + ]); + $add = [ + [ + 'href' => 'principal:principals/circles/bob', + 'readOnly' => true, + ] + ]; + $principal = 'principals/groups/bob'; + + $this->shareCache->expects(self::once()) + ->method('clear'); + $this->principalBackend->expects(self::once()) + ->method('findByUri') + ->willReturn($principal); + $this->userManager->expects(self::never()) + ->method('userExists'); + $this->groupManager->expects(self::once()) + ->method('groupExists') + ->willReturn(true); + $this->calendarService->expects(self::once()) + ->method('shareWith') + ->with($shareable->getResourceId(), $principal, Backend::ACCESS_READ); + + $this->backend->updateShares($shareable, $add, []); + } + + public function testUnshareBob(): void { + $shareable = $this->createConfiguredMock(IShareable::class, [ + 'getOwner' => 'principals/users/alice', + 'getResourceId' => 42, + ]); + $remove = [ + [ + 'href' => 'principal:principals/users/bob', + 'readOnly' => true, + ] + ]; + $principal = 'principals/users/bob'; + + $this->shareCache->expects(self::once()) + ->method('clear'); + $this->principalBackend->expects(self::once()) + ->method('findByUri') + ->willReturn($principal); + $this->calendarService->expects(self::once()) + ->method('deleteShare') + ->with($shareable->getResourceId(), $principal); + $this->calendarService->expects(self::once()) + ->method('hasGroupShare') + ->willReturn(false); + $this->calendarService->expects(self::never()) + ->method('unshare'); + + $this->backend->updateShares($shareable, [], $remove); + } + + public function testUnshareWithBobGroup(): void { + $shareable = $this->createConfiguredMock(IShareable::class, [ + 'getOwner' => 'principals/users/alice', + 'getResourceId' => 42, + ]); + $remove = [ + [ + 'href' => 'principal:principals/users/bob', + 'readOnly' => true, + ] + ]; + $oldShares = [ + [ + 'href' => 'principal:principals/groups/bob', + 'commonName' => 'bob', + 'status' => 1, + 'readOnly' => true, + '{http://owncloud.org/ns}principal' => 'principals/groups/bob', + '{http://owncloud.org/ns}group-share' => true, + ] + ]; + + + $this->shareCache->expects(self::once()) + ->method('clear'); + $this->principalBackend->expects(self::once()) + ->method('findByUri') + ->willReturn('principals/users/bob'); + $this->calendarService->expects(self::once()) + ->method('deleteShare') + ->with($shareable->getResourceId(), 'principals/users/bob'); + $this->calendarService->expects(self::once()) + ->method('hasGroupShare') + ->with($oldShares) + ->willReturn(true); + $this->calendarService->expects(self::once()) + ->method('unshare') + ->with($shareable->getResourceId(), 'principals/users/bob'); + + $this->backend->updateShares($shareable, [], $remove, $oldShares); + } + + public function testGetShares(): void { + $resourceId = 42; + $principal = 'principals/groups/bob'; + $rows = [ + [ + 'principaluri' => $principal, + 'access' => Backend::ACCESS_READ, + ] + ]; + $expected = [ + [ + 'href' => 'principal:principals/groups/bob', + 'commonName' => 'bob', + 'status' => 1, + 'readOnly' => true, + '{http://owncloud.org/ns}principal' => $principal, + '{http://owncloud.org/ns}group-share' => true, + ] + ]; + + + $this->shareCache->expects(self::once()) + ->method('get') + ->with((string)$resourceId) + ->willReturn(null); + $this->calendarService->expects(self::once()) + ->method('getShares') + ->with($resourceId) + ->willReturn($rows); + $this->principalBackend->expects(self::once()) + ->method('getPrincipalByPath') + ->with($principal) + ->willReturn(['uri' => $principal, '{DAV:}displayname' => 'bob']); + $this->shareCache->expects(self::once()) + ->method('set') + ->with((string)$resourceId, $expected); + + $result = $this->backend->getShares($resourceId); + $this->assertEquals($expected, $result); + } + + public function testGetSharesAddressbooks(): void { + $service = $this->createMock(\OCA\DAV\CardDAV\Sharing\Service::class); + $backend = new ContactsSharingBackend( + $this->userManager, + $this->groupManager, + $this->principalBackend, + $this->cacheFactory, + $service, + $this->logger); + $resourceId = 42; + $principal = 'principals/groups/bob'; + $rows = [ + [ + 'principaluri' => $principal, + 'access' => Backend::ACCESS_READ, + ] + ]; + $expected = [ + [ + 'href' => 'principal:principals/groups/bob', + 'commonName' => 'bob', + 'status' => 1, + 'readOnly' => true, + '{http://owncloud.org/ns}principal' => $principal, + '{http://owncloud.org/ns}group-share' => true, + ] + ]; + + $this->shareCache->expects(self::once()) + ->method('get') + ->with((string)$resourceId) + ->willReturn(null); + $service->expects(self::once()) + ->method('getShares') + ->with($resourceId) + ->willReturn($rows); + $this->principalBackend->expects(self::once()) + ->method('getPrincipalByPath') + ->with($principal) + ->willReturn(['uri' => $principal, '{DAV:}displayname' => 'bob']); + $this->shareCache->expects(self::once()) + ->method('set') + ->with((string)$resourceId, $expected); + + $result = $backend->getShares($resourceId); + $this->assertEquals($expected, $result); + } + + public function testPreloadShares(): void { + $resourceIds = [42, 99]; + $rows = [ + [ + 'resourceid' => 42, + 'principaluri' => 'principals/groups/bob', + 'access' => Backend::ACCESS_READ, + ], + [ + 'resourceid' => 99, + 'principaluri' => 'principals/users/carlos', + 'access' => Backend::ACCESS_READ_WRITE, + ] + ]; + $principalResults = [ + ['uri' => 'principals/groups/bob', '{DAV:}displayname' => 'bob'], + ['uri' => 'principals/users/carlos', '{DAV:}displayname' => 'carlos'], + ]; + + $this->shareCache->expects(self::exactly(2)) + ->method('get') + ->willReturn(null); + $this->calendarService->expects(self::once()) + ->method('getSharesForIds') + ->with($resourceIds) + ->willReturn($rows); + $this->principalBackend->expects(self::exactly(2)) + ->method('getPrincipalByPath') + ->willReturnCallback(function (string $principal) use ($principalResults) { + switch ($principal) { + case 'principals/groups/bob': + return $principalResults[0]; + default: + return $principalResults[1]; + } + }); + $this->shareCache->expects(self::exactly(2)) + ->method('set'); + + $this->backend->preloadShares($resourceIds); + } +} diff --git a/apps/dav/tests/unit/DAV/Sharing/SharingServiceTest.php b/apps/dav/tests/unit/DAV/Sharing/SharingServiceTest.php new file mode 100644 index 00000000000..97cd3176d3b --- /dev/null +++ b/apps/dav/tests/unit/DAV/Sharing/SharingServiceTest.php @@ -0,0 +1,72 @@ +<?php + +declare(strict_types=1); +/* + * @copyright 2024 Anna Larch <anna.larch@gmx.net> + * + * @author Anna Larch <anna.larch@gmx.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library 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 library. If not, see <http://www.gnu.org/licenses/>. + */ +namespace OCA\DAV\Tests\unit\DAV\Sharing; + +use OCA\DAV\CalDAV\Sharing\Service; +use OCA\DAV\DAV\Sharing\SharingMapper; +use OCA\DAV\DAV\Sharing\SharingService; +use Test\TestCase; + +class SharingServiceTest extends TestCase { + + private SharingService $service; + + protected function setUp(): void { + parent::setUp(); + $this->service = new Service($this->createMock(SharingMapper::class)); + } + + public function testHasGroupShare(): void { + $oldShares = [ + [ + 'href' => 'principal:principals/groups/bob', + 'commonName' => 'bob', + 'status' => 1, + 'readOnly' => true, + '{http://owncloud.org/ns}principal' => 'principals/groups/bob', + '{http://owncloud.org/ns}group-share' => true, + ], + [ + 'href' => 'principal:principals/users/bob', + 'commonName' => 'bob', + 'status' => 1, + 'readOnly' => true, + '{http://owncloud.org/ns}principal' => 'principals/users/bob', + '{http://owncloud.org/ns}group-share' => false, + ] + ]; + + $this->assertTrue($this->service->hasGroupShare($oldShares)); + + $oldShares = [ + [ + 'href' => 'principal:principals/users/bob', + 'commonName' => 'bob', + 'status' => 1, + 'readOnly' => true, + '{http://owncloud.org/ns}principal' => 'principals/users/bob', + '{http://owncloud.org/ns}group-share' => false, + ] + ]; + $this->assertFalse($this->service->hasGroupShare($oldShares)); + } +} |