aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoas Schilling <coding@schilljs.com>2023-12-01 09:15:18 +0100
committerJoas Schilling <coding@schilljs.com>2023-12-01 10:57:40 +0100
commit7bfeeaedee4873eda6cb534c1cec2ce4910cbb9b (patch)
tree0eb1d3d5b93009252f841089481b4df86b689d50
parentffbc8c90bfce4237c74fe6a1cdb8091db70dce83 (diff)
downloadnextcloud-server-7bfeeaedee4873eda6cb534c1cec2ce4910cbb9b.tar.gz
nextcloud-server-7bfeeaedee4873eda6cb534c1cec2ce4910cbb9b.zip
feat(out-of-office): Add OCS endpoint to set and clear absence
Signed-off-by: Joas Schilling <coding@schilljs.com>
-rw-r--r--apps/dav/appinfo/routes.php2
-rw-r--r--apps/dav/lib/Controller/OutOfOfficeController.php77
-rw-r--r--apps/dav/openapi.json271
3 files changed, 350 insertions, 0 deletions
diff --git a/apps/dav/appinfo/routes.php b/apps/dav/appinfo/routes.php
index 1b2fa0094bf..d4a9f4cbeeb 100644
--- a/apps/dav/appinfo/routes.php
+++ b/apps/dav/appinfo/routes.php
@@ -36,5 +36,7 @@ return [
'ocs' => [
['name' => 'direct#getUrl', 'url' => '/api/v1/direct', 'verb' => 'POST'],
['name' => 'out_of_office#getCurrentOutOfOfficeData', 'url' => '/api/v1/outOfOffice/{userId}', 'verb' => 'GET'],
+ ['name' => 'out_of_office#setOutOfOffice', 'url' => '/api/v1/outOfOffice/{userId}', 'verb' => 'POST'],
+ ['name' => 'out_of_office#clearOutOfOffice', 'url' => '/api/v1/outOfOffice/{userId}', 'verb' => 'DELETE'],
],
];
diff --git a/apps/dav/lib/Controller/OutOfOfficeController.php b/apps/dav/lib/Controller/OutOfOfficeController.php
index e86f116c3b1..ffac1247a6c 100644
--- a/apps/dav/lib/Controller/OutOfOfficeController.php
+++ b/apps/dav/lib/Controller/OutOfOfficeController.php
@@ -26,14 +26,18 @@ declare(strict_types=1);
namespace OCA\DAV\Controller;
+use DateTimeImmutable;
use OCA\DAV\Db\AbsenceMapper;
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\IUserSession;
+use OCP\User\IAvailabilityCoordinator;
/**
* @psalm-import-type DAVOutOfOfficeData from ResponseDefinitions
@@ -44,6 +48,9 @@ class OutOfOfficeController extends OCSController {
string $appName,
IRequest $request,
private AbsenceMapper $absenceMapper,
+ private ?IUserSession $userSession,
+ private AbsenceService $absenceService,
+ private IAvailabilityCoordinator $coordinator,
) {
parent::__construct($appName, $request);
}
@@ -74,4 +81,74 @@ class OutOfOfficeController extends OCSController {
'message' => $data->getMessage(),
]);
}
+
+ /**
+ * 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
+ * @return DataResponse<Http::STATUS_OK, DAVOutOfOfficeData, array{}>|DataResponse<Http::STATUS_BAD_REQUEST, array{error: 'firstDay'}, array{}>|DataResponse<Http::STATUS_UNAUTHORIZED, null, array{}>
+ *
+ * 200: Absence data
+ * 400: When the first day is not before the last day
+ * 401: When the user is not logged in
+ */
+ #[NoAdminRequired]
+ public function setOutOfOffice(
+ string $firstDay,
+ string $lastDay,
+ string $status,
+ string $message,
+ ): DataResponse {
+ $user = $this->userSession?->getUser();
+ if ($user === null) {
+ return new DataResponse(null, Http::STATUS_UNAUTHORIZED);
+ }
+
+ $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,
+ );
+ $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(),
+ ]);
+ }
+
+ /**
+ * 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);
+ }
}
diff --git a/apps/dav/openapi.json b/apps/dav/openapi.json
index c8ae5a96206..a235e3bff1d 100644
--- a/apps/dav/openapi.json
+++ b/apps/dav/openapi.json
@@ -317,6 +317,277 @@
}
}
}
+ },
+ "post": {
+ "operationId": "out_of_office-set-out-of-office",
+ "summary": "Set out-of-office absence",
+ "tags": [
+ "out_of_office"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "firstDay",
+ "in": "query",
+ "description": "First day of the absence in format `YYYY-MM-DD`",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "lastDay",
+ "in": "query",
+ "description": "Last day of the absence in format `YYYY-MM-DD`",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "status",
+ "in": "query",
+ "description": "Short text that is set as user status during the absence",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "message",
+ "in": "query",
+ "description": "Longer multiline message that is shown to others during the absence",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "userId",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Absence data",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "$ref": "#/components/schemas/OutOfOfficeData"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "When the first day is not before the last day",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "error"
+ ],
+ "properties": {
+ "error": {
+ "type": "string",
+ "enum": [
+ "firstDay"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "When the user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "nullable": true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "operationId": "out_of_office-clear-out-of-office",
+ "summary": "Clear the out-of-office",
+ "tags": [
+ "out_of_office"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "userId",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "When the absence was cleared successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "nullable": true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "When the user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "nullable": true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
}
},