diff options
author | Anna <anna@nextcloud.com> | 2024-10-02 10:35:44 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-02 10:35:44 +0200 |
commit | e333bc3c8f67c6bb685f36bdad386cbfad49474d (patch) | |
tree | bd6ce5185d789faff656f0a51e1dd9a3a9608b22 /apps/dav | |
parent | 06bfb20f2aa38e24e50b3c09808b089487a3be23 (diff) | |
parent | 6468ec5716419f094586f9bc19684679530277c6 (diff) | |
download | nextcloud-server-e333bc3c8f67c6bb685f36bdad386cbfad49474d.tar.gz nextcloud-server-e333bc3c8f67c6bb685f36bdad386cbfad49474d.zip |
Merge pull request #47788 from nextcloud/feat/add-addressbook-list-command
feat(carddav): add command to list address books
Diffstat (limited to 'apps/dav')
-rw-r--r-- | apps/dav/appinfo/info.xml | 1 | ||||
-rw-r--r-- | apps/dav/composer/composer/autoload_classmap.php | 1 | ||||
-rw-r--r-- | apps/dav/composer/composer/autoload_static.php | 1 | ||||
-rw-r--r-- | apps/dav/lib/Command/ListAddressbooks.php | 76 | ||||
-rw-r--r-- | apps/dav/lib/Command/ListCalendars.php | 2 | ||||
-rw-r--r-- | apps/dav/tests/unit/Command/ListAddressbooksTest.php | 110 |
6 files changed, 190 insertions, 1 deletions
diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index 7c6b02a35d4..6f5a085ef05 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -53,6 +53,7 @@ <commands> <command>OCA\DAV\Command\CreateAddressBook</command> + <command>OCA\DAV\Command\ListAddressbooks</command> <command>OCA\DAV\Command\CreateCalendar</command> <command>OCA\DAV\Command\CreateSubscription</command> <command>OCA\DAV\Command\DeleteCalendar</command> diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index 2045c5e1fac..2e878decb3f 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -156,6 +156,7 @@ return array( 'OCA\\DAV\\Command\\CreateSubscription' => $baseDir . '/../lib/Command/CreateSubscription.php', 'OCA\\DAV\\Command\\DeleteCalendar' => $baseDir . '/../lib/Command/DeleteCalendar.php', 'OCA\\DAV\\Command\\FixCalendarSyncCommand' => $baseDir . '/../lib/Command/FixCalendarSyncCommand.php', + 'OCA\\DAV\\Command\\ListAddressbooks' => $baseDir . '/../lib/Command/ListAddressbooks.php', 'OCA\\DAV\\Command\\ListCalendars' => $baseDir . '/../lib/Command/ListCalendars.php', 'OCA\\DAV\\Command\\MoveCalendar' => $baseDir . '/../lib/Command/MoveCalendar.php', 'OCA\\DAV\\Command\\RemoveInvalidShares' => $baseDir . '/../lib/Command/RemoveInvalidShares.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index 31f0974e8e3..5f43453cda6 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -171,6 +171,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\Command\\CreateSubscription' => __DIR__ . '/..' . '/../lib/Command/CreateSubscription.php', 'OCA\\DAV\\Command\\DeleteCalendar' => __DIR__ . '/..' . '/../lib/Command/DeleteCalendar.php', 'OCA\\DAV\\Command\\FixCalendarSyncCommand' => __DIR__ . '/..' . '/../lib/Command/FixCalendarSyncCommand.php', + 'OCA\\DAV\\Command\\ListAddressbooks' => __DIR__ . '/..' . '/../lib/Command/ListAddressbooks.php', 'OCA\\DAV\\Command\\ListCalendars' => __DIR__ . '/..' . '/../lib/Command/ListCalendars.php', 'OCA\\DAV\\Command\\MoveCalendar' => __DIR__ . '/..' . '/../lib/Command/MoveCalendar.php', 'OCA\\DAV\\Command\\RemoveInvalidShares' => __DIR__ . '/..' . '/../lib/Command/RemoveInvalidShares.php', diff --git a/apps/dav/lib/Command/ListAddressbooks.php b/apps/dav/lib/Command/ListAddressbooks.php new file mode 100644 index 00000000000..c0b6e63ccb8 --- /dev/null +++ b/apps/dav/lib/Command/ListAddressbooks.php @@ -0,0 +1,76 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\DAV\Command; + +use OCA\DAV\CardDAV\CardDavBackend; +use OCA\DAV\CardDAV\SystemAddressbook; +use OCP\IUserManager; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class ListAddressbooks extends Command { + public function __construct( + protected IUserManager $userManager, + private CardDavBackend $cardDavBackend, + ) { + parent::__construct('dav:list-addressbooks'); + } + + protected function configure(): void { + $this + ->setDescription('List all addressbooks of a user') + ->addArgument('uid', + InputArgument::REQUIRED, + 'User for whom all addressbooks will be listed'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $user = $input->getArgument('uid'); + if (!$this->userManager->userExists($user)) { + throw new \InvalidArgumentException("User <$user> is unknown."); + } + + $addressBooks = $this->cardDavBackend->getAddressBooksForUser("principals/users/$user"); + + $addressBookTableData = []; + foreach ($addressBooks as $book) { + // skip system / contacts integration address book + if ($book['uri'] === SystemAddressbook::URI_SHARED) { + continue; + } + + $readOnly = false; + $readOnlyIndex = '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}read-only'; + if (isset($book[$readOnlyIndex])) { + $readOnly = $book[$readOnlyIndex]; + } + + $addressBookTableData[] = [ + $book['uri'], + $book['{DAV:}displayname'], + $book['{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal'] ?? $book['principaluri'], + $book['{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}owner-displayname'], + $readOnly ? ' x ' : ' ✓ ', + ]; + } + + if (count($addressBookTableData) > 0) { + $table = new Table($output); + $table->setHeaders(['Database ID', 'URI', 'Displayname', 'Owner principal', 'Owner displayname', 'Writable']) + ->setRows($addressBookTableData); + + $table->render(); + } else { + $output->writeln("<info>User <$user> has no addressbooks</info>"); + } + return self::SUCCESS; + } +} diff --git a/apps/dav/lib/Command/ListCalendars.php b/apps/dav/lib/Command/ListCalendars.php index 5344530e8a5..06a1f7397c4 100644 --- a/apps/dav/lib/Command/ListCalendars.php +++ b/apps/dav/lib/Command/ListCalendars.php @@ -63,7 +63,7 @@ class ListCalendars extends Command { if (count($calendarTableData) > 0) { $table = new Table($output); - $table->setHeaders(['uri', 'displayname', 'owner\'s userid', 'owner\'s displayname', 'writable']) + $table->setHeaders(['URI', 'Displayname', 'Owner principal', 'Owner displayname', 'Writable']) ->setRows($calendarTableData); $table->render(); diff --git a/apps/dav/tests/unit/Command/ListAddressbooksTest.php b/apps/dav/tests/unit/Command/ListAddressbooksTest.php new file mode 100644 index 00000000000..b6a8c25477c --- /dev/null +++ b/apps/dav/tests/unit/Command/ListAddressbooksTest.php @@ -0,0 +1,110 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\DAV\Tests\Command; + +use OCA\DAV\CardDAV\CardDavBackend; +use OCA\DAV\Command\ListAddressbooks; +use OCP\IUserManager; +use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\Console\Tester\CommandTester; +use Test\TestCase; + +/** + * Class ListCalendarsTest + * + * @package OCA\DAV\Tests\Command + */ +class ListAddressbooksTest extends TestCase { + + private \OCP\IUserManager|MockObject $userManager; + private CardDavBackend|MockObject $cardDavBackend; + private ListAddressbooks $command; + + public const USERNAME = 'username'; + + protected function setUp(): void { + parent::setUp(); + + $this->userManager = $this->createMock(IUserManager::class); + $this->cardDavBackend = $this->createMock(CardDavBackend::class); + + $this->command = new ListAddressbooks( + $this->userManager, + $this->cardDavBackend + ); + } + + public function testWithBadUser(): void { + $this->expectException(\InvalidArgumentException::class); + + $this->userManager->expects($this->once()) + ->method('userExists') + ->with(self::USERNAME) + ->willReturn(false); + + $commandTester = new CommandTester($this->command); + $commandTester->execute([ + 'uid' => self::USERNAME, + ]); + $this->assertStringContainsString('User <' . self::USERNAME . '> in unknown', $commandTester->getDisplay()); + } + + public function testWithCorrectUserWithNoCalendars(): void { + $this->userManager->expects($this->once()) + ->method('userExists') + ->with(self::USERNAME) + ->willReturn(true); + + $this->cardDavBackend->expects($this->once()) + ->method('getAddressBooksForUser') + ->with('principals/users/' . self::USERNAME) + ->willReturn([]); + + $commandTester = new CommandTester($this->command); + $commandTester->execute([ + 'uid' => self::USERNAME, + ]); + $this->assertStringContainsString('User <' . self::USERNAME . "> has no addressbooks\n", $commandTester->getDisplay()); + } + + public function dataExecute() { + return [ + [false, '✓'], + [true, 'x'] + ]; + } + + /** + * @dataProvider dataExecute + */ + public function testWithCorrectUser(bool $readOnly, string $output): void { + $this->userManager->expects($this->once()) + ->method('userExists') + ->with(self::USERNAME) + ->willReturn(true); + + $this->cardDavBackend->expects($this->once()) + ->method('getAddressBooksForUser') + ->with('principals/users/' . self::USERNAME) + ->willReturn([ + [ + '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}read-only' => $readOnly, + 'uri' => 'test', + '{DAV:}displayname' => 'dp', + '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal' => 'owner-principal', + '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}owner-displayname' => 'owner-dp', + ] + ]); + + $commandTester = new CommandTester($this->command); + $commandTester->execute([ + 'uid' => self::USERNAME, + ]); + $this->assertStringContainsString($output, $commandTester->getDisplay()); + } +} |