diff options
Diffstat (limited to 'apps/dav/lib/Controller/OutOfOfficeController.php')
-rw-r--r-- | apps/dav/lib/Controller/OutOfOfficeController.php | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/apps/dav/lib/Controller/OutOfOfficeController.php b/apps/dav/lib/Controller/OutOfOfficeController.php new file mode 100644 index 00000000000..d3516d092e8 --- /dev/null +++ b/apps/dav/lib/Controller/OutOfOfficeController.php @@ -0,0 +1,189 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\DAV\Controller; + +use DateTimeImmutable; +use OCA\DAV\ResponseDefinitions; +use OCA\DAV\Service\AbsenceService; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\OCSController; +use OCP\IRequest; +use OCP\IUserManager; +use OCP\IUserSession; +use OCP\User\IAvailabilityCoordinator; +use function mb_strlen; + +/** + * @psalm-import-type DAVOutOfOfficeData from ResponseDefinitions + * @psalm-import-type DAVCurrentOutOfOfficeData from ResponseDefinitions + */ +class OutOfOfficeController extends OCSController { + + public function __construct( + string $appName, + IRequest $request, + private IUserManager $userManager, + private ?IUserSession $userSession, + private AbsenceService $absenceService, + private IAvailabilityCoordinator $coordinator, + ) { + parent::__construct($appName, $request); + } + + /** + * Get the currently configured out-of-office data of a user + * + * @param string $userId The user id to get out-of-office data for. + * @return DataResponse<Http::STATUS_OK, DAVCurrentOutOfOfficeData, array{}>|DataResponse<Http::STATUS_NOT_FOUND, null, array{}> + * + * 200: Out-of-office data + * 404: No out-of-office data was found + */ + #[NoAdminRequired] + public function getCurrentOutOfOfficeData(string $userId): DataResponse { + $user = $this->userManager->get($userId); + if ($user === null) { + return new DataResponse(null, Http::STATUS_NOT_FOUND); + } + try { + $data = $this->absenceService->getCurrentAbsence($user); + if ($data === null) { + return new DataResponse(null, Http::STATUS_NOT_FOUND); + } + } catch (DoesNotExistException) { + return new DataResponse(null, Http::STATUS_NOT_FOUND); + } + + return new DataResponse($data->jsonSerialize()); + } + + /** + * Get the configured out-of-office data of a user. + * + * @param string $userId The user id to get out-of-office data for. + * @return DataResponse<Http::STATUS_OK, DAVOutOfOfficeData, array{}>|DataResponse<Http::STATUS_NOT_FOUND, null, array{}> + * + * 200: Out-of-office data + * 404: No out-of-office data was found + */ + #[NoAdminRequired] + public function getOutOfOffice(string $userId): DataResponse { + try { + $data = $this->absenceService->getAbsence($userId); + if ($data === null) { + return new DataResponse(null, Http::STATUS_NOT_FOUND); + } + } catch (DoesNotExistException) { + return new DataResponse(null, Http::STATUS_NOT_FOUND); + } + + return new DataResponse([ + 'id' => $data->getId(), + 'userId' => $data->getUserId(), + 'firstDay' => $data->getFirstDay(), + 'lastDay' => $data->getLastDay(), + 'status' => $data->getStatus(), + 'message' => $data->getMessage(), + 'replacementUserId' => $data->getReplacementUserId(), + 'replacementUserDisplayName' => $data->getReplacementUserDisplayName(), + ]); + } + + /** + * Set out-of-office absence + * + * @param string $firstDay First day of the absence in format `YYYY-MM-DD` + * @param string $lastDay Last day of the absence in format `YYYY-MM-DD` + * @param string $status Short text that is set as user status during the absence + * @param string $message Longer multiline message that is shown to others during the absence + * @param ?string $replacementUserId User id of the replacement user + * @return DataResponse<Http::STATUS_OK, DAVOutOfOfficeData, array{}>|DataResponse<Http::STATUS_BAD_REQUEST, array{error: 'firstDay'|'statusLength'}, array{}>|DataResponse<Http::STATUS_UNAUTHORIZED, null, array{}>|DataResponse<Http::STATUS_NOT_FOUND, null, array{}> + * + * 200: Absence data + * 400: When validation fails, e.g. data range error or the first day is not before the last day + * 401: When the user is not logged in + * 404: When the replacementUserId was provided but replacement user was not found + */ + #[NoAdminRequired] + public function setOutOfOffice( + string $firstDay, + string $lastDay, + string $status, + string $message, + ?string $replacementUserId, + ): DataResponse { + $user = $this->userSession?->getUser(); + if ($user === null) { + return new DataResponse(null, Http::STATUS_UNAUTHORIZED); + } + if (mb_strlen($status) > 100) { + return new DataResponse(['error' => 'statusLength'], Http::STATUS_BAD_REQUEST); + } + + $replacementUser = null; + if ($replacementUserId !== null) { + $replacementUser = $this->userManager->get($replacementUserId); + if ($replacementUser === null) { + return new DataResponse(null, Http::STATUS_NOT_FOUND); + } + } + + $parsedFirstDay = new DateTimeImmutable($firstDay); + $parsedLastDay = new DateTimeImmutable($lastDay); + if ($parsedFirstDay->getTimestamp() > $parsedLastDay->getTimestamp()) { + return new DataResponse(['error' => 'firstDay'], Http::STATUS_BAD_REQUEST); + } + + $data = $this->absenceService->createOrUpdateAbsence( + $user, + $firstDay, + $lastDay, + $status, + $message, + $replacementUserId, + $replacementUser?->getDisplayName() + ); + $this->coordinator->clearCache($user->getUID()); + + return new DataResponse([ + 'id' => $data->getId(), + 'userId' => $data->getUserId(), + 'firstDay' => $data->getFirstDay(), + 'lastDay' => $data->getLastDay(), + 'status' => $data->getStatus(), + 'message' => $data->getMessage(), + 'replacementUserId' => $data->getReplacementUserId(), + 'replacementUserDisplayName' => $data->getReplacementUserDisplayName(), + ]); + } + + /** + * Clear the out-of-office + * + * @return DataResponse<Http::STATUS_OK|Http::STATUS_UNAUTHORIZED, null, array{}> + * + * 200: When the absence was cleared successfully + * 401: When the user is not logged in + */ + #[NoAdminRequired] + public function clearOutOfOffice(): DataResponse { + $user = $this->userSession?->getUser(); + if ($user === null) { + return new DataResponse(null, Http::STATUS_UNAUTHORIZED); + } + + $this->absenceService->clearAbsence($user); + $this->coordinator->clearCache($user->getUID()); + return new DataResponse(null); + } +} |