diff options
Diffstat (limited to 'apps/dav/lib')
-rw-r--r-- | apps/dav/lib/Controller/ExampleContentController.php | 80 | ||||
-rw-r--r-- | apps/dav/lib/DAV/GroupPrincipalBackend.php | 4 | ||||
-rw-r--r-- | apps/dav/lib/Listener/UserEventsListener.php | 6 | ||||
-rw-r--r-- | apps/dav/lib/Service/DefaultContactService.php | 77 | ||||
-rw-r--r-- | apps/dav/lib/Service/ExampleContactService.php | 132 | ||||
-rw-r--r-- | apps/dav/lib/Settings/ExampleContentSettings.php | 14 |
6 files changed, 161 insertions, 152 deletions
diff --git a/apps/dav/lib/Controller/ExampleContentController.php b/apps/dav/lib/Controller/ExampleContentController.php index 905fd392e6c..e20ee4b7f49 100644 --- a/apps/dav/lib/Controller/ExampleContentController.php +++ b/apps/dav/lib/Controller/ExampleContentController.php @@ -10,6 +10,7 @@ declare(strict_types=1); namespace OCA\DAV\Controller; use OCA\DAV\AppInfo\Application; +use OCA\DAV\Service\ExampleContactService; use OCA\DAV\Service\ExampleEventService; use OCP\AppFramework\ApiController; use OCP\AppFramework\Http; @@ -17,103 +18,50 @@ use OCP\AppFramework\Http\Attribute\FrontpageRoute; use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\DataDownloadResponse; use OCP\AppFramework\Http\JSONResponse; -use OCP\Files\AppData\IAppDataFactory; -use OCP\Files\IAppData; -use OCP\Files\NotFoundException; -use OCP\IAppConfig; -use OCP\IConfig; use OCP\IRequest; use Psr\Log\LoggerInterface; class ExampleContentController extends ApiController { - private IAppData $appData; - public function __construct( IRequest $request, - private IConfig $config, - private IAppConfig $appConfig, - private IAppDataFactory $appDataFactory, - private LoggerInterface $logger, - private ExampleEventService $exampleEventService, + private readonly LoggerInterface $logger, + private readonly ExampleEventService $exampleEventService, + private readonly ExampleContactService $exampleContactService, ) { parent::__construct(Application::APP_ID, $request); - $this->appData = $this->appDataFactory->get('dav'); } - public function setEnableDefaultContact($allow) { - if ($allow === 'yes' && !$this->defaultContactExists()) { + #[FrontpageRoute(verb: 'PUT', url: '/api/defaultcontact/config')] + public function setEnableDefaultContact(bool $allow): JSONResponse { + if ($allow && !$this->exampleContactService->defaultContactExists()) { try { - $this->setCard(); + $this->exampleContactService->setCard(); } catch (\Exception $e) { $this->logger->error('Could not create default contact', ['exception' => $e]); return new JSONResponse([], Http::STATUS_INTERNAL_SERVER_ERROR); } } - $this->config->setAppValue(Application::APP_ID, 'enableDefaultContact', $allow); + $this->exampleContactService->setDefaultContactEnabled($allow); return new JSONResponse([], Http::STATUS_OK); } #[NoCSRFRequired] + #[FrontpageRoute(verb: 'GET', url: '/api/defaultcontact/contact')] public function getDefaultContact(): DataDownloadResponse { - $cardData = $this->getCard() + $cardData = $this->exampleContactService->getCard() ?? file_get_contents(__DIR__ . '/../ExampleContentFiles/exampleContact.vcf'); return new DataDownloadResponse($cardData, 'example_contact.vcf', 'text/vcard'); } + #[FrontpageRoute(verb: 'PUT', url: '/api/defaultcontact/contact')] public function setDefaultContact(?string $contactData = null) { - if (!$this->config->getAppValue(Application::APP_ID, 'enableDefaultContact', 'yes')) { + if (!$this->exampleContactService->isDefaultContactEnabled()) { return new JSONResponse([], Http::STATUS_FORBIDDEN); } - $this->setCard($contactData); + $this->exampleContactService->setCard($contactData); return new JSONResponse([], Http::STATUS_OK); } - private function getCard(): ?string { - try { - $folder = $this->appData->getFolder('defaultContact'); - } catch (NotFoundException $e) { - return null; - } - - if (!$folder->fileExists('defaultContact.vcf')) { - return null; - } - - return $folder->getFile('defaultContact.vcf')->getContent(); - } - - private function setCard(?string $cardData = null) { - try { - $folder = $this->appData->getFolder('defaultContact'); - } catch (NotFoundException $e) { - $folder = $this->appData->newFolder('defaultContact'); - } - - $isCustom = true; - if (is_null($cardData)) { - $cardData = file_get_contents(__DIR__ . '/../ExampleContentFiles/exampleContact.vcf'); - $isCustom = false; - } - - if (!$cardData) { - throw new \Exception('Could not read exampleContact.vcf'); - } - - $file = (!$folder->fileExists('defaultContact.vcf')) ? $folder->newFile('defaultContact.vcf') : $folder->getFile('defaultContact.vcf'); - $file->putContent($cardData); - - $this->appConfig->setValueBool(Application::APP_ID, 'hasCustomDefaultContact', $isCustom); - } - - private function defaultContactExists(): bool { - try { - $folder = $this->appData->getFolder('defaultContact'); - } catch (NotFoundException $e) { - return false; - } - return $folder->fileExists('defaultContact.vcf'); - } - #[FrontpageRoute(verb: 'POST', url: '/api/exampleEvent/enable')] public function setCreateExampleEvent(bool $enable): JSONResponse { $this->exampleEventService->setCreateExampleEvent($enable); diff --git a/apps/dav/lib/DAV/GroupPrincipalBackend.php b/apps/dav/lib/DAV/GroupPrincipalBackend.php index ddbd64bdda1..70a0099330c 100644 --- a/apps/dav/lib/DAV/GroupPrincipalBackend.php +++ b/apps/dav/lib/DAV/GroupPrincipalBackend.php @@ -188,6 +188,10 @@ class GroupPrincipalBackend implements BackendInterface { $groups = $this->groupManager->search($value, $searchLimit); $results[] = array_reduce($groups, function (array $carry, IGroup $group) use ($restrictGroups) { + if ($group->hideFromCollaboration()) { + return $carry; + } + $gid = $group->getGID(); // is sharing restricted to groups only? if ($restrictGroups !== false) { diff --git a/apps/dav/lib/Listener/UserEventsListener.php b/apps/dav/lib/Listener/UserEventsListener.php index 67cf228515a..c876192d67f 100644 --- a/apps/dav/lib/Listener/UserEventsListener.php +++ b/apps/dav/lib/Listener/UserEventsListener.php @@ -12,7 +12,7 @@ namespace OCA\DAV\Listener; use OCA\DAV\CalDAV\CalDavBackend; use OCA\DAV\CardDAV\CardDavBackend; use OCA\DAV\CardDAV\SyncService; -use OCA\DAV\Service\DefaultContactService; +use OCA\DAV\Service\ExampleContactService; use OCA\DAV\Service\ExampleEventService; use OCP\Accounts\UserUpdatedEvent; use OCP\Defaults; @@ -46,7 +46,7 @@ class UserEventsListener implements IEventListener { private CalDavBackend $calDav, private CardDavBackend $cardDav, private Defaults $themingDefaults, - private DefaultContactService $defaultContactService, + private ExampleContactService $exampleContactService, private ExampleEventService $exampleEventService, private LoggerInterface $logger, ) { @@ -175,7 +175,7 @@ class UserEventsListener implements IEventListener { } } if ($addressBookId) { - $this->defaultContactService->createDefaultContact($addressBookId); + $this->exampleContactService->createDefaultContact($addressBookId); } } } diff --git a/apps/dav/lib/Service/DefaultContactService.php b/apps/dav/lib/Service/DefaultContactService.php deleted file mode 100644 index 24e55ef7b69..00000000000 --- a/apps/dav/lib/Service/DefaultContactService.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace OCA\DAV\Service; - -use OCA\DAV\AppInfo\Application; -use OCA\DAV\CardDAV\CardDavBackend; -use OCP\App\IAppManager; -use OCP\Files\AppData\IAppDataFactory; -use OCP\IAppConfig; -use Psr\Log\LoggerInterface; -use Symfony\Component\Uid\Uuid; - -class DefaultContactService { - public function __construct( - private CardDavBackend $cardDav, - private IAppManager $appManager, - private IAppDataFactory $appDataFactory, - private IAppConfig $config, - private LoggerInterface $logger, - ) { - } - - public function createDefaultContact(int $addressBookId): void { - $enableDefaultContact = $this->config->getValueString(Application::APP_ID, 'enableDefaultContact', 'yes'); - if ($enableDefaultContact !== 'yes') { - return; - } - $appData = $this->appDataFactory->get('dav'); - try { - $folder = $appData->getFolder('defaultContact'); - $defaultContactFile = $folder->getFile('defaultContact.vcf'); - $data = $defaultContactFile->getContent(); - } catch (\Exception $e) { - $this->logger->error('Couldn\'t get default contact file', ['exception' => $e]); - return; - } - - // Make sure the UID is unique - $newUid = Uuid::v4()->toRfc4122(); - $newRev = date('Ymd\THis\Z'); - $vcard = \Sabre\VObject\Reader::read($data, \Sabre\VObject\Reader::OPTION_FORGIVING); - if ($vcard->UID) { - $vcard->UID->setValue($newUid); - } else { - $vcard->add('UID', $newUid); - } - if ($vcard->REV) { - $vcard->REV->setValue($newRev); - } else { - $vcard->add('REV', $newRev); - } - - // Level 3 means that the document is invalid - // https://sabre.io/vobject/vcard/#validating-vcard - $level3Warnings = array_filter($vcard->validate(), function ($warning) { - return $warning['level'] === 3; - }); - - if (!empty($level3Warnings)) { - $this->logger->error('Default contact is invalid', ['warnings' => $level3Warnings]); - return; - } - try { - $this->cardDav->createCard($addressBookId, 'default', $vcard->serialize(), false); - } catch (\Exception $e) { - $this->logger->error($e->getMessage(), ['exception' => $e]); - } - - } -} diff --git a/apps/dav/lib/Service/ExampleContactService.php b/apps/dav/lib/Service/ExampleContactService.php new file mode 100644 index 00000000000..6ed6c66cbb3 --- /dev/null +++ b/apps/dav/lib/Service/ExampleContactService.php @@ -0,0 +1,132 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\DAV\Service; + +use OCA\DAV\AppInfo\Application; +use OCA\DAV\CardDAV\CardDavBackend; +use OCP\AppFramework\Services\IAppConfig; +use OCP\Files\AppData\IAppDataFactory; +use OCP\Files\IAppData; +use OCP\Files\NotFoundException; +use Psr\Log\LoggerInterface; +use Symfony\Component\Uid\Uuid; + +class ExampleContactService { + private readonly IAppData $appData; + + public function __construct( + IAppDataFactory $appDataFactory, + private readonly IAppConfig $appConfig, + private readonly LoggerInterface $logger, + private readonly CardDavBackend $cardDav, + ) { + $this->appData = $appDataFactory->get(Application::APP_ID); + } + + public function isDefaultContactEnabled(): bool { + return $this->appConfig->getAppValueBool('enableDefaultContact', true); + } + + public function setDefaultContactEnabled(bool $value): void { + $this->appConfig->setAppValueBool('enableDefaultContact', $value); + } + + public function getCard(): ?string { + try { + $folder = $this->appData->getFolder('defaultContact'); + } catch (NotFoundException $e) { + return null; + } + + if (!$folder->fileExists('defaultContact.vcf')) { + return null; + } + + return $folder->getFile('defaultContact.vcf')->getContent(); + } + + public function setCard(?string $cardData = null) { + try { + $folder = $this->appData->getFolder('defaultContact'); + } catch (NotFoundException $e) { + $folder = $this->appData->newFolder('defaultContact'); + } + + $isCustom = true; + if (is_null($cardData)) { + $cardData = file_get_contents(__DIR__ . '/../ExampleContentFiles/exampleContact.vcf'); + $isCustom = false; + } + + if (!$cardData) { + throw new \Exception('Could not read exampleContact.vcf'); + } + + $file = (!$folder->fileExists('defaultContact.vcf')) ? $folder->newFile('defaultContact.vcf') : $folder->getFile('defaultContact.vcf'); + $file->putContent($cardData); + + $this->appConfig->setAppValueBool('hasCustomDefaultContact', $isCustom); + } + + public function defaultContactExists(): bool { + try { + $folder = $this->appData->getFolder('defaultContact'); + } catch (NotFoundException $e) { + return false; + } + return $folder->fileExists('defaultContact.vcf'); + } + + public function createDefaultContact(int $addressBookId): void { + if (!$this->isDefaultContactEnabled()) { + return; + } + + try { + $folder = $this->appData->getFolder('defaultContact'); + $defaultContactFile = $folder->getFile('defaultContact.vcf'); + $data = $defaultContactFile->getContent(); + } catch (\Exception $e) { + $this->logger->error('Couldn\'t get default contact file', ['exception' => $e]); + return; + } + + // Make sure the UID is unique + $newUid = Uuid::v4()->toRfc4122(); + $newRev = date('Ymd\THis\Z'); + $vcard = \Sabre\VObject\Reader::read($data, \Sabre\VObject\Reader::OPTION_FORGIVING); + if ($vcard->UID) { + $vcard->UID->setValue($newUid); + } else { + $vcard->add('UID', $newUid); + } + if ($vcard->REV) { + $vcard->REV->setValue($newRev); + } else { + $vcard->add('REV', $newRev); + } + + // Level 3 means that the document is invalid + // https://sabre.io/vobject/vcard/#validating-vcard + $level3Warnings = array_filter($vcard->validate(), static function ($warning) { + return $warning['level'] === 3; + }); + + if (!empty($level3Warnings)) { + $this->logger->error('Default contact is invalid', ['warnings' => $level3Warnings]); + return; + } + try { + $this->cardDav->createCard($addressBookId, 'default', $vcard->serialize(), false); + } catch (\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + } + } +} diff --git a/apps/dav/lib/Settings/ExampleContentSettings.php b/apps/dav/lib/Settings/ExampleContentSettings.php index fef2d25b8d2..7b6f9b03a3a 100644 --- a/apps/dav/lib/Settings/ExampleContentSettings.php +++ b/apps/dav/lib/Settings/ExampleContentSettings.php @@ -9,21 +9,21 @@ declare(strict_types=1); namespace OCA\DAV\Settings; use OCA\DAV\AppInfo\Application; +use OCA\DAV\Service\ExampleContactService; use OCA\DAV\Service\ExampleEventService; use OCP\App\IAppManager; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Services\IAppConfig; use OCP\AppFramework\Services\IInitialState; -use OCP\IAppConfig; -use OCP\IConfig; use OCP\Settings\ISettings; class ExampleContentSettings implements ISettings { public function __construct( - private readonly IConfig $config, private readonly IAppConfig $appConfig, private readonly IInitialState $initialState, private readonly IAppManager $appManager, private readonly ExampleEventService $exampleEventService, + private readonly ExampleContactService $exampleContactService, ) { } @@ -43,11 +43,13 @@ class ExampleContentSettings implements ISettings { } if ($contactsEnabled) { - $enableDefaultContact = $this->config->getAppValue(Application::APP_ID, 'enableDefaultContact', 'yes'); - $this->initialState->provideInitialState('enableDefaultContact', $enableDefaultContact); + $this->initialState->provideInitialState( + 'enableDefaultContact', + $this->exampleContactService->isDefaultContactEnabled(), + ); $this->initialState->provideInitialState( 'hasCustomDefaultContact', - $this->appConfig->getValueBool(Application::APP_ID, 'hasCustomDefaultContact'), + $this->appConfig->getAppValueBool('hasCustomDefaultContact'), ); } |