fix(dav): Make current ooo info time-dependent

* 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>
This commit is contained in:
Christoph Wurst 2023-12-01 10:46:16 +01:00
parent e27e2e4395
commit 9a206c6282
No known key found for this signature in database
GPG Key ID: CC42AC2A7F0E56D8
7 changed files with 260 additions and 27 deletions

View File

@ -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'],
],

View File

@ -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->absenceMapper->findByUserId($userId);
$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);
}

View File

@ -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 {

View File

@ -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;

View File

@ -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",

View File

@ -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(),
];
}
}

View File

@ -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;
}