* If there is an out of office absence info and it happens now -> return data * Else: return no data Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>tags/v29.0.0beta1
@@ -33,7 +33,8 @@ 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#getCurrentOutOfOfficeData', 'url' => '/api/v1/outOfOffice/{userId}/now', 'verb' => 'GET'], | |||
['name' => 'out_of_office#getOutOfOffice', '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'], | |||
], |
@@ -27,7 +27,6 @@ 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; | |||
@@ -36,18 +35,20 @@ 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; | |||
/** | |||
* @psalm-import-type DAVOutOfOfficeData from ResponseDefinitions | |||
* @psalm-import-type DAVCurrentOutOfOfficeData from ResponseDefinitions | |||
*/ | |||
class OutOfOfficeController extends OCSController { | |||
public function __construct( | |||
string $appName, | |||
IRequest $request, | |||
private AbsenceMapper $absenceMapper, | |||
private IUserManager $userManager, | |||
private ?IUserSession $userSession, | |||
private AbsenceService $absenceService, | |||
private IAvailabilityCoordinator $coordinator, | |||
@@ -59,15 +60,45 @@ class OutOfOfficeController extends OCSController { | |||
* 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, DAVOutOfOfficeData, array{}>|DataResponse<Http::STATUS_NOT_FOUND, null, array{}> | |||
* @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->absenceMapper->findByUserId($userId); | |||
$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); | |||
} |
@@ -27,13 +27,24 @@ declare(strict_types=1); | |||
namespace OCA\DAV; | |||
/** | |||
* @psalm-type DAVOutOfOfficeData = array{ | |||
* @psalm-type DAVOutOfOfficeDataCommon = array{ | |||
* userId: string, | |||
* message: string, | |||
* } | |||
* | |||
* @psalm-type DAVOutOfOfficeData = DAVOutOfOfficeDataCommon&array{ | |||
* id: int, | |||
* userId: string, | |||
* firstDay: string, | |||
* lastDay: string, | |||
* status: string, | |||
* message: string, | |||
* } | |||
* | |||
* @todo this is a copy of \OCP\User\IOutOfOfficeData | |||
* @psalm-type DAVCurrentOutOfOfficeData = DAVOutOfOfficeDataCommon&array{ | |||
* id: string, | |||
* startDate: int, | |||
* endDate: int, | |||
* shortMessage: string, | |||
* } | |||
*/ | |||
class ResponseDefinitions { |
@@ -145,6 +145,22 @@ class AbsenceService { | |||
} | |||
} | |||
public function getCurrentAbsence(IUser $user): ?IOutOfOfficeData { | |||
try { | |||
$absence = $this->absenceMapper->findByUserId($user->getUID()); | |||
$oooData = $absence->toOutOufOfficeData( | |||
$user, | |||
$this->timezoneService->getUserTimezone($user->getUID()) ?? $this->timezoneService->getDefaultTimezone(), | |||
); | |||
if ($this->isInEffect($oooData)) { | |||
return $oooData; | |||
} | |||
} catch (DoesNotExistException) { | |||
// Nothing there to process | |||
} | |||
return null; | |||
} | |||
public function isInEffect(IOutOfOfficeData $absence): bool { | |||
$now = $this->timeFactory->getTime(); | |||
return $absence->getStartDate() <= $now && $absence->getEndDate() >= $now; |
@@ -42,6 +42,38 @@ | |||
} | |||
} | |||
}, | |||
"CurrentOutOfOfficeData": { | |||
"allOf": [ | |||
{ | |||
"$ref": "#/components/schemas/OutOfOfficeDataCommon" | |||
}, | |||
{ | |||
"type": "object", | |||
"required": [ | |||
"id", | |||
"startDate", | |||
"endDate", | |||
"shortMessage" | |||
], | |||
"properties": { | |||
"id": { | |||
"type": "string" | |||
}, | |||
"startDate": { | |||
"type": "integer", | |||
"format": "int64" | |||
}, | |||
"endDate": { | |||
"type": "integer", | |||
"format": "int64" | |||
}, | |||
"shortMessage": { | |||
"type": "string" | |||
} | |||
} | |||
} | |||
] | |||
}, | |||
"OCSMeta": { | |||
"type": "object", | |||
"required": [ | |||
@@ -67,32 +99,46 @@ | |||
} | |||
}, | |||
"OutOfOfficeData": { | |||
"allOf": [ | |||
{ | |||
"$ref": "#/components/schemas/OutOfOfficeDataCommon" | |||
}, | |||
{ | |||
"type": "object", | |||
"required": [ | |||
"id", | |||
"firstDay", | |||
"lastDay", | |||
"status" | |||
], | |||
"properties": { | |||
"id": { | |||
"type": "integer", | |||
"format": "int64" | |||
}, | |||
"firstDay": { | |||
"type": "string" | |||
}, | |||
"lastDay": { | |||
"type": "string" | |||
}, | |||
"status": { | |||
"type": "string" | |||
} | |||
} | |||
} | |||
] | |||
}, | |||
"OutOfOfficeDataCommon": { | |||
"type": "object", | |||
"required": [ | |||
"id", | |||
"userId", | |||
"firstDay", | |||
"lastDay", | |||
"status", | |||
"message" | |||
], | |||
"properties": { | |||
"id": { | |||
"type": "integer", | |||
"format": "int64" | |||
}, | |||
"userId": { | |||
"type": "string" | |||
}, | |||
"firstDay": { | |||
"type": "string" | |||
}, | |||
"lastDay": { | |||
"type": "string" | |||
}, | |||
"status": { | |||
"type": "string" | |||
}, | |||
"message": { | |||
"type": "string" | |||
} | |||
@@ -219,7 +265,7 @@ | |||
} | |||
} | |||
}, | |||
"/ocs/v2.php/apps/dav/api/v1/outOfOffice/{userId}": { | |||
"/ocs/v2.php/apps/dav/api/v1/outOfOffice/{userId}/now": { | |||
"get": { | |||
"operationId": "out_of_office-get-current-out-of-office-data", | |||
"summary": "Get the currently configured out-of-office data of a user.", | |||
@@ -255,6 +301,106 @@ | |||
} | |||
} | |||
], | |||
"responses": { | |||
"200": { | |||
"description": "Out-of-office 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/CurrentOutOfOfficeData" | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
}, | |||
"404": { | |||
"description": "No out-of-office data was found", | |||
"content": { | |||
"application/json": { | |||
"schema": { | |||
"type": "object", | |||
"required": [ | |||
"ocs" | |||
], | |||
"properties": { | |||
"ocs": { | |||
"type": "object", | |||
"required": [ | |||
"meta", | |||
"data" | |||
], | |||
"properties": { | |||
"meta": { | |||
"$ref": "#/components/schemas/OCSMeta" | |||
}, | |||
"data": { | |||
"nullable": true | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
}, | |||
"/ocs/v2.php/apps/dav/api/v1/outOfOffice/{userId}": { | |||
"get": { | |||
"operationId": "out_of_office-get-out-of-office", | |||
"summary": "Get the configured out-of-office data of a user.", | |||
"tags": [ | |||
"out_of_office" | |||
], | |||
"security": [ | |||
{ | |||
"bearer_auth": [] | |||
}, | |||
{ | |||
"basic_auth": [] | |||
} | |||
], | |||
"parameters": [ | |||
{ | |||
"name": "userId", | |||
"in": "path", | |||
"description": "The user id to get out-of-office data for.", | |||
"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": "Out-of-office data", |
@@ -60,4 +60,15 @@ class OutOfOfficeData implements IOutOfOfficeData { | |||
public function getMessage(): string { | |||
return $this->message; | |||
} | |||
public function jsonSerialize(): array { | |||
return [ | |||
'id' => $this->getId(), | |||
'userId' => $this->getUser()->getUID(), | |||
'startDate' => $this->getStartDate(), | |||
'endDate' => $this->getEndDate(), | |||
'shortMessage' => $this->getShortMessage(), | |||
'message' => $this->getMessage(), | |||
]; | |||
} | |||
} |
@@ -25,14 +25,24 @@ declare(strict_types=1); | |||
namespace OCP\User; | |||
use JsonSerializable; | |||
use OCP\IUser; | |||
/** | |||
* DTO to hold out-of-office information of a user | |||
* | |||
* @psalm-type OutOfOfficeData = array{ | |||
* id: string, | |||
* userId: string, | |||
* startDate: int, | |||
* endDate: int, | |||
* shortMessage: string, | |||
* message: string, | |||
* } | |||
* | |||
* @since 28.0.0 | |||
*/ | |||
interface IOutOfOfficeData { | |||
interface IOutOfOfficeData extends JsonSerializable { | |||
/** | |||
* Get the unique token assigned to the current out-of-office event | |||
* | |||
@@ -74,4 +84,11 @@ interface IOutOfOfficeData { | |||
* @since 28.0.0 | |||
*/ | |||
public function getMessage(): string; | |||
/** | |||
* @return OutOfOfficeData | |||
* | |||
* @since 28.0.0 | |||
*/ | |||
public function jsonSerialize(): array; | |||
} |