diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index c99d82a798..0cfa2e968e 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -47,6 +47,7 @@ OCA\DAV\Command\CreateAddressBook OCA\DAV\Command\CreateCalendar + OCA\DAV\Command\DeleteCalendar OCA\DAV\Command\MoveCalendar OCA\DAV\Command\ListCalendars OCA\DAV\Command\RetentionCleanupCommand diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index 19c0e2549f..13e78cee71 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -118,6 +118,7 @@ return array( 'OCA\\DAV\\CardDAV\\Xml\\Groups' => $baseDir . '/../lib/CardDAV/Xml/Groups.php', 'OCA\\DAV\\Command\\CreateAddressBook' => $baseDir . '/../lib/Command/CreateAddressBook.php', 'OCA\\DAV\\Command\\CreateCalendar' => $baseDir . '/../lib/Command/CreateCalendar.php', + 'OCA\\DAV\\Command\\DeleteCalendar' => $baseDir . '/../lib/Command/DeleteCalendar.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 6895064e39..42ba59e058 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -133,6 +133,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\CardDAV\\Xml\\Groups' => __DIR__ . '/..' . '/../lib/CardDAV/Xml/Groups.php', 'OCA\\DAV\\Command\\CreateAddressBook' => __DIR__ . '/..' . '/../lib/Command/CreateAddressBook.php', 'OCA\\DAV\\Command\\CreateCalendar' => __DIR__ . '/..' . '/../lib/Command/CreateCalendar.php', + 'OCA\\DAV\\Command\\DeleteCalendar' => __DIR__ . '/..' . '/../lib/Command/DeleteCalendar.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/DeleteCalendar.php b/apps/dav/lib/Command/DeleteCalendar.php new file mode 100644 index 0000000000..14796b02fc --- /dev/null +++ b/apps/dav/lib/Command/DeleteCalendar.php @@ -0,0 +1,124 @@ +. + * + */ + +namespace OCA\DAV\Command; + +use OCA\DAV\CalDAV\BirthdayService; +use OCA\DAV\CalDAV\CalDavBackend; +use OCP\IConfig; +use OCP\IUserManager; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class DeleteCalendar extends Command { + /** @var CalDavBackend */ + private $calDav; + + /** @var IConfig */ + private $config; + + /** @var IUserManager */ + private $userManager; + + /** + * @param CalDavBackend $calDav + * @param IConfig $config + * @param IUserManager $userManager + */ + public function __construct( + CalDavBackend $calDav, + IConfig $config, + IUserManager $userManager + ) { + parent::__construct(); + $this->calDav = $calDav; + $this->config = $config; + $this->userManager = $userManager; + } + + protected function configure(): void { + $this + ->setName('dav:delete-calendar') + ->setDescription('Delete a dav calendar') + ->addArgument('uid', + InputArgument::REQUIRED, + 'User who owns the calendar') + ->addArgument('name', + InputArgument::OPTIONAL, + 'Name of the calendar to delete') + ->addOption('birthday', + null, + InputOption::VALUE_NONE, + 'Delete the birthday calendar') + ->addOption('force', + 'f', + InputOption::VALUE_NONE, + 'Force delete skipping trashbin'); + } + + protected function execute( + InputInterface $input, + OutputInterface $output + ): int { + /** @var string $user **/ + $user = $input->getArgument('uid'); + if (!$this->userManager->userExists($user)) { + throw new \InvalidArgumentException( + 'User <' . $user . '> is unknown.'); + } + + $birthday = $input->getOption('birthday'); + if ($birthday !== false) { + $name = BirthdayService::BIRTHDAY_CALENDAR_URI; + } else { + $name = $input->getArgument('name'); + if (!$name) { + throw new \InvalidArgumentException( + 'Please specify a calendar name or --birthday'); + } + } + + $calendar = $this->calDav->getCalendarByUri( + 'principals/users/' . $user, + $name); + if ($calendar === null) { + throw new \InvalidArgumentException( + 'User <' . $user . '> has no calendar named <' . $name . '>. You can run occ dav:list-calendars to list calendars URIs for this user.'); + } + + if ($name === BirthdayService::BIRTHDAY_CALENDAR_URI) { + $this->config->setUserValue($user, + 'dav', 'generateBirthdayCalendar', 'no'); + } + + $force = $input->getOption('force'); + + $this->calDav->deleteCalendar($calendar['id'], $force !== false); + + return 0; + } +} diff --git a/apps/dav/tests/unit/Command/DeleteCalendarTest.php b/apps/dav/tests/unit/Command/DeleteCalendarTest.php new file mode 100644 index 0000000000..b25a37e071 --- /dev/null +++ b/apps/dav/tests/unit/Command/DeleteCalendarTest.php @@ -0,0 +1,230 @@ +. + * + */ + +namespace OCA\DAV\Tests\Command; + +use OCA\DAV\CalDAV\BirthdayService; +use OCA\DAV\CalDav\CalDavBackend; +use OCA\DAV\Command\DeleteCalendar; +use OCP\IConfig; +use OCP\IUserManager; +use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Component\Console\Tester\CommandTester; +use Test\TestCase; + +/** + * Class DeleteCalendarTest + * + * @package OCA\DAV\Tests\Command + */ +class DeleteCalendarTest extends TestCase { + public const USER = 'user'; + public const NAME = 'calendar'; + + /** @var CalDavBackend|MockObject */ + private $calDav; + + /** @var IConfig|MockObject */ + private $config; + + /** @var IUserManager|MockObject */ + private $userManager; + + /** @var DeleteCalendar */ + private $command; + + protected function setUp(): void { + parent::setUp(); + + $this->calDav = $this->createMock(CalDavBackend::class); + $this->config = $this->createMock(IConfig::class); + $this->userManager = $this->createMock(IUserManager::class); + + $this->command = new DeleteCalendar( + $this->calDav, + $this->config, + $this->userManager, + ); + } + + public function testInvalidUser() { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage( + 'User <' . self::USER . '> is unknown.'); + + $this->userManager->expects($this->once()) + ->method('userExists') + ->with(self::USER) + ->willReturn(false); + + $commandTester = new CommandTester($this->command); + $commandTester->execute([ + 'uid' => self::USER, + 'name' => self::NAME, + ]); + } + + public function testNoCalendarName() { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Please specify a calendar name or --birthday'); + + $this->userManager->expects($this->once()) + ->method('userExists') + ->with(self::USER) + ->willReturn(true); + + $commandTester = new CommandTester($this->command); + $commandTester->execute([ + 'uid' => self::USER, + ]); + } + + public function testInvalidCalendar() { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage( + 'User <' . self::USER . '> has no calendar named <' . self::NAME . '>.'); + + $this->userManager->expects($this->once()) + ->method('userExists') + ->with(self::USER) + ->willReturn(true); + $this->calDav->expects($this->once()) + ->method('getCalendarByUri') + ->with( + 'principals/users/' . self::USER, + self::NAME + ) + ->willReturn(null); + + $commandTester = new CommandTester($this->command); + $commandTester->execute([ + 'uid' => self::USER, + 'name' => self::NAME, + ]); + } + + public function testDelete() { + $id = 1234; + + $this->userManager->expects($this->once()) + ->method('userExists') + ->with(self::USER) + ->willReturn(true); + $this->calDav->expects($this->once()) + ->method('getCalendarByUri') + ->with( + 'principals/users/' . self::USER, + self::NAME + ) + ->willReturn(['id' => $id]); + $this->calDav->expects($this->once()) + ->method('deleteCalendar') + ->with($id, false); + + $commandTester = new CommandTester($this->command); + $commandTester->execute([ + 'uid' => self::USER, + 'name' => self::NAME, + ]); + } + + public function testForceDelete() { + $id = 1234; + + $this->userManager->expects($this->once()) + ->method('userExists') + ->with(self::USER) + ->willReturn(true); + $this->calDav->expects($this->once()) + ->method('getCalendarByUri') + ->with( + 'principals/users/' . self::USER, + self::NAME + ) + ->willReturn(['id' => $id]); + $this->calDav->expects($this->once()) + ->method('deleteCalendar') + ->with($id, true); + + $commandTester = new CommandTester($this->command); + $commandTester->execute([ + 'uid' => self::USER, + 'name' => self::NAME, + '-f' => true + ]); + } + + public function testDeleteBirthday() { + $id = 1234; + + $this->userManager->expects($this->once()) + ->method('userExists') + ->with(self::USER) + ->willReturn(true); + $this->calDav->expects($this->once()) + ->method('getCalendarByUri') + ->with( + 'principals/users/' . self::USER, + BirthdayService::BIRTHDAY_CALENDAR_URI + ) + ->willReturn(['id' => $id]); + $this->config->expects($this->once()) + ->method('setUserValue') + ->with( + self::USER, + 'dav', 'generateBirthdayCalendar', 'no' + ); + $this->calDav->expects($this->once()) + ->method('deleteCalendar') + ->with($id); + + $commandTester = new CommandTester($this->command); + $commandTester->execute([ + 'uid' => self::USER, + '--birthday' => true, + ]); + } + + public function testBirthdayHasPrecedence() { + $this->userManager->expects($this->once()) + ->method('userExists') + ->with(self::USER) + ->willReturn(true); + $this->calDav->expects($this->once()) + ->method('getCalendarByUri') + ->with( + 'principals/users/' . self::USER, + BirthdayService::BIRTHDAY_CALENDAR_URI + ) + ->willReturn(['id' => 1234]); + + $commandTester = new CommandTester($this->command); + $commandTester->execute([ + 'uid' => self::USER, + 'name' => self::NAME, + '--birthday' => true, + ]); + } +}