diff options
Diffstat (limited to 'apps/dav/tests/integration/DAV/Sharing/CalDavSharingBackendTest.php')
-rw-r--r-- | apps/dav/tests/integration/DAV/Sharing/CalDavSharingBackendTest.php | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/apps/dav/tests/integration/DAV/Sharing/CalDavSharingBackendTest.php b/apps/dav/tests/integration/DAV/Sharing/CalDavSharingBackendTest.php new file mode 100644 index 00000000000..be06e8e4d4b --- /dev/null +++ b/apps/dav/tests/integration/DAV/Sharing/CalDavSharingBackendTest.php @@ -0,0 +1,251 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\DAV\Tests\integration\DAV\Sharing; + +use OC\Memcache\NullCache; +use OCA\DAV\CalDAV\Calendar; +use OCA\DAV\CalDAV\Sharing\Service; +use OCA\DAV\Connector\Sabre\Principal; +use OCA\DAV\DAV\Sharing\Backend; +use OCA\DAV\DAV\Sharing\SharingMapper; +use OCA\DAV\DAV\Sharing\SharingService; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\ICacheFactory; +use OCP\IDBConnection; +use OCP\IGroupManager; +use OCP\IUserManager; +use OCP\Server; +use Psr\Log\LoggerInterface; +use Test\TestCase; + +/** + * @group DB + */ +class CalDavSharingBackendTest extends TestCase { + + private IDBConnection $db; + private IUserManager $userManager; + private IGroupManager $groupManager; + private Principal $principalBackend; + private ICacheFactory $cacheFactory; + private LoggerInterface $logger; + private SharingMapper $sharingMapper; + private SharingService $sharingService; + private Backend $sharingBackend; + + private $resourceIds = [10001]; + + protected function setUp(): void { + parent::setUp(); + + $this->db = Server::get(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->cacheFactory->method('createInMemory') + ->willReturn(new NullCache()); + $this->logger = new \Psr\Log\NullLogger(); + + $this->sharingMapper = new SharingMapper($this->db); + $this->sharingService = new Service($this->sharingMapper); + + $this->sharingBackend = new \OCA\DAV\CalDAV\Sharing\Backend( + $this->userManager, + $this->groupManager, + $this->principalBackend, + $this->cacheFactory, + $this->sharingService, + $this->logger + ); + + $this->removeFixtures(); + } + + protected function tearDown(): void { + $this->removeFixtures(); + } + + protected function removeFixtures(): void { + $qb = $this->db->getQueryBuilder(); + $qb->delete('dav_shares') + ->where($qb->expr()->in('resourceid', $qb->createNamedParameter($this->resourceIds, IQueryBuilder::PARAM_INT_ARRAY))); + $qb->executeStatement(); + } + + public function testShareCalendarWithGroup(): void { + $calendar = $this->createMock(Calendar::class); + $calendar->method('getResourceId') + ->willReturn(10001); + $calendar->method('getOwner') + ->willReturn('principals/users/admin'); + + $this->principalBackend->method('findByUri') + ->willReturn('principals/groups/alice_bob'); + + $this->groupManager->method('groupExists') + ->willReturn(true); + + $this->sharingBackend->updateShares( + $calendar, + [['href' => 'principals/groups/alice_bob']], + [], + [] + ); + + $this->assertCount(1, $this->sharingService->getShares(10001)); + } + + public function testUnshareCalendarFromGroup(): void { + $calendar = $this->createMock(Calendar::class); + $calendar->method('getResourceId') + ->willReturn(10001); + $calendar->method('getOwner') + ->willReturn('principals/users/admin'); + + $this->principalBackend->method('findByUri') + ->willReturn('principals/groups/alice_bob'); + + $this->groupManager->method('groupExists') + ->willReturn(true); + + $this->sharingBackend->updateShares( + shareable: $calendar, + add: [['href' => 'principals/groups/alice_bob']], + remove: [], + ); + + $this->assertCount(1, $this->sharingService->getShares(10001)); + + $this->sharingBackend->updateShares( + shareable: $calendar, + add: [], + remove: ['principals/groups/alice_bob'], + ); + + $this->assertCount(0, $this->sharingService->getShares(10001)); + } + + public function testShareCalendarWithGroupAndUnshareAsUser(): void { + $calendar = $this->createMock(Calendar::class); + $calendar->method('getResourceId') + ->willReturn(10001); + $calendar->method('getOwner') + ->willReturn('principals/users/admin'); + + $this->principalBackend->method('findByUri') + ->willReturnMap([ + ['principals/groups/alice_bob', '', 'principals/groups/alice_bob'], + ['principals/users/bob', '', 'principals/users/bob'], + ]); + $this->principalBackend->method('getGroupMembership') + ->willReturn([ + 'principals/groups/alice_bob', + ]); + $this->principalBackend->method('getCircleMembership') + ->willReturn([]); + + $this->groupManager->method('groupExists') + ->willReturn(true); + + /* + * Owner is sharing the calendar with a group. + */ + $this->sharingBackend->updateShares( + shareable: $calendar, + add: [['href' => 'principals/groups/alice_bob']], + remove: [], + ); + + $this->assertCount(1, $this->sharingService->getShares(10001)); + + /* + * Member of the group unshares the calendar. + */ + $this->sharingBackend->unshare( + shareable: $calendar, + principalUri: 'principals/users/bob' + ); + + $this->assertCount(1, $this->sharingService->getShares(10001)); + $this->assertCount(1, $this->sharingService->getUnshares(10001)); + } + + /** + * Tests the functionality of sharing a calendar with a user, then with a group (that includes the shared user), + * and subsequently unsharing it from the individual user. Verifies that the unshare operation correctly removes the specific user share + * without creating an additional unshare entry. + */ + public function testShareCalendarWithUserThenGroupThenUnshareUser(): void { + $calendar = $this->createMock(Calendar::class); + $calendar->method('getResourceId') + ->willReturn(10001); + $calendar->method('getOwner') + ->willReturn('principals/users/admin'); + + $this->principalBackend->method('findByUri') + ->willReturnMap([ + ['principals/groups/alice_bob', '', 'principals/groups/alice_bob'], + ['principals/users/bob', '', 'principals/users/bob'], + ]); + $this->principalBackend->method('getGroupMembership') + ->willReturn([ + 'principals/groups/alice_bob', + ]); + $this->principalBackend->method('getCircleMembership') + ->willReturn([]); + + $this->userManager->method('userExists') + ->willReturn(true); + $this->groupManager->method('groupExists') + ->willReturn(true); + + /* + * Step 1) The owner shares the calendar with a user. + */ + $this->sharingBackend->updateShares( + shareable: $calendar, + add: [['href' => 'principals/users/bob']], + remove: [], + ); + + $this->assertCount(1, $this->sharingService->getShares(10001)); + + /* + * Step 2) The owner shares the calendar with a group that includes the + * user from step 1 as a member. + */ + $this->sharingBackend->updateShares( + shareable: $calendar, + add: [['href' => 'principals/groups/alice_bob']], + remove: [], + ); + + $this->assertCount(2, $this->sharingService->getShares(10001)); + + /* + * Step 3) Unshare the calendar from user as owner. + */ + $this->sharingBackend->updateShares( + shareable: $calendar, + add: [], + remove: ['principals/users/bob'], + ); + + /* + * The purpose of this test is to ensure that removing a user from a share, as the owner, does not result in an "unshare" row being added. + * Instead, the actual user share should be removed. + */ + $this->assertCount(1, $this->sharingService->getShares(10001)); + $this->assertCount(0, $this->sharingService->getUnshares(10001)); + } + +} |