aboutsummaryrefslogtreecommitdiffstats
path: root/apps/dav/tests/unit/DAV
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dav/tests/unit/DAV')
-rw-r--r--apps/dav/tests/unit/DAV/AnonymousOptionsTest.php48
-rw-r--r--apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php46
-rw-r--r--apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php343
-rw-r--r--apps/dav/tests/unit/DAV/GroupPrincipalTest.php110
-rw-r--r--apps/dav/tests/unit/DAV/HookManagerTest.php250
-rw-r--r--apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php183
-rw-r--r--apps/dav/tests/unit/DAV/Sharing/BackendTest.php399
-rw-r--r--apps/dav/tests/unit/DAV/Sharing/PluginTest.php51
-rw-r--r--apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php84
-rw-r--r--apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php167
10 files changed, 1123 insertions, 558 deletions
diff --git a/apps/dav/tests/unit/DAV/AnonymousOptionsTest.php b/apps/dav/tests/unit/DAV/AnonymousOptionsTest.php
index 8c178ba8e44..c99ebf327c8 100644
--- a/apps/dav/tests/unit/DAV/AnonymousOptionsTest.php
+++ b/apps/dav/tests/unit/DAV/AnonymousOptionsTest.php
@@ -1,29 +1,11 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
- *
- * @author Bastien Durel <bastien@durel.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Robin Appelman <robin@icewind.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: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\tests\unit\DAV;
+namespace OCA\DAV\Tests\unit\DAV;
use OCA\DAV\Connector\Sabre\AnonymousOptionsPlugin;
use Sabre\DAV\Auth\Backend\BasicCallBack;
@@ -34,7 +16,7 @@ use Sabre\HTTP\Sapi;
use Test\TestCase;
class AnonymousOptionsTest extends TestCase {
- private function sendRequest($method, $path, $userAgent = '') {
+ private function sendRequest(string $method, string $path, string $userAgent = '') {
$server = new Server();
$server->addPlugin(new AnonymousOptionsPlugin());
$server->addPlugin(new Plugin(new BasicCallBack(function () {
@@ -50,49 +32,49 @@ class AnonymousOptionsTest extends TestCase {
return $server->httpResponse;
}
- public function testAnonymousOptionsRoot() {
+ public function testAnonymousOptionsRoot(): void {
$response = $this->sendRequest('OPTIONS', '');
$this->assertEquals(401, $response->getStatus());
}
- public function testAnonymousOptionsNonRoot() {
+ public function testAnonymousOptionsNonRoot(): void {
$response = $this->sendRequest('OPTIONS', 'foo');
$this->assertEquals(401, $response->getStatus());
}
- public function testAnonymousOptionsNonRootSubDir() {
+ public function testAnonymousOptionsNonRootSubDir(): void {
$response = $this->sendRequest('OPTIONS', 'foo/bar');
$this->assertEquals(401, $response->getStatus());
}
- public function testAnonymousOptionsRootOffice() {
+ public function testAnonymousOptionsRootOffice(): void {
$response = $this->sendRequest('OPTIONS', '', 'Microsoft Office does strange things');
$this->assertEquals(200, $response->getStatus());
}
- public function testAnonymousOptionsNonRootOffice() {
+ public function testAnonymousOptionsNonRootOffice(): void {
$response = $this->sendRequest('OPTIONS', 'foo', 'Microsoft Office does strange things');
$this->assertEquals(200, $response->getStatus());
}
- public function testAnonymousOptionsNonRootSubDirOffice() {
+ public function testAnonymousOptionsNonRootSubDirOffice(): void {
$response = $this->sendRequest('OPTIONS', 'foo/bar', 'Microsoft Office does strange things');
$this->assertEquals(200, $response->getStatus());
}
- public function testAnonymousHead() {
+ public function testAnonymousHead(): void {
$response = $this->sendRequest('HEAD', '', 'Microsoft Office does strange things');
$this->assertEquals(200, $response->getStatus());
}
- public function testAnonymousHeadNoOffice() {
+ public function testAnonymousHeadNoOffice(): void {
$response = $this->sendRequest('HEAD', '');
$this->assertEquals(401, $response->getStatus(), 'curl');
@@ -105,6 +87,6 @@ class SapiMock extends Sapi {
*
* @return void
*/
- public static function sendResponse(ResponseInterface $response) {
+ public static function sendResponse(ResponseInterface $response): void {
}
}
diff --git a/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php b/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php
index a0733a68550..0e82ef0a3ae 100644
--- a/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php
+++ b/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php
@@ -1,48 +1,30 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @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 OCA\DAV\Tests\unit\DAV;
use OCA\DAV\Files\BrowserErrorPagePlugin;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\NotFound;
use Sabre\HTTP\Response;
class BrowserErrorPagePluginTest extends \Test\TestCase {
- /**
- * @dataProvider providesExceptions
- * @param $expectedCode
- * @param $exception
- */
- public function test($expectedCode, $exception) {
- /** @var BrowserErrorPagePlugin | \PHPUnit\Framework\MockObject\MockObject $plugin */
- $plugin = $this->getMockBuilder(BrowserErrorPagePlugin::class)->setMethods(['sendResponse', 'generateBody'])->getMock();
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesExceptions')]
+ public function test(int $expectedCode, \Throwable $exception): void {
+ /** @var BrowserErrorPagePlugin&MockObject $plugin */
+ $plugin = $this->getMockBuilder(BrowserErrorPagePlugin::class)->onlyMethods(['sendResponse', 'generateBody'])->getMock();
$plugin->expects($this->once())->method('generateBody')->willReturn(':boom:');
$plugin->expects($this->once())->method('sendResponse');
- /** @var \Sabre\DAV\Server | \PHPUnit\Framework\MockObject\MockObject $server */
- $server = $this->getMockBuilder('Sabre\DAV\Server')->disableOriginalConstructor()->getMock();
+ /** @var \Sabre\DAV\Server&MockObject $server */
+ $server = $this->createMock('Sabre\DAV\Server');
$server->expects($this->once())->method('on');
- $httpResponse = $this->getMockBuilder(Response::class)->disableOriginalConstructor()->getMock();
+ $httpResponse = $this->createMock(Response::class);
$httpResponse->expects($this->once())->method('addHeaders');
$httpResponse->expects($this->once())->method('setStatus')->with($expectedCode);
$httpResponse->expects($this->once())->method('setBody')->with(':boom:');
@@ -51,7 +33,7 @@ class BrowserErrorPagePluginTest extends \Test\TestCase {
$plugin->logException($exception);
}
- public function providesExceptions() {
+ public static function providesExceptions(): array {
return [
[ 404, new NotFound()],
[ 500, new \RuntimeException()],
diff --git a/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php b/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php
index 2e7939aa614..2a85c0cbecd 100644
--- a/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php
+++ b/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php
@@ -1,71 +1,62 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2017, Georg Ehrke <oc.list@georgehrke.com>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.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 OCA\DAV\Tests\DAV;
+namespace OCA\DAV\Tests\unit\DAV;
+use OCA\DAV\CalDAV\Calendar;
+use OCA\DAV\CalDAV\DefaultCalendarValidator;
use OCA\DAV\DAV\CustomPropertiesBackend;
+use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\IUser;
+use PHPUnit\Framework\MockObject\MockObject;
+use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\PropFind;
use Sabre\DAV\PropPatch;
+use Sabre\DAV\Server;
use Sabre\DAV\Tree;
+use Sabre\DAV\Xml\Property\Href;
+use Sabre\DAVACL\IACL;
+use Sabre\DAVACL\IPrincipal;
use Test\TestCase;
/**
* @group DB
*/
class CustomPropertiesBackendTest extends TestCase {
+ private const BASE_URI = '/remote.php/dav/';
- /** @var Tree | \PHPUnit\Framework\MockObject\MockObject */
- private $tree;
-
- /** @var IDBConnection */
- private $dbConnection;
-
- /** @var IUser | \PHPUnit\Framework\MockObject\MockObject */
- private $user;
-
- /** @var CustomPropertiesBackend | \PHPUnit\Framework\MockObject\MockObject */
- private $backend;
+ private Server&MockObject $server;
+ private Tree&MockObject $tree;
+ private IDBConnection $dbConnection;
+ private IUser&MockObject $user;
+ private DefaultCalendarValidator&MockObject $defaultCalendarValidator;
+ private CustomPropertiesBackend $backend;
protected function setUp(): void {
parent::setUp();
+ $this->server = $this->createMock(Server::class);
+ $this->server->method('getBaseUri')
+ ->willReturn(self::BASE_URI);
$this->tree = $this->createMock(Tree::class);
$this->user = $this->createMock(IUser::class);
$this->user->method('getUID')
->with()
->willReturn('dummy_user_42');
- $this->dbConnection = \OC::$server->getDatabaseConnection();
+ $this->dbConnection = \OCP\Server::get(IDBConnection::class);
+ $this->defaultCalendarValidator = $this->createMock(DefaultCalendarValidator::class);
$this->backend = new CustomPropertiesBackend(
+ $this->server,
$this->tree,
$this->dbConnection,
- $this->user
+ $this->user,
+ $this->defaultCalendarValidator,
);
}
@@ -85,13 +76,19 @@ class CustomPropertiesBackendTest extends TestCase {
}
}
- protected function insertProps(string $user, string $path, array $props) {
+ protected function insertProps(string $user, string $path, array $props): void {
foreach ($props as $name => $value) {
$this->insertProp($user, $path, $name, $value);
}
}
- protected function insertProp(string $user, string $path, string $name, string $value) {
+ protected function insertProp(string $user, string $path, string $name, mixed $value): void {
+ $type = CustomPropertiesBackend::PROPERTY_TYPE_STRING;
+ if ($value instanceof Href) {
+ $value = $value->getHref();
+ $type = CustomPropertiesBackend::PROPERTY_TYPE_HREF;
+ }
+
$query = $this->dbConnection->getQueryBuilder();
$query->insert('properties')
->values([
@@ -99,37 +96,44 @@ class CustomPropertiesBackendTest extends TestCase {
'propertypath' => $query->createNamedParameter($this->formatPath($path)),
'propertyname' => $query->createNamedParameter($name),
'propertyvalue' => $query->createNamedParameter($value),
+ 'valuetype' => $query->createNamedParameter($type, IQueryBuilder::PARAM_INT)
]);
$query->execute();
}
- protected function getProps(string $user, string $path) {
+ protected function getProps(string $user, string $path): array {
$query = $this->dbConnection->getQueryBuilder();
- $query->select('propertyname', 'propertyvalue')
+ $query->select('propertyname', 'propertyvalue', 'valuetype')
->from('properties')
->where($query->expr()->eq('userid', $query->createNamedParameter($user)))
- ->where($query->expr()->eq('propertypath', $query->createNamedParameter($this->formatPath($path))));
+ ->andWhere($query->expr()->eq('propertypath', $query->createNamedParameter($this->formatPath($path))));
$result = $query->execute();
$data = [];
while ($row = $result->fetch()) {
- $data[$row['propertyname']] = $row['propertyvalue'];
+ $value = $row['propertyvalue'];
+ if ((int)$row['valuetype'] === CustomPropertiesBackend::PROPERTY_TYPE_HREF) {
+ $value = new Href($value);
+ }
+ $data[$row['propertyname']] = $value;
}
$result->closeCursor();
return $data;
}
- public function testPropFindNoDbCalls() {
+ public function testPropFindNoDbCalls(): void {
$db = $this->createMock(IDBConnection::class);
$backend = new CustomPropertiesBackend(
+ $this->server,
$this->tree,
$db,
- $this->user
+ $this->user,
+ $this->defaultCalendarValidator,
);
$propFind = $this->createMock(PropFind::class);
- $propFind->expects($this->at(0))
+ $propFind->expects($this->once())
->method('get404Properties')
->with()
->willReturn([
@@ -145,7 +149,7 @@ class CustomPropertiesBackendTest extends TestCase {
$backend->propFind('foo_bar_path_1337_0', $propFind);
}
- public function testPropFindCalendarCall() {
+ public function testPropFindCalendarCall(): void {
$propFind = $this->createMock(PropFind::class);
$propFind->method('get404Properties')
->with()
@@ -179,7 +183,7 @@ class CustomPropertiesBackendTest extends TestCase {
$setProps = [];
$propFind->method('set')
- ->willReturnCallback(function ($name, $value, $status) use (&$setProps) {
+ ->willReturnCallback(function ($name, $value, $status) use (&$setProps): void {
$setProps[$name] = $value;
});
@@ -187,10 +191,165 @@ class CustomPropertiesBackendTest extends TestCase {
$this->assertEquals($props, $setProps);
}
- /**
- * @dataProvider propPatchProvider
- */
- public function testPropPatch(string $path, array $existing, array $props, array $result) {
+ public function testPropFindPrincipalCall(): void {
+ $this->tree->method('getNodeForPath')
+ ->willReturnCallback(function ($uri) {
+ $node = $this->createMock(Calendar::class);
+ $node->method('getOwner')
+ ->willReturn('principals/users/dummy_user_42');
+ return $node;
+ });
+
+ $propFind = $this->createMock(PropFind::class);
+ $propFind->method('get404Properties')
+ ->with()
+ ->willReturn([
+ '{DAV:}getcontentlength',
+ '{DAV:}getcontenttype',
+ '{DAV:}getetag',
+ '{abc}def',
+ ]);
+
+ $propFind->method('getRequestedProperties')
+ ->with()
+ ->willReturn([
+ '{DAV:}getcontentlength',
+ '{DAV:}getcontenttype',
+ '{DAV:}getetag',
+ '{abc}def',
+ '{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL',
+ ]);
+
+ $props = [
+ '{abc}def' => 'a',
+ '{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('calendars/admin/personal'),
+ ];
+ $this->insertProps('dummy_user_42', 'principals/users/dummy_user_42', $props);
+
+ $setProps = [];
+ $propFind->method('set')
+ ->willReturnCallback(function ($name, $value, $status) use (&$setProps): void {
+ $setProps[$name] = $value;
+ });
+
+ $this->backend->propFind('principals/users/dummy_user_42', $propFind);
+ $this->assertEquals($props, $setProps);
+ }
+
+ public static function propFindPrincipalScheduleDefaultCalendarProviderUrlProvider(): array {
+ // [ user, nodes, existingProps, requestedProps, returnedProps ]
+ return [
+ [ // Exists
+ 'dummy_user_42',
+ ['calendars/dummy_user_42/foo/' => Calendar::class],
+ ['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('calendars/dummy_user_42/foo/')],
+ ['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL'],
+ ['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('calendars/dummy_user_42/foo/')],
+ ],
+ [ // Doesn't exist
+ 'dummy_user_42',
+ ['calendars/dummy_user_42/foo/' => Calendar::class],
+ ['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('calendars/dummy_user_42/bar/')],
+ ['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL'],
+ [],
+ ],
+ [ // No privilege
+ 'dummy_user_42',
+ ['calendars/user2/baz/' => Calendar::class],
+ ['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('calendars/user2/baz/')],
+ ['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL'],
+ [],
+ ],
+ [ // Not a calendar
+ 'dummy_user_42',
+ ['foo/dummy_user_42/bar/' => IACL::class],
+ ['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('foo/dummy_user_42/bar/')],
+ ['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL'],
+ [],
+ ],
+ ];
+
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('propFindPrincipalScheduleDefaultCalendarProviderUrlProvider')]
+ public function testPropFindPrincipalScheduleDefaultCalendarUrl(
+ string $user,
+ array $nodes,
+ array $existingProps,
+ array $requestedProps,
+ array $returnedProps,
+ ): void {
+ $propFind = $this->createMock(PropFind::class);
+ $propFind->method('get404Properties')
+ ->with()
+ ->willReturn([
+ '{DAV:}getcontentlength',
+ '{DAV:}getcontenttype',
+ '{DAV:}getetag',
+ ]);
+
+ $propFind->method('getRequestedProperties')
+ ->with()
+ ->willReturn(array_merge([
+ '{DAV:}getcontentlength',
+ '{DAV:}getcontenttype',
+ '{DAV:}getetag',
+ '{abc}def',
+ ],
+ $requestedProps,
+ ));
+
+ $this->server->method('calculateUri')
+ ->willReturnCallback(function ($uri) {
+ if (!str_starts_with($uri, self::BASE_URI)) {
+ return trim(substr($uri, strlen(self::BASE_URI)), '/');
+ }
+ return null;
+ });
+ $this->tree->method('getNodeForPath')
+ ->willReturnCallback(function ($uri) use ($nodes) {
+ if (str_starts_with($uri, 'principals/')) {
+ return $this->createMock(IPrincipal::class);
+ }
+ if (array_key_exists($uri, $nodes)) {
+ $owner = explode('/', $uri)[1];
+ $node = $this->createMock($nodes[$uri]);
+ $node->method('getOwner')
+ ->willReturn("principals/users/$owner");
+ return $node;
+ }
+ throw new NotFound('Node not found');
+ });
+
+ $this->insertProps($user, "principals/users/$user", $existingProps);
+
+ $setProps = [];
+ $propFind->method('set')
+ ->willReturnCallback(function ($name, $value, $status) use (&$setProps): void {
+ $setProps[$name] = $value;
+ });
+
+ $this->backend->propFind("principals/users/$user", $propFind);
+ $this->assertEquals($returnedProps, $setProps);
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('propPatchProvider')]
+ public function testPropPatch(string $path, array $existing, array $props, array $result): void {
+ $this->server->method('calculateUri')
+ ->willReturnCallback(function ($uri) {
+ if (str_starts_with($uri, self::BASE_URI)) {
+ return trim(substr($uri, strlen(self::BASE_URI)), '/');
+ }
+ return null;
+ });
+ $this->tree->method('getNodeForPath')
+ ->willReturnCallback(function ($uri) {
+ $node = $this->createMock(Calendar::class);
+ $node->method('getOwner')
+ ->willReturn('principals/users/' . $this->user->getUID());
+ return $node;
+ });
+
$this->insertProps($this->user->getUID(), $path, $existing);
$propPatch = new PropPatch($props);
@@ -201,46 +360,102 @@ class CustomPropertiesBackendTest extends TestCase {
$this->assertEquals($result, $storedProps);
}
- public function propPatchProvider() {
+ public static function propPatchProvider(): array {
$longPath = str_repeat('long_path', 100);
return [
['foo_bar_path_1337', [], ['{DAV:}displayname' => 'anything'], ['{DAV:}displayname' => 'anything']],
['foo_bar_path_1337', ['{DAV:}displayname' => 'foo'], ['{DAV:}displayname' => 'anything'], ['{DAV:}displayname' => 'anything']],
['foo_bar_path_1337', ['{DAV:}displayname' => 'foo'], ['{DAV:}displayname' => null], []],
[$longPath, [], ['{DAV:}displayname' => 'anything'], ['{DAV:}displayname' => 'anything']],
+ ['principals/users/dummy_user_42', [], ['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('foo/bar/')], ['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('foo/bar/')]],
+ ['principals/users/dummy_user_42', [], ['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href(self::BASE_URI . 'foo/bar/')], ['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('foo/bar/')]],
];
}
- /**
- * @dataProvider deleteProvider
- */
- public function testDelete(string $path) {
+ public function testPropPatchWithUnsuitableCalendar(): void {
+ $path = 'principals/users/' . $this->user->getUID();
+
+ $node = $this->createMock(Calendar::class);
+ $node->expects(self::once())
+ ->method('getOwner')
+ ->willReturn($path);
+
+ $this->defaultCalendarValidator->expects(self::once())
+ ->method('validateScheduleDefaultCalendar')
+ ->with($node)
+ ->willThrowException(new \Sabre\DAV\Exception('Invalid calendar'));
+
+ $this->server->method('calculateUri')
+ ->willReturnCallback(function ($uri) {
+ if (str_starts_with($uri, self::BASE_URI)) {
+ return trim(substr($uri, strlen(self::BASE_URI)), '/');
+ }
+ return null;
+ });
+ $this->tree->expects(self::once())
+ ->method('getNodeForPath')
+ ->with('foo/bar/')
+ ->willReturn($node);
+
+ $storedProps = $this->getProps($this->user->getUID(), $path);
+ $this->assertEquals([], $storedProps);
+
+ $propPatch = new PropPatch([
+ '{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('foo/bar/'),
+ ]);
+ $this->backend->propPatch($path, $propPatch);
+ try {
+ $propPatch->commit();
+ } catch (\Throwable $e) {
+ $this->assertInstanceOf(\Sabre\DAV\Exception::class, $e);
+ }
+
+ $storedProps = $this->getProps($this->user->getUID(), $path);
+ $this->assertEquals([], $storedProps);
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('deleteProvider')]
+ public function testDelete(string $path): void {
$this->insertProps('dummy_user_42', $path, ['foo' => 'bar']);
$this->backend->delete($path);
$this->assertEquals([], $this->getProps('dummy_user_42', $path));
}
- public function deleteProvider() {
+ public static function deleteProvider(): array {
return [
['foo_bar_path_1337'],
[str_repeat('long_path', 100)]
];
}
- /**
- * @dataProvider moveProvider
- */
- public function testMove(string $source, string $target) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('moveProvider')]
+ public function testMove(string $source, string $target): void {
$this->insertProps('dummy_user_42', $source, ['foo' => 'bar']);
$this->backend->move($source, $target);
$this->assertEquals([], $this->getProps('dummy_user_42', $source));
$this->assertEquals(['foo' => 'bar'], $this->getProps('dummy_user_42', $target));
}
- public function moveProvider() {
+ public static function moveProvider(): array {
return [
['foo_bar_path_1337', 'foo_bar_path_7333'],
[str_repeat('long_path1', 100), str_repeat('long_path2', 100)]
];
}
+
+ public function testDecodeValueFromDatabaseObjectCurrent(): void {
+ $propertyValue = 'O:48:"Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp":1:{s:8:"\x00*\x00value";s:6:"opaque";}';
+ $propertyType = 3;
+ $decodeValue = $this->invokePrivate($this->backend, 'decodeValueFromDatabase', [$propertyValue, $propertyType]);
+ $this->assertInstanceOf(\Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp::class, $decodeValue);
+ $this->assertEquals('opaque', $decodeValue->getValue());
+ }
+
+ public function testDecodeValueFromDatabaseObjectLegacy(): void {
+ $propertyValue = 'O:48:"Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp":1:{s:8:"' . chr(0) . '*' . chr(0) . 'value";s:6:"opaque";}';
+ $propertyType = 3;
+ $decodeValue = $this->invokePrivate($this->backend, 'decodeValueFromDatabase', [$propertyValue, $propertyType]);
+ $this->assertInstanceOf(\Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp::class, $decodeValue);
+ $this->assertEquals('opaque', $decodeValue->getValue());
+ }
}
diff --git a/apps/dav/tests/unit/DAV/GroupPrincipalTest.php b/apps/dav/tests/unit/DAV/GroupPrincipalTest.php
index 8f86961a6af..2756152a6e2 100644
--- a/apps/dav/tests/unit/DAV/GroupPrincipalTest.php
+++ b/apps/dav/tests/unit/DAV/GroupPrincipalTest.php
@@ -1,32 +1,10 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @copyright Copyright (c) 2018, Georg Ehrke
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Citharel <nextcloud@tcit.fr>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @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: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\DAV\Tests\unit\DAV;
@@ -42,20 +20,11 @@ use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\PropPatch;
class GroupPrincipalTest extends \Test\TestCase {
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var IGroupManager | MockObject */
- private $groupManager;
-
- /** @var IUserSession | MockObject */
- private $userSession;
-
- /** @var IManager | MockObject */
- private $shareManager;
-
- /** @var GroupPrincipalBackend */
- private $connector;
+ private IConfig&MockObject $config;
+ private IGroupManager&MockObject $groupManager;
+ private IUserSession&MockObject $userSession;
+ private IManager&MockObject $shareManager;
+ private GroupPrincipalBackend $connector;
protected function setUp(): void {
$this->groupManager = $this->createMock(IGroupManager::class);
@@ -72,12 +41,12 @@ class GroupPrincipalTest extends \Test\TestCase {
parent::setUp();
}
- public function testGetPrincipalsByPrefixWithoutPrefix() {
+ public function testGetPrincipalsByPrefixWithoutPrefix(): void {
$response = $this->connector->getPrincipalsByPrefix('');
$this->assertSame([], $response);
}
- public function testGetPrincipalsByPrefixWithUsers() {
+ public function testGetPrincipalsByPrefixWithUsers(): void {
$group1 = $this->mockGroup('foo');
$group2 = $this->mockGroup('bar');
$this->groupManager
@@ -102,7 +71,7 @@ class GroupPrincipalTest extends \Test\TestCase {
$this->assertSame($expectedResponse, $response);
}
- public function testGetPrincipalsByPrefixEmpty() {
+ public function testGetPrincipalsByPrefixEmpty(): void {
$this->groupManager
->expects($this->once())
->method('search')
@@ -113,7 +82,7 @@ class GroupPrincipalTest extends \Test\TestCase {
$this->assertSame([], $response);
}
- public function testGetPrincipalsByPathWithoutMail() {
+ public function testGetPrincipalsByPathWithoutMail(): void {
$group1 = $this->mockGroup('foo');
$this->groupManager
->expects($this->once())
@@ -130,7 +99,7 @@ class GroupPrincipalTest extends \Test\TestCase {
$this->assertSame($expectedResponse, $response);
}
- public function testGetPrincipalsByPathWithMail() {
+ public function testGetPrincipalsByPathWithMail(): void {
$fooUser = $this->mockGroup('foo');
$this->groupManager
->expects($this->once())
@@ -147,7 +116,7 @@ class GroupPrincipalTest extends \Test\TestCase {
$this->assertSame($expectedResponse, $response);
}
- public function testGetPrincipalsByPathEmpty() {
+ public function testGetPrincipalsByPathEmpty(): void {
$this->groupManager
->expects($this->once())
->method('get')
@@ -158,7 +127,7 @@ class GroupPrincipalTest extends \Test\TestCase {
$this->assertSame(null, $response);
}
- public function testGetPrincipalsByPathGroupWithSlash() {
+ public function testGetPrincipalsByPathGroupWithSlash(): void {
$group1 = $this->mockGroup('foo/bar');
$this->groupManager
->expects($this->once())
@@ -175,7 +144,7 @@ class GroupPrincipalTest extends \Test\TestCase {
$this->assertSame($expectedResponse, $response);
}
- public function testGetPrincipalsByPathGroupWithHash() {
+ public function testGetPrincipalsByPathGroupWithHash(): void {
$group1 = $this->mockGroup('foo#bar');
$this->groupManager
->expects($this->once())
@@ -192,45 +161,38 @@ class GroupPrincipalTest extends \Test\TestCase {
$this->assertSame($expectedResponse, $response);
}
- public function testGetGroupMemberSet() {
+ public function testGetGroupMemberSet(): void {
$response = $this->connector->getGroupMemberSet('principals/groups/foo');
$this->assertSame([], $response);
}
- public function testGetGroupMembership() {
+ public function testGetGroupMembership(): void {
$response = $this->connector->getGroupMembership('principals/groups/foo');
$this->assertSame([], $response);
}
- public function testSetGroupMembership() {
+ public function testSetGroupMembership(): void {
$this->expectException(\Sabre\DAV\Exception::class);
$this->expectExceptionMessage('Setting members of the group is not supported yet');
$this->connector->setGroupMemberSet('principals/groups/foo', ['foo']);
}
- public function testUpdatePrincipal() {
+ public function testUpdatePrincipal(): void {
$this->assertSame(0, $this->connector->updatePrincipal('foo', new PropPatch([])));
}
- public function testSearchPrincipalsWithEmptySearchProperties() {
+ public function testSearchPrincipalsWithEmptySearchProperties(): void {
$this->assertSame([], $this->connector->searchPrincipals('principals/groups', []));
}
- public function testSearchPrincipalsWithWrongPrefixPath() {
+ public function testSearchPrincipalsWithWrongPrefixPath(): void {
$this->assertSame([], $this->connector->searchPrincipals('principals/users',
['{DAV:}displayname' => 'Foo']));
}
- /**
- * @dataProvider searchPrincipalsDataProvider
- * @param bool $sharingEnabled
- * @param bool $groupSharingEnabled
- * @param bool $groupsOnly
- * @param string $test
- * @param array $result
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('searchPrincipalsDataProvider')]
public function testSearchPrincipals(bool $sharingEnabled, bool $groupSharingEnabled, bool $groupsOnly, string $test, array $result): void {
$this->shareManager->expects($this->once())
->method('shareAPIEnabled')
@@ -288,7 +250,7 @@ class GroupPrincipalTest extends \Test\TestCase {
['{DAV:}displayname' => 'Foo'], $test));
}
- public function searchPrincipalsDataProvider() {
+ public static function searchPrincipalsDataProvider(): array {
return [
[true, true, false, 'allof', ['principals/groups/group1', 'principals/groups/group2', 'principals/groups/group3', 'principals/groups/group4', 'principals/groups/group5']],
[true, true, false, 'anyof', ['principals/groups/group1', 'principals/groups/group2', 'principals/groups/group3', 'principals/groups/group4', 'principals/groups/group5']],
@@ -301,14 +263,7 @@ class GroupPrincipalTest extends \Test\TestCase {
];
}
- /**
- * @dataProvider findByUriDataProvider
- * @param bool $sharingEnabled
- * @param bool $groupSharingEnabled
- * @param bool $groupsOnly
- * @param string $findUri
- * @param string|null $result
- */
+ #[\PHPUnit\Framework\Attributes\DataProvider('findByUriDataProvider')]
public function testFindByUri(bool $sharingEnabled, bool $groupSharingEnabled, bool $groupsOnly, string $findUri, ?string $result): void {
$this->shareManager->expects($this->once())
->method('shareAPIEnabled')
@@ -329,7 +284,7 @@ class GroupPrincipalTest extends \Test\TestCase {
->method('getUser')
->willReturn($user);
- $this->groupManager->expects($this->at(0))
+ $this->groupManager->expects($this->once())
->method('getUserGroupIds')
->with($user)
->willReturn(['group1', 'group2', 'group5']);
@@ -344,7 +299,7 @@ class GroupPrincipalTest extends \Test\TestCase {
$this->assertEquals($result, $this->connector->findByUri($findUri, 'principals/groups'));
}
- public function findByUriDataProvider() {
+ public static function findByUriDataProvider(): array {
return [
[false, false, false, 'principal:principals/groups/group1', null],
[false, false, false, 'principal:principals/groups/group3', null],
@@ -361,10 +316,7 @@ class GroupPrincipalTest extends \Test\TestCase {
];
}
- /**
- * @return Group|MockObject
- */
- private function mockGroup($gid) {
+ private function mockGroup(string $gid): Group&MockObject {
$fooGroup = $this->createMock(Group::class);
$fooGroup
->expects($this->exactly(1))
@@ -373,7 +325,7 @@ class GroupPrincipalTest extends \Test\TestCase {
$fooGroup
->expects($this->exactly(1))
->method('getDisplayName')
- ->willReturn('Group '.$gid);
+ ->willReturn('Group ' . $gid);
return $fooGroup;
}
}
diff --git a/apps/dav/tests/unit/DAV/HookManagerTest.php b/apps/dav/tests/unit/DAV/HookManagerTest.php
deleted file mode 100644
index 503062c75db..00000000000
--- a/apps/dav/tests/unit/DAV/HookManagerTest.php
+++ /dev/null
@@ -1,250 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bjoern Schiessle <bjoern@schiessle.org>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Citharel <nextcloud@tcit.fr>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @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/>
- *
- */
-namespace OCA\DAV\Tests\unit\DAV;
-
-use OCA\DAV\CalDAV\CalDavBackend;
-use OCA\DAV\CardDAV\CardDavBackend;
-use OCA\DAV\CardDAV\SyncService;
-use OCA\DAV\HookManager;
-use OCP\Defaults;
-use OCP\IL10N;
-use OCP\IUser;
-use OCP\IUserManager;
-use PHPUnit\Framework\MockObject\MockObject;
-use Symfony\Component\EventDispatcher\EventDispatcherInterface;
-use Test\TestCase;
-
-class HookManagerTest extends TestCase {
- /** @var IL10N */
- private $l10n;
-
- /** @var EventDispatcherInterface | MockObject */
- private $eventDispatcher;
-
- protected function setUp(): void {
- parent::setUp();
- $this->eventDispatcher = $this->createMock(EventDispatcherInterface::class);
- $this->l10n = $this->createMock(IL10N::class);
- $this->l10n
- ->expects($this->any())
- ->method('t')
- ->willReturnCallback(function ($text, $parameters = []) {
- return vsprintf($text, $parameters);
- });
- }
-
- public function test() {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
- $user->expects($this->once())->method('getUID')->willReturn('newUser');
-
- /** @var IUserManager | MockObject $userManager */
- $userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var SyncService | MockObject $syncService */
- $syncService = $this->getMockBuilder(SyncService::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var Defaults | MockObject $syncService */
- $defaults = $this->getMockBuilder(Defaults::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $defaults->expects($this->once())->method('getColorPrimary')->willReturn('#745bca');
-
- /** @var CalDavBackend | MockObject $cal */
- $cal = $this->getMockBuilder(CalDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $cal->expects($this->once())->method('getCalendarsForUserCount')->willReturn(0);
- $cal->expects($this->once())->method('createCalendar')->with(
- 'principals/users/newUser',
- 'personal', [
- '{DAV:}displayname' => 'Personal',
- '{http://apple.com/ns/ical/}calendar-color' => '#745bca',
- 'components' => 'VEVENT'
- ]);
-
- /** @var CardDavBackend | MockObject $card */
- $card = $this->getMockBuilder(CardDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $card->expects($this->once())->method('getAddressBooksForUserCount')->willReturn(0);
- $card->expects($this->once())->method('createAddressBook')->with(
- 'principals/users/newUser',
- 'contacts', ['{DAV:}displayname' => 'Contacts']);
-
- $hm = new HookManager($userManager, $syncService, $cal, $card, $defaults, $this->eventDispatcher);
- $hm->firstLogin($user);
- }
-
- public function testWithExisting() {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
- $user->expects($this->once())->method('getUID')->willReturn('newUser');
-
- /** @var IUserManager | MockObject $userManager */
- $userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var SyncService | MockObject $syncService */
- $syncService = $this->getMockBuilder(SyncService::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var Defaults | MockObject $syncService */
- $defaults = $this->getMockBuilder(Defaults::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var CalDavBackend | MockObject $cal */
- $cal = $this->getMockBuilder(CalDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $cal->expects($this->once())->method('getCalendarsForUserCount')->willReturn(1);
- $cal->expects($this->never())->method('createCalendar');
-
- /** @var CardDavBackend | MockObject $card */
- $card = $this->getMockBuilder(CardDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $card->expects($this->once())->method('getAddressBooksForUserCount')->willReturn(1);
- $card->expects($this->never())->method('createAddressBook');
-
- $hm = new HookManager($userManager, $syncService, $cal, $card, $defaults, $this->eventDispatcher);
- $hm->firstLogin($user);
- }
-
- public function testWithBirthdayCalendar() {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
- $user->expects($this->once())->method('getUID')->willReturn('newUser');
-
- /** @var IUserManager | MockObject $userManager */
- $userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var SyncService | MockObject $syncService */
- $syncService = $this->getMockBuilder(SyncService::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var Defaults | MockObject $syncService */
- $defaults = $this->getMockBuilder(Defaults::class)
- ->disableOriginalConstructor()
- ->getMock();
- $defaults->expects($this->once())->method('getColorPrimary')->willReturn('#745bca');
-
- /** @var CalDavBackend | MockObject $cal */
- $cal = $this->getMockBuilder(CalDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $cal->expects($this->once())->method('getCalendarsForUserCount')->willReturn(0);
- $cal->expects($this->once())->method('createCalendar')->with(
- 'principals/users/newUser',
- 'personal', [
- '{DAV:}displayname' => 'Personal',
- '{http://apple.com/ns/ical/}calendar-color' => '#745bca',
- 'components' => 'VEVENT'
- ]);
-
- /** @var CardDavBackend | MockObject $card */
- $card = $this->getMockBuilder(CardDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $card->expects($this->once())->method('getAddressBooksForUserCount')->willReturn(0);
- $card->expects($this->once())->method('createAddressBook')->with(
- 'principals/users/newUser',
- 'contacts', ['{DAV:}displayname' => 'Contacts']);
-
- $hm = new HookManager($userManager, $syncService, $cal, $card, $defaults, $this->eventDispatcher);
- $hm->firstLogin($user);
- }
-
- public function testDeleteCalendar() {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var IUserManager | MockObject $userManager */
- $userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $userManager->expects($this->once())->method('get')->willReturn($user);
-
- /** @var SyncService | MockObject $syncService */
- $syncService = $this->getMockBuilder(SyncService::class)
- ->disableOriginalConstructor()
- ->getMock();
- $syncService->expects($this->once())
- ->method('deleteUser');
-
- /** @var Defaults | MockObject $syncService */
- $defaults = $this->getMockBuilder(Defaults::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- /** @var CalDavBackend | MockObject $cal */
- $cal = $this->getMockBuilder(CalDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $cal->expects($this->once())->method('getUsersOwnCalendars')->willReturn([
- ['id' => 'personal']
- ]);
- $cal->expects($this->once())->method('getSubscriptionsForUser')->willReturn([
- ['id' => 'some-subscription']
- ]);
- $cal->expects($this->once())->method('deleteCalendar')->with('personal');
- $cal->expects($this->once())->method('deleteSubscription')->with('some-subscription');
- $cal->expects($this->once())->method('deleteAllSharesByUser');
-
- /** @var CardDavBackend | MockObject $card */
- $card = $this->getMockBuilder(CardDavBackend::class)
- ->disableOriginalConstructor()
- ->getMock();
- $card->expects($this->once())->method('getUsersOwnAddressBooks')->willReturn([
- ['id' => 'personal']
- ]);
- $card->expects($this->once())->method('deleteAddressBook');
-
- $hm = new HookManager($userManager, $syncService, $cal, $card, $defaults, $this->eventDispatcher);
- $hm->preDeleteUser(['uid' => 'newUser']);
- $hm->postDeleteUser(['uid' => 'newUser']);
- }
-}
diff --git a/apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php b/apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php
new file mode 100644
index 00000000000..8e410eb0a78
--- /dev/null
+++ b/apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php
@@ -0,0 +1,183 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+namespace OCA\DAV\Tests\unit\DAV\Listener;
+
+use OCA\DAV\BackgroundJob\UserStatusAutomation;
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CardDAV\CardDavBackend;
+use OCA\DAV\CardDAV\SyncService;
+use OCA\DAV\Listener\UserEventsListener;
+use OCA\DAV\Service\ExampleContactService;
+use OCA\DAV\Service\ExampleEventService;
+use OCP\BackgroundJob\IJobList;
+use OCP\Defaults;
+use OCP\IUser;
+use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
+use Test\TestCase;
+
+class UserEventsListenerTest extends TestCase {
+ private IUserManager&MockObject $userManager;
+ private SyncService&MockObject $syncService;
+ private CalDavBackend&MockObject $calDavBackend;
+ private CardDavBackend&MockObject $cardDavBackend;
+ private Defaults&MockObject $defaults;
+ private ExampleContactService&MockObject $exampleContactService;
+ private ExampleEventService&MockObject $exampleEventService;
+ private LoggerInterface&MockObject $logger;
+
+ private UserEventsListener $userEventsListener;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->syncService = $this->createMock(SyncService::class);
+ $this->calDavBackend = $this->createMock(CalDavBackend::class);
+ $this->cardDavBackend = $this->createMock(CardDavBackend::class);
+ $this->defaults = $this->createMock(Defaults::class);
+ $this->exampleContactService = $this->createMock(ExampleContactService::class);
+ $this->exampleEventService = $this->createMock(ExampleEventService::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+ $this->jobList = $this->createMock(IJobList::class);
+
+ $this->userEventsListener = new UserEventsListener(
+ $this->userManager,
+ $this->syncService,
+ $this->calDavBackend,
+ $this->cardDavBackend,
+ $this->defaults,
+ $this->exampleContactService,
+ $this->exampleEventService,
+ $this->logger,
+ $this->jobList,
+ );
+ }
+
+ public function test(): void {
+ $user = $this->createMock(IUser::class);
+ $user->expects($this->once())->method('getUID')->willReturn('newUser');
+
+ $this->defaults->expects($this->once())->method('getColorPrimary')->willReturn('#745bca');
+
+ $this->calDavBackend->expects($this->once())->method('getCalendarsForUserCount')->willReturn(0);
+ $this->calDavBackend->expects($this->once())->method('createCalendar')->with(
+ 'principals/users/newUser',
+ 'personal', [
+ '{DAV:}displayname' => 'Personal',
+ '{http://apple.com/ns/ical/}calendar-color' => '#745bca',
+ 'components' => 'VEVENT'
+ ])
+ ->willReturn(1000);
+ $this->calDavBackend->expects(self::never())
+ ->method('getCalendarsForUser');
+ $this->exampleEventService->expects(self::once())
+ ->method('createExampleEvent')
+ ->with(1000);
+
+ $this->cardDavBackend->expects($this->once())->method('getAddressBooksForUserCount')->willReturn(0);
+ $this->cardDavBackend->expects($this->once())->method('createAddressBook')->with(
+ 'principals/users/newUser',
+ 'contacts', ['{DAV:}displayname' => 'Contacts']);
+
+ $this->userEventsListener->firstLogin($user);
+ }
+
+ public function testWithExisting(): void {
+ $user = $this->createMock(IUser::class);
+ $user->expects($this->once())->method('getUID')->willReturn('newUser');
+
+ $this->calDavBackend->expects($this->once())->method('getCalendarsForUserCount')->willReturn(1);
+ $this->calDavBackend->expects($this->never())->method('createCalendar');
+ $this->calDavBackend->expects(self::never())
+ ->method('createCalendar');
+ $this->exampleEventService->expects(self::never())
+ ->method('createExampleEvent');
+
+ $this->cardDavBackend->expects($this->once())->method('getAddressBooksForUserCount')->willReturn(1);
+ $this->cardDavBackend->expects($this->never())->method('createAddressBook');
+
+ $this->userEventsListener->firstLogin($user);
+ }
+
+ public function testWithBirthdayCalendar(): void {
+ $user = $this->createMock(IUser::class);
+ $user->expects($this->once())->method('getUID')->willReturn('newUser');
+
+ $this->defaults->expects($this->once())->method('getColorPrimary')->willReturn('#745bca');
+
+ $this->calDavBackend->expects($this->once())->method('getCalendarsForUserCount')->willReturn(0);
+ $this->calDavBackend->expects($this->once())->method('createCalendar')->with(
+ 'principals/users/newUser',
+ 'personal', [
+ '{DAV:}displayname' => 'Personal',
+ '{http://apple.com/ns/ical/}calendar-color' => '#745bca',
+ 'components' => 'VEVENT'
+ ]);
+
+ $this->cardDavBackend->expects($this->once())->method('getAddressBooksForUserCount')->willReturn(0);
+ $this->cardDavBackend->expects($this->once())->method('createAddressBook')->with(
+ 'principals/users/newUser',
+ 'contacts', ['{DAV:}displayname' => 'Contacts']);
+
+ $this->userEventsListener->firstLogin($user);
+ }
+
+ public function testDeleteCalendar(): void {
+ $user = $this->createMock(IUser::class);
+ $user->expects($this->once())->method('getUID')->willReturn('newUser');
+
+ $this->syncService->expects($this->once())
+ ->method('deleteUser');
+
+ $this->calDavBackend->expects($this->once())->method('getUsersOwnCalendars')->willReturn([
+ ['id' => 'personal']
+ ]);
+ $this->calDavBackend->expects($this->once())->method('getSubscriptionsForUser')->willReturn([
+ ['id' => 'some-subscription']
+ ]);
+ $this->calDavBackend->expects($this->once())->method('deleteCalendar')->with('personal');
+ $this->calDavBackend->expects($this->once())->method('deleteSubscription')->with('some-subscription');
+ $this->calDavBackend->expects($this->once())->method('deleteAllSharesByUser');
+
+ $this->cardDavBackend->expects($this->once())->method('getUsersOwnAddressBooks')->willReturn([
+ ['id' => 'personal']
+ ]);
+ $this->cardDavBackend->expects($this->once())->method('deleteAddressBook');
+
+ $this->userEventsListener->preDeleteUser($user);
+ $this->userEventsListener->postDeleteUser('newUser');
+ }
+
+ public function testDeleteUserAutomationEvent(): void {
+ $user = $this->createMock(IUser::class);
+ $user->expects($this->once())->method('getUID')->willReturn('newUser');
+
+ $this->syncService->expects($this->once())
+ ->method('deleteUser');
+
+ $this->calDavBackend->expects($this->once())->method('getUsersOwnCalendars')->willReturn([
+ ['id' => []]
+ ]);
+ $this->calDavBackend->expects($this->once())->method('getSubscriptionsForUser')->willReturn([
+ ['id' => []]
+ ]);
+ $this->cardDavBackend->expects($this->once())->method('getUsersOwnAddressBooks')->willReturn([
+ ['id' => []]
+ ]);
+
+ $this->jobList->expects(self::once())->method('remove')->with(UserStatusAutomation::class, ['userId' => 'newUser']);
+
+ $this->userEventsListener->preDeleteUser($user);
+ $this->userEventsListener->postDeleteUser('newUser');
+ }
+}
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..556a623a73f
--- /dev/null
+++ b/apps/dav/tests/unit/DAV/Sharing/BackendTest.php
@@ -0,0 +1,399 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+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 Principal&MockObject $principalBackend;
+ private ICache&MockObject $shareCache;
+ private LoggerInterface&MockObject $logger;
+ private ICacheFactory&MockObject $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 = [
+ 'principal:principals/users/bob',
+ ];
+ $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::never())
+ ->method('unshare');
+
+ $this->backend->updateShares($shareable, [], $remove);
+ }
+
+ public function testUnshareWithBobGroup(): void {
+ $shareable = $this->createConfiguredMock(IShareable::class, [
+ 'getOwner' => 'principals/users/alice',
+ 'getResourceId' => 42,
+ ]);
+ $remove = [
+ 'principal:principals/users/bob',
+ ];
+ $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::never())
+ ->method('unshare');
+
+ $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/PluginTest.php b/apps/dav/tests/unit/DAV/Sharing/PluginTest.php
index 1c4bb5e12e4..7a88f7cc5dd 100644
--- a/apps/dav/tests/unit/DAV/Sharing/PluginTest.php
+++ b/apps/dav/tests/unit/DAV/Sharing/PluginTest.php
@@ -1,28 +1,10 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Georg Ehrke <oc.list@georgehrke.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @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 OCA\DAV\Tests\unit\DAV\Sharing;
@@ -31,6 +13,7 @@ use OCA\DAV\DAV\Sharing\IShareable;
use OCA\DAV\DAV\Sharing\Plugin;
use OCP\IConfig;
use OCP\IRequest;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Server;
use Sabre\DAV\SimpleCollection;
use Sabre\HTTP\Request;
@@ -38,38 +21,30 @@ use Sabre\HTTP\Response;
use Test\TestCase;
class PluginTest extends TestCase {
-
- /** @var Plugin */
- private $plugin;
- /** @var Server */
- private $server;
- /** @var IShareable | \PHPUnit\Framework\MockObject\MockObject */
- private $book;
+ private Plugin $plugin;
+ private Server $server;
+ private IShareable&MockObject $book;
protected function setUp(): void {
parent::setUp();
- /** @var Auth | \PHPUnit\Framework\MockObject\MockObject $authBackend */
- $authBackend = $this->getMockBuilder(Auth::class)->disableOriginalConstructor()->getMock();
+ $authBackend = $this->createMock(Auth::class);
$authBackend->method('isDavAuthenticated')->willReturn(true);
- /** @var IRequest $request */
- $request = $this->getMockBuilder(IRequest::class)->disableOriginalConstructor()->getMock();
+ $request = $this->createMock(IRequest::class);
$config = $this->createMock(IConfig::class);
$this->plugin = new Plugin($authBackend, $request, $config);
$root = new SimpleCollection('root');
$this->server = new \Sabre\DAV\Server($root);
/** @var SimpleCollection $node */
- $this->book = $this->getMockBuilder(IShareable::class)->
- disableOriginalConstructor()->
- getMock();
+ $this->book = $this->createMock(IShareable::class);
$this->book->method('getName')->willReturn('addressbook1.vcf');
$root->addChild($this->book);
$this->plugin->initialize($this->server);
}
- public function testSharing() {
+ public function testSharing(): void {
$this->book->expects($this->once())->method('updateShares')->with([[
'href' => 'principal:principals/admin',
'commonName' => null,
diff --git a/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php b/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php
index 05e6699cc4c..3df861accf2 100644
--- a/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php
+++ b/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php
@@ -1,47 +1,27 @@
<?php
+
+declare(strict_types=1);
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Citharel <nextcloud@tcit.fr>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @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 OCA\DAV\Tests\unit\DAV;
use OCA\DAV\DAV\SystemPrincipalBackend;
+use Sabre\DAV\Exception;
use Test\TestCase;
class SystemPrincipalBackendTest extends TestCase {
- /**
- * @dataProvider providesPrefix
- * @param $expected
- * @param $prefix
- */
- public function testGetPrincipalsByPrefix($expected, $prefix) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesPrefix')]
+ public function testGetPrincipalsByPrefix(array $expected, string $prefix): void {
$backend = new SystemPrincipalBackend();
$result = $backend->getPrincipalsByPrefix($prefix);
$this->assertEquals($expected, $result);
}
- public function providesPrefix() {
+ public static function providesPrefix(): array {
return [
[[], ''],
[[[
@@ -56,18 +36,14 @@ class SystemPrincipalBackendTest extends TestCase {
];
}
- /**
- * @dataProvider providesPath
- * @param $expected
- * @param $path
- */
- public function testGetPrincipalByPath($expected, $path) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesPath')]
+ public function testGetPrincipalByPath(?array $expected, string $path): void {
$backend = new SystemPrincipalBackend();
$result = $backend->getPrincipalByPath($path);
$this->assertEquals($expected, $result);
}
- public function providesPath() {
+ public static function providesPath(): array {
return [
[null, ''],
[null, 'principals'],
@@ -79,60 +55,44 @@ class SystemPrincipalBackendTest extends TestCase {
];
}
- /**
- * @dataProvider providesPrincipalForGetGroupMemberSet
- *
- * @param string $principal
- * @throws \Sabre\DAV\Exception
- */
- public function testGetGroupMemberSetExceptional($principal) {
- $this->expectException(\Sabre\DAV\Exception::class);
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesPrincipalForGetGroupMemberSet')]
+ public function testGetGroupMemberSetExceptional(?string $principal): void {
+ $this->expectException(Exception::class);
$this->expectExceptionMessage('Principal not found');
$backend = new SystemPrincipalBackend();
$backend->getGroupMemberSet($principal);
}
- public function providesPrincipalForGetGroupMemberSet() {
+ public static function providesPrincipalForGetGroupMemberSet(): array {
return [
[null],
['principals/system'],
];
}
- /**
- * @throws \Sabre\DAV\Exception
- */
- public function testGetGroupMemberSet() {
+ public function testGetGroupMemberSet(): void {
$backend = new SystemPrincipalBackend();
$result = $backend->getGroupMemberSet('principals/system/system');
$this->assertEquals(['principals/system/system'], $result);
}
- /**
- * @dataProvider providesPrincipalForGetGroupMembership
- *
- * @param string $principal
- * @throws \Sabre\DAV\Exception
- */
- public function testGetGroupMembershipExceptional($principal) {
- $this->expectException(\Sabre\DAV\Exception::class);
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesPrincipalForGetGroupMembership')]
+ public function testGetGroupMembershipExceptional(string $principal): void {
+ $this->expectException(Exception::class);
$this->expectExceptionMessage('Principal not found');
$backend = new SystemPrincipalBackend();
$backend->getGroupMembership($principal);
}
- public function providesPrincipalForGetGroupMembership() {
+ public static function providesPrincipalForGetGroupMembership(): array {
return [
['principals/system/a'],
];
}
- /**
- * @throws \Sabre\DAV\Exception
- */
- public function testGetGroupMembership() {
+ public function testGetGroupMembership(): void {
$backend = new SystemPrincipalBackend();
$result = $backend->getGroupMembership('principals/system/system');
$this->assertEquals([], $result);
diff --git a/apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php b/apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php
new file mode 100644
index 00000000000..eefbc53fd22
--- /dev/null
+++ b/apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php
@@ -0,0 +1,167 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2019 ownCloud GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+namespace OCA\DAV\Tests\unit\DAV;
+
+use OCA\DAV\Connector\Sabre\Exception\Forbidden;
+use OCA\DAV\Connector\Sabre\File as DavFile;
+use OCA\DAV\DAV\ViewOnlyPlugin;
+use OCA\Files_Sharing\SharedStorage;
+use OCA\Files_Versions\Sabre\VersionFile;
+use OCA\Files_Versions\Versions\IVersion;
+use OCP\Files\File;
+use OCP\Files\Folder;
+use OCP\Files\Storage\ISharedStorage;
+use OCP\Files\Storage\IStorage;
+use OCP\IUser;
+use OCP\Share\IAttributes;
+use OCP\Share\IShare;
+use PHPUnit\Framework\MockObject\MockObject;
+use Sabre\DAV\Server;
+use Sabre\DAV\Tree;
+use Sabre\HTTP\RequestInterface;
+use Test\TestCase;
+
+class ViewOnlyPluginTest extends TestCase {
+ private Tree&MockObject $tree;
+ private RequestInterface&MockObject $request;
+ private Folder&MockObject $userFolder;
+ private ViewOnlyPlugin $plugin;
+
+ public function setUp(): void {
+ parent::setUp();
+
+ $this->userFolder = $this->createMock(Folder::class);
+ $this->request = $this->createMock(RequestInterface::class);
+ $this->tree = $this->createMock(Tree::class);
+ $server = $this->createMock(Server::class);
+
+ $this->plugin = new ViewOnlyPlugin(
+ $this->userFolder,
+ );
+ $server->tree = $this->tree;
+
+ $this->plugin->initialize($server);
+ }
+
+ public function testCanGetNonDav(): void {
+ $this->request->expects($this->once())->method('getPath')->willReturn('files/test/target');
+ $this->tree->method('getNodeForPath')->willReturn(null);
+
+ $this->assertTrue($this->plugin->checkViewOnly($this->request));
+ }
+
+ public function testCanGetNonShared(): void {
+ $this->request->expects($this->once())->method('getPath')->willReturn('files/test/target');
+ $davNode = $this->createMock(DavFile::class);
+ $this->tree->method('getNodeForPath')->willReturn($davNode);
+
+ $file = $this->createMock(File::class);
+ $davNode->method('getNode')->willReturn($file);
+
+ $storage = $this->createMock(IStorage::class);
+ $file->method('getStorage')->willReturn($storage);
+ $storage->method('instanceOfStorage')->with(ISharedStorage::class)->willReturn(false);
+
+ $this->assertTrue($this->plugin->checkViewOnly($this->request));
+ }
+
+ public static function providesDataForCanGet(): array {
+ return [
+ // has attribute permissions-download enabled - can get file
+ [false, true, true, true],
+ // has no attribute permissions-download - can get file
+ [false, null, true, true],
+ // has attribute permissions-download enabled - can get file version
+ [true, true, true, true],
+ // has no attribute permissions-download - can get file version
+ [true, null, true, true],
+ // has attribute permissions-download disabled - cannot get the file
+ [false, false, false, false],
+ // has attribute permissions-download disabled - cannot get the file version
+ [true, false, false, false],
+
+ // Has global allowViewWithoutDownload option enabled
+ // has attribute permissions-download disabled - can get file
+ [false, false, false, true],
+ // has attribute permissions-download disabled - can get file version
+ [true, false, false, true],
+ ];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('providesDataForCanGet')]
+ public function testCanGet(bool $isVersion, ?bool $attrEnabled, bool $expectCanDownloadFile, bool $allowViewWithoutDownload): void {
+ $nodeInfo = $this->createMock(File::class);
+ if ($isVersion) {
+ $davPath = 'versions/alice/versions/117/123456';
+ $version = $this->createMock(IVersion::class);
+ $version->expects($this->once())
+ ->method('getSourceFile')
+ ->willReturn($nodeInfo);
+ $davNode = $this->createMock(VersionFile::class);
+ $davNode->expects($this->once())
+ ->method('getVersion')
+ ->willReturn($version);
+
+ $currentUser = $this->createMock(IUser::class);
+ $currentUser->expects($this->once())
+ ->method('getUID')
+ ->willReturn('alice');
+ $nodeInfo->expects($this->once())
+ ->method('getOwner')
+ ->willReturn($currentUser);
+
+ $nodeInfo = $this->createMock(File::class);
+ $owner = $this->createMock(IUser::class);
+ $owner->expects($this->once())
+ ->method('getUID')
+ ->willReturn('bob');
+ $this->userFolder->expects($this->once())
+ ->method('getById')
+ ->willReturn([$nodeInfo]);
+ $this->userFolder->expects($this->once())
+ ->method('getOwner')
+ ->willReturn($owner);
+ } else {
+ $davPath = 'files/path/to/file.odt';
+ $davNode = $this->createMock(DavFile::class);
+ $davNode->method('getNode')->willReturn($nodeInfo);
+ }
+
+ $this->request->expects($this->once())->method('getPath')->willReturn($davPath);
+
+ $this->tree->expects($this->once())
+ ->method('getNodeForPath')
+ ->with($davPath)
+ ->willReturn($davNode);
+
+ $storage = $this->createMock(SharedStorage::class);
+ $share = $this->createMock(IShare::class);
+ $nodeInfo->expects($this->once())
+ ->method('getStorage')
+ ->willReturn($storage);
+ $storage->method('instanceOfStorage')->with(ISharedStorage::class)->willReturn(true);
+ $storage->method('getShare')->willReturn($share);
+
+ $extAttr = $this->createMock(IAttributes::class);
+ $share->method('getAttributes')->willReturn($extAttr);
+ $extAttr->expects($this->once())
+ ->method('getAttribute')
+ ->with('permissions', 'download')
+ ->willReturn($attrEnabled);
+
+ $share->expects($this->once())
+ ->method('canSeeContent')
+ ->willReturn($allowViewWithoutDownload);
+
+ if (!$expectCanDownloadFile) {
+ $this->expectException(Forbidden::class);
+ }
+ $this->plugin->checkViewOnly($this->request);
+ }
+}