Skip to content

Commit

Permalink
feat(out-of-office): Add OCS endpoint to set and clear absence
Browse files Browse the repository at this point in the history
Signed-off-by: Joas Schilling <coding@schilljs.com>
  • Loading branch information
nickvergessen committed Dec 1, 2023
1 parent ffbc8c9 commit 7bfeeae
Show file tree
Hide file tree
Showing 3 changed files with 350 additions and 0 deletions.
2 changes: 2 additions & 0 deletions apps/dav/appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,7 @@
'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'],
],
];
77 changes: 77 additions & 0 deletions apps/dav/lib/Controller/OutOfOfficeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,18 @@

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
Expand All @@ -44,6 +48,9 @@ public function __construct(
string $appName,
IRequest $request,
private AbsenceMapper $absenceMapper,
private ?IUserSession $userSession,
private AbsenceService $absenceService,
private IAvailabilityCoordinator $coordinator,
) {
parent::__construct($appName, $request);
}
Expand Down Expand Up @@ -74,4 +81,74 @@ public function getCurrentOutOfOfficeData(string $userId): DataResponse {
'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);
}
}
271 changes: 271 additions & 0 deletions apps/dav/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}
}
}
}
}
}
}
}
}
},
Expand Down

0 comments on commit 7bfeeae

Please sign in to comment.