From 45ed9b10d566d473468c9b829e5fb65829812ee4 Mon Sep 17 00:00:00 2001 From: Richard Steinmetz Date: Wed, 4 Oct 2023 12:31:46 +0200 Subject: [PATCH] feat(dav): implement personal absence settings backend Signed-off-by: Richard Steinmetz --- apps/dav/appinfo/info.xml | 2 +- .../composer/composer/autoload_classmap.php | 4 + .../dav/composer/composer/autoload_static.php | 4 + apps/dav/lib/Db/Absence.php | 68 +++++++++++++++ apps/dav/lib/Db/AbsenceMapper.php | 81 ++++++++++++++++++ .../Version1029Date20231004091403.php | 83 +++++++++++++++++++ apps/dav/lib/Service/AbsenceService.php | 74 +++++++++++++++++ 7 files changed, 315 insertions(+), 1 deletion(-) create mode 100644 apps/dav/lib/Db/Absence.php create mode 100644 apps/dav/lib/Db/AbsenceMapper.php create mode 100644 apps/dav/lib/Migration/Version1029Date20231004091403.php create mode 100644 apps/dav/lib/Service/AbsenceService.php diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index bc3e73aa7186a..776f0744fecdf 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -5,7 +5,7 @@ WebDAV WebDAV endpoint WebDAV endpoint - 1.28.0 + 1.29.0 agpl owncloud.org DAV diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index 414c5df4a4a29..bd8f5baf4806a 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -201,6 +201,8 @@ 'OCA\\DAV\\DAV\\Sharing\\Xml\\ShareRequest' => $baseDir . '/../lib/DAV/Sharing/Xml/ShareRequest.php', 'OCA\\DAV\\DAV\\SystemPrincipalBackend' => $baseDir . '/../lib/DAV/SystemPrincipalBackend.php', 'OCA\\DAV\\DAV\\ViewOnlyPlugin' => $baseDir . '/../lib/DAV/ViewOnlyPlugin.php', + 'OCA\\DAV\\Db\\Absence' => $baseDir . '/../lib/Db/Absence.php', + 'OCA\\DAV\\Db\\AbsenceMapper' => $baseDir . '/../lib/Db/AbsenceMapper.php', 'OCA\\DAV\\Db\\Direct' => $baseDir . '/../lib/Db/Direct.php', 'OCA\\DAV\\Db\\DirectMapper' => $baseDir . '/../lib/Db/DirectMapper.php', 'OCA\\DAV\\Direct\\DirectFile' => $baseDir . '/../lib/Direct/DirectFile.php', @@ -297,6 +299,7 @@ 'OCA\\DAV\\Migration\\Version1018Date20210312100735' => $baseDir . '/../lib/Migration/Version1018Date20210312100735.php', 'OCA\\DAV\\Migration\\Version1024Date20211221144219' => $baseDir . '/../lib/Migration/Version1024Date20211221144219.php', 'OCA\\DAV\\Migration\\Version1027Date20230504122946' => $baseDir . '/../lib/Migration/Version1027Date20230504122946.php', + 'OCA\\DAV\\Migration\\Version1029Date20231004091403' => $baseDir . '/../lib/Migration/Version1029Date20231004091403.php', 'OCA\\DAV\\Profiler\\ProfilerPlugin' => $baseDir . '/../lib/Profiler/ProfilerPlugin.php', 'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningNode' => $baseDir . '/../lib/Provisioning/Apple/AppleProvisioningNode.php', 'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningPlugin' => $baseDir . '/../lib/Provisioning/Apple/AppleProvisioningPlugin.php', @@ -306,6 +309,7 @@ 'OCA\\DAV\\Search\\EventsSearchProvider' => $baseDir . '/../lib/Search/EventsSearchProvider.php', 'OCA\\DAV\\Search\\TasksSearchProvider' => $baseDir . '/../lib/Search/TasksSearchProvider.php', 'OCA\\DAV\\Server' => $baseDir . '/../lib/Server.php', + 'OCA\\DAV\\Service\\AbsenceService' => $baseDir . '/../lib/Service/AbsenceService.php', 'OCA\\DAV\\Settings\\AvailabilitySettings' => $baseDir . '/../lib/Settings/AvailabilitySettings.php', 'OCA\\DAV\\Settings\\CalDAVSettings' => $baseDir . '/../lib/Settings/CalDAVSettings.php', 'OCA\\DAV\\SetupChecks\\NeedsSystemAddressBookSync' => $baseDir . '/../lib/SetupChecks/NeedsSystemAddressBookSync.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index 7b0520cc220c5..aaab360d1de9a 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -216,6 +216,8 @@ class ComposerStaticInitDAV 'OCA\\DAV\\DAV\\Sharing\\Xml\\ShareRequest' => __DIR__ . '/..' . '/../lib/DAV/Sharing/Xml/ShareRequest.php', 'OCA\\DAV\\DAV\\SystemPrincipalBackend' => __DIR__ . '/..' . '/../lib/DAV/SystemPrincipalBackend.php', 'OCA\\DAV\\DAV\\ViewOnlyPlugin' => __DIR__ . '/..' . '/../lib/DAV/ViewOnlyPlugin.php', + 'OCA\\DAV\\Db\\Absence' => __DIR__ . '/..' . '/../lib/Db/Absence.php', + 'OCA\\DAV\\Db\\AbsenceMapper' => __DIR__ . '/..' . '/../lib/Db/AbsenceMapper.php', 'OCA\\DAV\\Db\\Direct' => __DIR__ . '/..' . '/../lib/Db/Direct.php', 'OCA\\DAV\\Db\\DirectMapper' => __DIR__ . '/..' . '/../lib/Db/DirectMapper.php', 'OCA\\DAV\\Direct\\DirectFile' => __DIR__ . '/..' . '/../lib/Direct/DirectFile.php', @@ -312,6 +314,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\Migration\\Version1018Date20210312100735' => __DIR__ . '/..' . '/../lib/Migration/Version1018Date20210312100735.php', 'OCA\\DAV\\Migration\\Version1024Date20211221144219' => __DIR__ . '/..' . '/../lib/Migration/Version1024Date20211221144219.php', 'OCA\\DAV\\Migration\\Version1027Date20230504122946' => __DIR__ . '/..' . '/../lib/Migration/Version1027Date20230504122946.php', + 'OCA\\DAV\\Migration\\Version1029Date20231004091403' => __DIR__ . '/..' . '/../lib/Migration/Version1029Date20231004091403.php', 'OCA\\DAV\\Profiler\\ProfilerPlugin' => __DIR__ . '/..' . '/../lib/Profiler/ProfilerPlugin.php', 'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningNode' => __DIR__ . '/..' . '/../lib/Provisioning/Apple/AppleProvisioningNode.php', 'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningPlugin' => __DIR__ . '/..' . '/../lib/Provisioning/Apple/AppleProvisioningPlugin.php', @@ -321,6 +324,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\Search\\EventsSearchProvider' => __DIR__ . '/..' . '/../lib/Search/EventsSearchProvider.php', 'OCA\\DAV\\Search\\TasksSearchProvider' => __DIR__ . '/..' . '/../lib/Search/TasksSearchProvider.php', 'OCA\\DAV\\Server' => __DIR__ . '/..' . '/../lib/Server.php', + 'OCA\\DAV\\Service\\AbsenceService' => __DIR__ . '/..' . '/../lib/Service/AbsenceService.php', 'OCA\\DAV\\Settings\\AvailabilitySettings' => __DIR__ . '/..' . '/../lib/Settings/AvailabilitySettings.php', 'OCA\\DAV\\Settings\\CalDAVSettings' => __DIR__ . '/..' . '/../lib/Settings/CalDAVSettings.php', 'OCA\\DAV\\SetupChecks\\NeedsSystemAddressBookSync' => __DIR__ . '/..' . '/../lib/SetupChecks/NeedsSystemAddressBookSync.php', diff --git a/apps/dav/lib/Db/Absence.php b/apps/dav/lib/Db/Absence.php new file mode 100644 index 0000000000000..f705b99ef3058 --- /dev/null +++ b/apps/dav/lib/Db/Absence.php @@ -0,0 +1,68 @@ + + * + * @author Richard Steinmetz + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\DAV\Db; + +use JsonSerializable; +use OCP\AppFramework\Db\Entity; + +/** + * @method string getUserId() + * @method void setUserId(string $userId) + * @method string getFirstDay() + * @method void setFirstDay(string $firstDay) + * @method string getLastDay() + * @method void setLastDay(string $lastDay) + * @method string getStatus() + * @method void setStatus(string $status) + * @method string getMessage() + * @method void setMessage(string $message) + */ +class Absence extends Entity implements JsonSerializable { + protected string $userId = ''; + protected string $firstDay = ''; + protected string $lastDay = ''; + protected string $status = ''; + protected string $message = ''; + + public function __construct() { + $this->addType('userId', 'string'); + $this->addType('firstDay', 'string'); + $this->addType('lastDay', 'string'); + $this->addType('status', 'string'); + $this->addType('message', 'string'); + } + + public function jsonSerialize(): array { + return [ + 'userId' => $this->userId, + 'firstDay' => $this->firstDay, + 'lastDay' => $this->lastDay, + 'status' => $this->status, + 'message' => $this->message, + ]; + } +} diff --git a/apps/dav/lib/Db/AbsenceMapper.php b/apps/dav/lib/Db/AbsenceMapper.php new file mode 100644 index 0000000000000..6e1133f779c33 --- /dev/null +++ b/apps/dav/lib/Db/AbsenceMapper.php @@ -0,0 +1,81 @@ + + * + * @author Richard Steinmetz + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\DAV\Db; + +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Db\MultipleObjectsReturnedException; +use OCP\AppFramework\Db\QBMapper; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IDBConnection; + +/** + * @template-extends QBMapper + */ +class AbsenceMapper extends QBMapper { + public function __construct(IDBConnection $db) { + parent::__construct($db, 'dav_absence', Absence::class); + } + + /** + * @throws DoesNotExistException + * @throws \OCP\DB\Exception + */ + public function findByUserId(string $userId): Absence { + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from($this->getTableName()) + ->where($qb->expr()->eq( + 'user_id', + $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR), + IQueryBuilder::PARAM_STR), + ); + try { + return $this->findEntity($qb); + } catch (MultipleObjectsReturnedException $e) { + // Won't happen as there is a unique index on user_id + throw new \RuntimeException( + 'The impossible has happened! The query returned multiple absence settings for one user.', + 0, + $e, + ); + } + } + + /** + * @throws \OCP\DB\Exception + */ + public function deleteByUserId(string $userId): void { + $qb = $this->db->getQueryBuilder(); + $qb->delete($this->getTableName()) + ->where($qb->expr()->eq( + 'user_id', + $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR), + IQueryBuilder::PARAM_STR), + ); + $qb->executeStatement(); + } +} diff --git a/apps/dav/lib/Migration/Version1029Date20231004091403.php b/apps/dav/lib/Migration/Version1029Date20231004091403.php new file mode 100644 index 0000000000000..6eb7be8a5cd59 --- /dev/null +++ b/apps/dav/lib/Migration/Version1029Date20231004091403.php @@ -0,0 +1,83 @@ + + * + * @author Richard Steinmetz + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\DAV\Migration; + +use Closure; +use OCP\DB\ISchemaWrapper; +use OCP\DB\Types; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + +class Version1029Date20231004091403 extends SimpleMigrationStep { + /** + * @param IOutput $output + * @param Closure(): ISchemaWrapper $schemaClosure + * @param array $options + * @return null|ISchemaWrapper + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + if (!$schema->hasTable('dav_absence')) { + $table = $schema->createTable('dav_absence'); + $table->addColumn('id', Types::INTEGER, [ + 'autoincrement' => true, + 'notnull' => true, + 'length' => 4, + ]); + $table->addColumn('user_id', Types::STRING, [ + 'notnull' => true, + 'length' => 64, + ]); + $table->addColumn('first_day', Types::STRING, [ + 'length' => 10, + 'notnull' => true, + ]); + $table->addColumn('last_day', Types::STRING, [ + 'length' => 10, + 'notnull' => true, + ]); + $table->addColumn('status', Types::STRING, [ + 'length' => 100, + 'notnull' => true, + ]); + $table->addColumn('message', Types::TEXT, [ + 'notnull' => true, + ]); + $table->addUniqueIndex(['user_id'], 'dav_absence_uid_idx'); + } else { + $table = $schema->getTable('dav_absence'); + } + + if ($table->getPrimaryKey() === null) { + $table->setPrimaryKey(['id'], 'dav_absence_id_idx'); + } + + return $schema; + } +} diff --git a/apps/dav/lib/Service/AbsenceService.php b/apps/dav/lib/Service/AbsenceService.php new file mode 100644 index 0000000000000..228007b3af114 --- /dev/null +++ b/apps/dav/lib/Service/AbsenceService.php @@ -0,0 +1,74 @@ + + * + * @author Richard Steinmetz + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\DAV\Service; + +use OCA\DAV\Db\Absence; +use OCA\DAV\Db\AbsenceMapper; +use OCP\AppFramework\Db\DoesNotExistException; + +class AbsenceService { + public function __construct( + private AbsenceMapper $absenceMapper, + ) { + } + + /** + * @throws \OCP\DB\Exception + */ + public function createOrUpdateAbsence( + string $userId, + string $firstDay, + string $lastDay, + string $status, + string $message, + ): Absence { + try { + $absence = $this->absenceMapper->findByUserId($userId); + } catch (DoesNotExistException) { + $absence = new Absence(); + } + + $absence->setUserId($userId); + $absence->setFirstDay($firstDay); + $absence->setLastDay($lastDay); + $absence->setStatus($status); + $absence->setMessage($message); + + if ($absence->getId() === null) { + return $this->absenceMapper->insert($absence); + } + return $this->absenceMapper->update($absence); + } + + /** + * @throws \OCP\DB\Exception + */ + public function clearAbsence(string $userId): void { + $this->absenceMapper->deleteByUserId($userId); + } +} +