aboutsummaryrefslogtreecommitdiffstats
path: root/apps/dav/tests
diff options
context:
space:
mode:
authorAnna Larch <anna@nextcloud.com>2024-01-30 18:35:44 +0100
committerAnna Larch <anna@nextcloud.com>2024-02-15 18:01:12 +0100
commitdce69154ba335b610d70094f9daaded3b642f8cb (patch)
treea9ef54384367de8b48c30fb4babd798fc14533be /apps/dav/tests
parent1f0cba5f991a3c12d230284b3d96f91fb50312fd (diff)
downloadnextcloud-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.php109
-rw-r--r--apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php46
-rw-r--r--apps/dav/tests/unit/CalDAV/CalDavBackendTest.php31
-rw-r--r--apps/dav/tests/unit/CalDAV/CalendarTest.php4
-rw-r--r--apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php6
-rw-r--r--apps/dav/tests/unit/CardDAV/CardDavBackendTest.php49
-rw-r--r--apps/dav/tests/unit/DAV/Sharing/BackendTest.php427
-rw-r--r--apps/dav/tests/unit/DAV/Sharing/SharingServiceTest.php72
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));
+ }
+}