[skipci] Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at> Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>tags/v28.0.0beta2
], | ], | ||||
'ocs' => [ | 'ocs' => [ | ||||
['name' => 'direct#getUrl', 'url' => '/api/v1/direct', 'verb' => 'POST'], | ['name' => 'direct#getUrl', 'url' => '/api/v1/direct', 'verb' => 'POST'], | ||||
['name' => 'out_of_office#getCurrentOutOfOfficeData', 'url' => '/api/v1/outOfOffice/{userId}', 'verb' => 'GET'], | |||||
], | ], | ||||
]; | ]; |
'OCA\\DAV\\Controller\\BirthdayCalendarController' => $baseDir . '/../lib/Controller/BirthdayCalendarController.php', | 'OCA\\DAV\\Controller\\BirthdayCalendarController' => $baseDir . '/../lib/Controller/BirthdayCalendarController.php', | ||||
'OCA\\DAV\\Controller\\DirectController' => $baseDir . '/../lib/Controller/DirectController.php', | 'OCA\\DAV\\Controller\\DirectController' => $baseDir . '/../lib/Controller/DirectController.php', | ||||
'OCA\\DAV\\Controller\\InvitationResponseController' => $baseDir . '/../lib/Controller/InvitationResponseController.php', | 'OCA\\DAV\\Controller\\InvitationResponseController' => $baseDir . '/../lib/Controller/InvitationResponseController.php', | ||||
'OCA\\DAV\\Controller\\OutOfOfficeController' => $baseDir . '/../lib/Controller/OutOfOfficeController.php', | |||||
'OCA\\DAV\\DAV\\CustomPropertiesBackend' => $baseDir . '/../lib/DAV/CustomPropertiesBackend.php', | 'OCA\\DAV\\DAV\\CustomPropertiesBackend' => $baseDir . '/../lib/DAV/CustomPropertiesBackend.php', | ||||
'OCA\\DAV\\DAV\\GroupPrincipalBackend' => $baseDir . '/../lib/DAV/GroupPrincipalBackend.php', | 'OCA\\DAV\\DAV\\GroupPrincipalBackend' => $baseDir . '/../lib/DAV/GroupPrincipalBackend.php', | ||||
'OCA\\DAV\\DAV\\PublicAuth' => $baseDir . '/../lib/DAV/PublicAuth.php', | 'OCA\\DAV\\DAV\\PublicAuth' => $baseDir . '/../lib/DAV/PublicAuth.php', | ||||
'OCA\\DAV\\Profiler\\ProfilerPlugin' => $baseDir . '/../lib/Profiler/ProfilerPlugin.php', | 'OCA\\DAV\\Profiler\\ProfilerPlugin' => $baseDir . '/../lib/Profiler/ProfilerPlugin.php', | ||||
'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningNode' => $baseDir . '/../lib/Provisioning/Apple/AppleProvisioningNode.php', | 'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningNode' => $baseDir . '/../lib/Provisioning/Apple/AppleProvisioningNode.php', | ||||
'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningPlugin' => $baseDir . '/../lib/Provisioning/Apple/AppleProvisioningPlugin.php', | 'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningPlugin' => $baseDir . '/../lib/Provisioning/Apple/AppleProvisioningPlugin.php', | ||||
'OCA\\DAV\\ResponseDefinitions' => $baseDir . '/../lib/ResponseDefinitions.php', | |||||
'OCA\\DAV\\RootCollection' => $baseDir . '/../lib/RootCollection.php', | 'OCA\\DAV\\RootCollection' => $baseDir . '/../lib/RootCollection.php', | ||||
'OCA\\DAV\\Search\\ACalendarSearchProvider' => $baseDir . '/../lib/Search/ACalendarSearchProvider.php', | 'OCA\\DAV\\Search\\ACalendarSearchProvider' => $baseDir . '/../lib/Search/ACalendarSearchProvider.php', | ||||
'OCA\\DAV\\Search\\ContactsSearchProvider' => $baseDir . '/../lib/Search/ContactsSearchProvider.php', | 'OCA\\DAV\\Search\\ContactsSearchProvider' => $baseDir . '/../lib/Search/ContactsSearchProvider.php', |
'OCA\\DAV\\Controller\\BirthdayCalendarController' => __DIR__ . '/..' . '/../lib/Controller/BirthdayCalendarController.php', | 'OCA\\DAV\\Controller\\BirthdayCalendarController' => __DIR__ . '/..' . '/../lib/Controller/BirthdayCalendarController.php', | ||||
'OCA\\DAV\\Controller\\DirectController' => __DIR__ . '/..' . '/../lib/Controller/DirectController.php', | 'OCA\\DAV\\Controller\\DirectController' => __DIR__ . '/..' . '/../lib/Controller/DirectController.php', | ||||
'OCA\\DAV\\Controller\\InvitationResponseController' => __DIR__ . '/..' . '/../lib/Controller/InvitationResponseController.php', | 'OCA\\DAV\\Controller\\InvitationResponseController' => __DIR__ . '/..' . '/../lib/Controller/InvitationResponseController.php', | ||||
'OCA\\DAV\\Controller\\OutOfOfficeController' => __DIR__ . '/..' . '/../lib/Controller/OutOfOfficeController.php', | |||||
'OCA\\DAV\\DAV\\CustomPropertiesBackend' => __DIR__ . '/..' . '/../lib/DAV/CustomPropertiesBackend.php', | 'OCA\\DAV\\DAV\\CustomPropertiesBackend' => __DIR__ . '/..' . '/../lib/DAV/CustomPropertiesBackend.php', | ||||
'OCA\\DAV\\DAV\\GroupPrincipalBackend' => __DIR__ . '/..' . '/../lib/DAV/GroupPrincipalBackend.php', | 'OCA\\DAV\\DAV\\GroupPrincipalBackend' => __DIR__ . '/..' . '/../lib/DAV/GroupPrincipalBackend.php', | ||||
'OCA\\DAV\\DAV\\PublicAuth' => __DIR__ . '/..' . '/../lib/DAV/PublicAuth.php', | 'OCA\\DAV\\DAV\\PublicAuth' => __DIR__ . '/..' . '/../lib/DAV/PublicAuth.php', | ||||
'OCA\\DAV\\Profiler\\ProfilerPlugin' => __DIR__ . '/..' . '/../lib/Profiler/ProfilerPlugin.php', | 'OCA\\DAV\\Profiler\\ProfilerPlugin' => __DIR__ . '/..' . '/../lib/Profiler/ProfilerPlugin.php', | ||||
'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningNode' => __DIR__ . '/..' . '/../lib/Provisioning/Apple/AppleProvisioningNode.php', | 'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningNode' => __DIR__ . '/..' . '/../lib/Provisioning/Apple/AppleProvisioningNode.php', | ||||
'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningPlugin' => __DIR__ . '/..' . '/../lib/Provisioning/Apple/AppleProvisioningPlugin.php', | 'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningPlugin' => __DIR__ . '/..' . '/../lib/Provisioning/Apple/AppleProvisioningPlugin.php', | ||||
'OCA\\DAV\\ResponseDefinitions' => __DIR__ . '/..' . '/../lib/ResponseDefinitions.php', | |||||
'OCA\\DAV\\RootCollection' => __DIR__ . '/..' . '/../lib/RootCollection.php', | 'OCA\\DAV\\RootCollection' => __DIR__ . '/..' . '/../lib/RootCollection.php', | ||||
'OCA\\DAV\\Search\\ACalendarSearchProvider' => __DIR__ . '/..' . '/../lib/Search/ACalendarSearchProvider.php', | 'OCA\\DAV\\Search\\ACalendarSearchProvider' => __DIR__ . '/..' . '/../lib/Search/ACalendarSearchProvider.php', | ||||
'OCA\\DAV\\Search\\ContactsSearchProvider' => __DIR__ . '/..' . '/../lib/Search/ContactsSearchProvider.php', | 'OCA\\DAV\\Search\\ContactsSearchProvider' => __DIR__ . '/..' . '/../lib/Search/ContactsSearchProvider.php', |
<?php | |||||
declare(strict_types=1); | |||||
/** | |||||
* @copyright Copyright (c) 2023 Richard Steinmetz <richard@steinmetz.cloud> | |||||
* | |||||
* @author Richard Steinmetz <richard@steinmetz.cloud> | |||||
* | |||||
* @license AGPL-3.0-or-later | |||||
* | |||||
* This program is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation, either version 3 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
* | |||||
*/ | |||||
namespace OCA\DAV\Controller; | |||||
use OCA\DAV\Db\AbsenceMapper; | |||||
use OCA\DAV\ResponseDefinitions; | |||||
use OCP\AppFramework\Db\DoesNotExistException; | |||||
use OCP\AppFramework\Http; | |||||
use OCP\AppFramework\Http\DataResponse; | |||||
use OCP\AppFramework\OCSController; | |||||
use OCP\IRequest; | |||||
/** | |||||
* @psalm-import-type DAVOutOfOfficeData from ResponseDefinitions | |||||
*/ | |||||
class OutOfOfficeController extends OCSController { | |||||
public function __construct( | |||||
string $appName, | |||||
IRequest $request, | |||||
private AbsenceMapper $absenceMapper, | |||||
) { | |||||
parent::__construct($appName, $request); | |||||
} | |||||
/** | |||||
* Get the currently configured out-of-office data of a user. | |||||
* | |||||
* @NoAdminRequired | |||||
* @NoCSRFRequired | |||||
* | |||||
* @param string $userId The user id to get out-of-office data for. | |||||
* @return DataResponse<Http::STATUS_OK|Http::STATUS_NOT_FOUND, ?DAVOutOfOfficeData, array{}> | |||||
* | |||||
* 200: Out-of-office data | |||||
* 404: No out-of-office data was found | |||||
*/ | |||||
public function getCurrentOutOfOfficeData(string $userId): DataResponse { | |||||
try { | |||||
$data = $this->absenceMapper->findByUserId($userId); | |||||
} 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(), | |||||
]); | |||||
} | |||||
} |
namespace OCA\DAV\Db; | namespace OCA\DAV\Db; | ||||
use DateTimeImmutable; | |||||
use InvalidArgumentException; | |||||
use JsonSerializable; | use JsonSerializable; | ||||
use OC\User\OutOfOfficeData; | |||||
use OCP\AppFramework\Db\Entity; | use OCP\AppFramework\Db\Entity; | ||||
use OCP\IUser; | |||||
use OCP\User\IOutOfOfficeData; | |||||
/** | /** | ||||
* @method string getUserId() | * @method string getUserId() | ||||
*/ | */ | ||||
class Absence extends Entity implements JsonSerializable { | class Absence extends Entity implements JsonSerializable { | ||||
protected string $userId = ''; | protected string $userId = ''; | ||||
/** Inclusive, formatted as YYYY-MM-DD */ | |||||
protected string $firstDay = ''; | protected string $firstDay = ''; | ||||
/** Inclusive, formatted as YYYY-MM-DD */ | |||||
protected string $lastDay = ''; | protected string $lastDay = ''; | ||||
protected string $status = ''; | protected string $status = ''; | ||||
protected string $message = ''; | protected string $message = ''; | ||||
$this->addType('message', 'string'); | $this->addType('message', 'string'); | ||||
} | } | ||||
public function toOutOufOfficeData(IUser $user): IOutOfOfficeData { | |||||
if ($user->getUID() !== $this->getUserId()) { | |||||
throw new InvalidArgumentException("The user doesn't match the user id of this absence! Expected " . $this->getUserId() . ", got " . $user->getUID()); | |||||
} | |||||
//$user = $userManager->get($this->getUserId()); | |||||
$startDate = new DateTimeImmutable($this->getFirstDay()); | |||||
$endDate = new DateTimeImmutable($this->getLastDay()); | |||||
return new OutOfOfficeData( | |||||
(string)$this->getId(), | |||||
$user, | |||||
$startDate->getTimestamp(), | |||||
$endDate->getTimestamp(), | |||||
$this->getStatus(), | |||||
$this->getMessage(), | |||||
); | |||||
} | |||||
public function jsonSerialize(): array { | public function jsonSerialize(): array { | ||||
return [ | return [ | ||||
'userId' => $this->userId, | 'userId' => $this->userId, |
<?php | |||||
declare(strict_types=1); | |||||
/** | |||||
* @copyright Copyright (c) 2023 Richard Steinmetz <richard@steinmetz.cloud> | |||||
* | |||||
* @author Richard Steinmetz <richard@steinmetz.cloud> | |||||
* | |||||
* @license AGPL-3.0-or-later | |||||
* | |||||
* This program is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation, either version 3 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
* | |||||
*/ | |||||
namespace OCA\DAV; | |||||
/** | |||||
* @psalm-type DAVOutOfOfficeData = array{ | |||||
* id: int, | |||||
* userId: string, | |||||
* firstDay: string, | |||||
* lastDay: string, | |||||
* status: string, | |||||
* message: string, | |||||
* } | |||||
*/ | |||||
class ResponseDefinitions { | |||||
} |
namespace OCA\DAV\Service; | namespace OCA\DAV\Service; | ||||
use InvalidArgumentException; | |||||
use OCA\DAV\Db\Absence; | use OCA\DAV\Db\Absence; | ||||
use OCA\DAV\Db\AbsenceMapper; | use OCA\DAV\Db\AbsenceMapper; | ||||
use OCP\AppFramework\Db\DoesNotExistException; | use OCP\AppFramework\Db\DoesNotExistException; | ||||
use OCP\EventDispatcher\IEventDispatcher; | |||||
use OCP\IUserManager; | |||||
use OCP\User\Events\OutOfOfficeChangedEvent; | |||||
use OCP\User\Events\OutOfOfficeClearedEvent; | |||||
use OCP\User\Events\OutOfOfficeScheduledEvent; | |||||
class AbsenceService { | class AbsenceService { | ||||
public function __construct( | public function __construct( | ||||
private AbsenceMapper $absenceMapper, | private AbsenceMapper $absenceMapper, | ||||
private IEventDispatcher $eventDispatcher, | |||||
private IUserManager $userManager, | |||||
) { | ) { | ||||
} | } | ||||
/** | /** | ||||
* @param string $firstDay The first day (inclusive) of the absence formatted as YYYY-MM-DD. | |||||
* @param string $lastDay The last day (inclusive) of the absence formatted as YYYY-MM-DD. | |||||
* | |||||
* @throws \OCP\DB\Exception | * @throws \OCP\DB\Exception | ||||
* @throws InvalidArgumentException If no user with the given user id exists. | |||||
*/ | */ | ||||
public function createOrUpdateAbsence( | public function createOrUpdateAbsence( | ||||
string $userId, | string $userId, | ||||
$absence->setStatus($status); | $absence->setStatus($status); | ||||
$absence->setMessage($message); | $absence->setMessage($message); | ||||
// TODO: this method should probably just take a IUser instance | |||||
$user = $this->userManager->get($userId); | |||||
if ($user === null) { | |||||
throw new InvalidArgumentException("User $userId does not exist"); | |||||
} | |||||
$eventData = $absence->toOutOufOfficeData($user); | |||||
if ($absence->getId() === null) { | if ($absence->getId() === null) { | ||||
$this->eventDispatcher->dispatchTyped(new OutOfOfficeScheduledEvent($eventData)); | |||||
return $this->absenceMapper->insert($absence); | return $this->absenceMapper->insert($absence); | ||||
} | } | ||||
$this->eventDispatcher->dispatchTyped(new OutOfOfficeChangedEvent($eventData)); | |||||
return $this->absenceMapper->update($absence); | return $this->absenceMapper->update($absence); | ||||
} | } | ||||
* @throws \OCP\DB\Exception | * @throws \OCP\DB\Exception | ||||
*/ | */ | ||||
public function clearAbsence(string $userId): void { | public function clearAbsence(string $userId): void { | ||||
$this->absenceMapper->deleteByUserId($userId); | |||||
try { | |||||
$absence = $this->absenceMapper->findByUserId($userId); | |||||
} catch (DoesNotExistException $e) { | |||||
// Nothing to clear | |||||
return; | |||||
} | |||||
$this->absenceMapper->delete($absence); | |||||
// TODO: this method should probably just take a IUser instance | |||||
$user = $this->userManager->get($userId); | |||||
if ($user === null) { | |||||
throw new InvalidArgumentException("User $userId does not exist"); | |||||
} | |||||
$eventData = $absence->toOutOufOfficeData($user); | |||||
$this->eventDispatcher->dispatchTyped(new OutOfOfficeClearedEvent($eventData)); | |||||
} | } | ||||
} | } | ||||
"type": "string" | "type": "string" | ||||
} | } | ||||
} | } | ||||
}, | |||||
"OutOfOfficeData": { | |||||
"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" | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
} | } | ||||
} | } | ||||
} | } | ||||
}, | |||||
"/ocs/v2.php/apps/dav/api/v1/outOfOffice/{userId}": { | |||||
"get": { | |||||
"operationId": "out_of_office-get-current-out-of-office-data", | |||||
"summary": "Get the currently 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", | |||||
"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", | |||||
"nullable": true | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
}, | |||||
"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": { | |||||
"$ref": "#/components/schemas/OutOfOfficeData", | |||||
"nullable": true | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | } | ||||
}, | }, | ||||
"tags": [] | "tags": [] |
'OCP\\User\\Events\\BeforeUserLoggedInEvent' => $baseDir . '/lib/public/User/Events/BeforeUserLoggedInEvent.php', | 'OCP\\User\\Events\\BeforeUserLoggedInEvent' => $baseDir . '/lib/public/User/Events/BeforeUserLoggedInEvent.php', | ||||
'OCP\\User\\Events\\BeforeUserLoggedInWithCookieEvent' => $baseDir . '/lib/public/User/Events/BeforeUserLoggedInWithCookieEvent.php', | 'OCP\\User\\Events\\BeforeUserLoggedInWithCookieEvent' => $baseDir . '/lib/public/User/Events/BeforeUserLoggedInWithCookieEvent.php', | ||||
'OCP\\User\\Events\\BeforeUserLoggedOutEvent' => $baseDir . '/lib/public/User/Events/BeforeUserLoggedOutEvent.php', | 'OCP\\User\\Events\\BeforeUserLoggedOutEvent' => $baseDir . '/lib/public/User/Events/BeforeUserLoggedOutEvent.php', | ||||
'OCP\\User\\Events\\OutOfOfficeChangedEvent' => $baseDir . '/lib/public/User/Events/OutOfOfficeChangedEvent.php', | |||||
'OCP\\User\\Events\\OutOfOfficeClearedEvent' => $baseDir . '/lib/public/User/Events/OutOfOfficeClearedEvent.php', | |||||
'OCP\\User\\Events\\OutOfOfficeScheduledEvent' => $baseDir . '/lib/public/User/Events/OutOfOfficeScheduledEvent.php', | |||||
'OCP\\User\\Events\\PasswordUpdatedEvent' => $baseDir . '/lib/public/User/Events/PasswordUpdatedEvent.php', | 'OCP\\User\\Events\\PasswordUpdatedEvent' => $baseDir . '/lib/public/User/Events/PasswordUpdatedEvent.php', | ||||
'OCP\\User\\Events\\PostLoginEvent' => $baseDir . '/lib/public/User/Events/PostLoginEvent.php', | 'OCP\\User\\Events\\PostLoginEvent' => $baseDir . '/lib/public/User/Events/PostLoginEvent.php', | ||||
'OCP\\User\\Events\\UserChangedEvent' => $baseDir . '/lib/public/User/Events/UserChangedEvent.php', | 'OCP\\User\\Events\\UserChangedEvent' => $baseDir . '/lib/public/User/Events/UserChangedEvent.php', | ||||
'OCP\\User\\Events\\UserLoggedInWithCookieEvent' => $baseDir . '/lib/public/User/Events/UserLoggedInWithCookieEvent.php', | 'OCP\\User\\Events\\UserLoggedInWithCookieEvent' => $baseDir . '/lib/public/User/Events/UserLoggedInWithCookieEvent.php', | ||||
'OCP\\User\\Events\\UserLoggedOutEvent' => $baseDir . '/lib/public/User/Events/UserLoggedOutEvent.php', | 'OCP\\User\\Events\\UserLoggedOutEvent' => $baseDir . '/lib/public/User/Events/UserLoggedOutEvent.php', | ||||
'OCP\\User\\GetQuotaEvent' => $baseDir . '/lib/public/User/GetQuotaEvent.php', | 'OCP\\User\\GetQuotaEvent' => $baseDir . '/lib/public/User/GetQuotaEvent.php', | ||||
'OCP\\User\\IAvailabilityCoordinator' => $baseDir . '/lib/public/User/IAvailabilityCoordinator.php', | |||||
'OCP\\User\\IOutOfOfficeData' => $baseDir . '/lib/public/User/IOutOfOfficeData.php', | |||||
'OCP\\Util' => $baseDir . '/lib/public/Util.php', | 'OCP\\Util' => $baseDir . '/lib/public/Util.php', | ||||
'OCP\\WorkflowEngine\\EntityContext\\IContextPortation' => $baseDir . '/lib/public/WorkflowEngine/EntityContext/IContextPortation.php', | 'OCP\\WorkflowEngine\\EntityContext\\IContextPortation' => $baseDir . '/lib/public/WorkflowEngine/EntityContext/IContextPortation.php', | ||||
'OCP\\WorkflowEngine\\EntityContext\\IDisplayName' => $baseDir . '/lib/public/WorkflowEngine/EntityContext/IDisplayName.php', | 'OCP\\WorkflowEngine\\EntityContext\\IDisplayName' => $baseDir . '/lib/public/WorkflowEngine/EntityContext/IDisplayName.php', | ||||
'OC\\Updater\\VersionCheck' => $baseDir . '/lib/private/Updater/VersionCheck.php', | 'OC\\Updater\\VersionCheck' => $baseDir . '/lib/private/Updater/VersionCheck.php', | ||||
'OC\\UserStatus\\ISettableProvider' => $baseDir . '/lib/private/UserStatus/ISettableProvider.php', | 'OC\\UserStatus\\ISettableProvider' => $baseDir . '/lib/private/UserStatus/ISettableProvider.php', | ||||
'OC\\UserStatus\\Manager' => $baseDir . '/lib/private/UserStatus/Manager.php', | 'OC\\UserStatus\\Manager' => $baseDir . '/lib/private/UserStatus/Manager.php', | ||||
'OC\\User\\AvailabilityCoordinator' => $baseDir . '/lib/private/User/AvailabilityCoordinator.php', | |||||
'OC\\User\\Backend' => $baseDir . '/lib/private/User/Backend.php', | 'OC\\User\\Backend' => $baseDir . '/lib/private/User/Backend.php', | ||||
'OC\\User\\Database' => $baseDir . '/lib/private/User/Database.php', | 'OC\\User\\Database' => $baseDir . '/lib/private/User/Database.php', | ||||
'OC\\User\\DisplayNameCache' => $baseDir . '/lib/private/User/DisplayNameCache.php', | 'OC\\User\\DisplayNameCache' => $baseDir . '/lib/private/User/DisplayNameCache.php', | ||||
'OC\\User\\LoginException' => $baseDir . '/lib/private/User/LoginException.php', | 'OC\\User\\LoginException' => $baseDir . '/lib/private/User/LoginException.php', | ||||
'OC\\User\\Manager' => $baseDir . '/lib/private/User/Manager.php', | 'OC\\User\\Manager' => $baseDir . '/lib/private/User/Manager.php', | ||||
'OC\\User\\NoUserException' => $baseDir . '/lib/private/User/NoUserException.php', | 'OC\\User\\NoUserException' => $baseDir . '/lib/private/User/NoUserException.php', | ||||
'OC\\User\\OutOfOfficeData' => $baseDir . '/lib/private/User/OutOfOfficeData.php', | |||||
'OC\\User\\Session' => $baseDir . '/lib/private/User/Session.php', | 'OC\\User\\Session' => $baseDir . '/lib/private/User/Session.php', | ||||
'OC\\User\\User' => $baseDir . '/lib/private/User/User.php', | 'OC\\User\\User' => $baseDir . '/lib/private/User/User.php', | ||||
'OC_API' => $baseDir . '/lib/private/legacy/OC_API.php', | 'OC_API' => $baseDir . '/lib/private/legacy/OC_API.php', |
'OCP\\User\\Events\\BeforeUserLoggedInEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/BeforeUserLoggedInEvent.php', | 'OCP\\User\\Events\\BeforeUserLoggedInEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/BeforeUserLoggedInEvent.php', | ||||
'OCP\\User\\Events\\BeforeUserLoggedInWithCookieEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/BeforeUserLoggedInWithCookieEvent.php', | 'OCP\\User\\Events\\BeforeUserLoggedInWithCookieEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/BeforeUserLoggedInWithCookieEvent.php', | ||||
'OCP\\User\\Events\\BeforeUserLoggedOutEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/BeforeUserLoggedOutEvent.php', | 'OCP\\User\\Events\\BeforeUserLoggedOutEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/BeforeUserLoggedOutEvent.php', | ||||
'OCP\\User\\Events\\OutOfOfficeChangedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/OutOfOfficeChangedEvent.php', | |||||
'OCP\\User\\Events\\OutOfOfficeClearedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/OutOfOfficeClearedEvent.php', | |||||
'OCP\\User\\Events\\OutOfOfficeScheduledEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/OutOfOfficeScheduledEvent.php', | |||||
'OCP\\User\\Events\\PasswordUpdatedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/PasswordUpdatedEvent.php', | 'OCP\\User\\Events\\PasswordUpdatedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/PasswordUpdatedEvent.php', | ||||
'OCP\\User\\Events\\PostLoginEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/PostLoginEvent.php', | 'OCP\\User\\Events\\PostLoginEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/PostLoginEvent.php', | ||||
'OCP\\User\\Events\\UserChangedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserChangedEvent.php', | 'OCP\\User\\Events\\UserChangedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserChangedEvent.php', | ||||
'OCP\\User\\Events\\UserLoggedInWithCookieEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserLoggedInWithCookieEvent.php', | 'OCP\\User\\Events\\UserLoggedInWithCookieEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserLoggedInWithCookieEvent.php', | ||||
'OCP\\User\\Events\\UserLoggedOutEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserLoggedOutEvent.php', | 'OCP\\User\\Events\\UserLoggedOutEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserLoggedOutEvent.php', | ||||
'OCP\\User\\GetQuotaEvent' => __DIR__ . '/../../..' . '/lib/public/User/GetQuotaEvent.php', | 'OCP\\User\\GetQuotaEvent' => __DIR__ . '/../../..' . '/lib/public/User/GetQuotaEvent.php', | ||||
'OCP\\User\\IAvailabilityCoordinator' => __DIR__ . '/../../..' . '/lib/public/User/IAvailabilityCoordinator.php', | |||||
'OCP\\User\\IOutOfOfficeData' => __DIR__ . '/../../..' . '/lib/public/User/IOutOfOfficeData.php', | |||||
'OCP\\Util' => __DIR__ . '/../../..' . '/lib/public/Util.php', | 'OCP\\Util' => __DIR__ . '/../../..' . '/lib/public/Util.php', | ||||
'OCP\\WorkflowEngine\\EntityContext\\IContextPortation' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/EntityContext/IContextPortation.php', | 'OCP\\WorkflowEngine\\EntityContext\\IContextPortation' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/EntityContext/IContextPortation.php', | ||||
'OCP\\WorkflowEngine\\EntityContext\\IDisplayName' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/EntityContext/IDisplayName.php', | 'OCP\\WorkflowEngine\\EntityContext\\IDisplayName' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/EntityContext/IDisplayName.php', | ||||
'OC\\Updater\\VersionCheck' => __DIR__ . '/../../..' . '/lib/private/Updater/VersionCheck.php', | 'OC\\Updater\\VersionCheck' => __DIR__ . '/../../..' . '/lib/private/Updater/VersionCheck.php', | ||||
'OC\\UserStatus\\ISettableProvider' => __DIR__ . '/../../..' . '/lib/private/UserStatus/ISettableProvider.php', | 'OC\\UserStatus\\ISettableProvider' => __DIR__ . '/../../..' . '/lib/private/UserStatus/ISettableProvider.php', | ||||
'OC\\UserStatus\\Manager' => __DIR__ . '/../../..' . '/lib/private/UserStatus/Manager.php', | 'OC\\UserStatus\\Manager' => __DIR__ . '/../../..' . '/lib/private/UserStatus/Manager.php', | ||||
'OC\\User\\AvailabilityCoordinator' => __DIR__ . '/../../..' . '/lib/private/User/AvailabilityCoordinator.php', | |||||
'OC\\User\\Backend' => __DIR__ . '/../../..' . '/lib/private/User/Backend.php', | 'OC\\User\\Backend' => __DIR__ . '/../../..' . '/lib/private/User/Backend.php', | ||||
'OC\\User\\Database' => __DIR__ . '/../../..' . '/lib/private/User/Database.php', | 'OC\\User\\Database' => __DIR__ . '/../../..' . '/lib/private/User/Database.php', | ||||
'OC\\User\\DisplayNameCache' => __DIR__ . '/../../..' . '/lib/private/User/DisplayNameCache.php', | 'OC\\User\\DisplayNameCache' => __DIR__ . '/../../..' . '/lib/private/User/DisplayNameCache.php', | ||||
'OC\\User\\LoginException' => __DIR__ . '/../../..' . '/lib/private/User/LoginException.php', | 'OC\\User\\LoginException' => __DIR__ . '/../../..' . '/lib/private/User/LoginException.php', | ||||
'OC\\User\\Manager' => __DIR__ . '/../../..' . '/lib/private/User/Manager.php', | 'OC\\User\\Manager' => __DIR__ . '/../../..' . '/lib/private/User/Manager.php', | ||||
'OC\\User\\NoUserException' => __DIR__ . '/../../..' . '/lib/private/User/NoUserException.php', | 'OC\\User\\NoUserException' => __DIR__ . '/../../..' . '/lib/private/User/NoUserException.php', | ||||
'OC\\User\\OutOfOfficeData' => __DIR__ . '/../../..' . '/lib/private/User/OutOfOfficeData.php', | |||||
'OC\\User\\Session' => __DIR__ . '/../../..' . '/lib/private/User/Session.php', | 'OC\\User\\Session' => __DIR__ . '/../../..' . '/lib/private/User/Session.php', | ||||
'OC\\User\\User' => __DIR__ . '/../../..' . '/lib/private/User/User.php', | 'OC\\User\\User' => __DIR__ . '/../../..' . '/lib/private/User/User.php', | ||||
'OC_API' => __DIR__ . '/../../..' . '/lib/private/legacy/OC_API.php', | 'OC_API' => __DIR__ . '/../../..' . '/lib/private/legacy/OC_API.php', |
<?php | |||||
declare(strict_types=1); | |||||
/** | |||||
* @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at> | |||||
* | |||||
* @author 2023 Christoph Wurst <christoph@winzerhof-wurst.at> | |||||
* @author Richard Steinmetz <richard@steinmetz.cloud> | |||||
* | |||||
* @license GNU AGPL version 3 or any later version | |||||
* | |||||
* This program is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU Affero General Public License as | |||||
* published by the Free Software Foundation, either version 3 of the | |||||
* License, or (at your option) any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU Affero General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU Affero General Public License | |||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
namespace OC\User; | |||||
use JsonException; | |||||
use OCA\DAV\Db\AbsenceMapper; | |||||
use OCP\AppFramework\Db\DoesNotExistException; | |||||
use OCP\ICache; | |||||
use OCP\ICacheFactory; | |||||
use OCP\IUser; | |||||
use OCP\User\IAvailabilityCoordinator; | |||||
use OCP\User\IOutOfOfficeData; | |||||
use Psr\Log\LoggerInterface; | |||||
class AvailabilityCoordinator implements IAvailabilityCoordinator { | |||||
private ICache $cache; | |||||
public function __construct( | |||||
ICacheFactory $cacheFactory, | |||||
private AbsenceMapper $absenceMapper, | |||||
private LoggerInterface $logger, | |||||
) { | |||||
$this->cache = $cacheFactory->createLocal('OutOfOfficeData'); | |||||
} | |||||
private function getCachedOutOfOfficeData(IUser $user): ?OutOfOfficeData { | |||||
$cachedString = $this->cache->get($user->getUID()); | |||||
if ($cachedString === null) { | |||||
return null; | |||||
} | |||||
try { | |||||
$cachedData = json_decode($cachedString, true, 10, JSON_THROW_ON_ERROR); | |||||
} catch (JsonException $e) { | |||||
$this->logger->error('Failed to deserialize cached out-of-office data: ' . $e->getMessage(), [ | |||||
'exception' => $e, | |||||
'json' => $cachedString, | |||||
]); | |||||
return null; | |||||
} | |||||
return new OutOfOfficeData( | |||||
$cachedData['id'], | |||||
$user, | |||||
$cachedData['startDate'], | |||||
$cachedData['endDate'], | |||||
$cachedData['shortMessage'], | |||||
$cachedData['message'], | |||||
); | |||||
} | |||||
private function setCachedOutOfOfficeData(IOutOfOfficeData $data): void { | |||||
try { | |||||
$cachedString = json_encode([ | |||||
'id' => $data->getId(), | |||||
'startDate' => $data->getStartDate(), | |||||
'endDate' => $data->getEndDate(), | |||||
'shortMessage' => $data->getShortMessage(), | |||||
'message' => $data->getMessage(), | |||||
], JSON_THROW_ON_ERROR); | |||||
} catch (JsonException $e) { | |||||
$this->logger->error('Failed to serialize out-of-office data: ' . $e->getMessage(), [ | |||||
'exception' => $e, | |||||
]); | |||||
return; | |||||
} | |||||
$this->cache->set($data->getUser()->getUID(), $cachedString, 300); | |||||
} | |||||
public function getCurrentOutOfOfficeData(IUser $user): ?IOutOfOfficeData { | |||||
$cachedData = $this->getCachedOutOfOfficeData($user); | |||||
if ($cachedData !== null) { | |||||
return $cachedData; | |||||
} | |||||
try { | |||||
$absenceData = $this->absenceMapper->findByUserId($user->getUID()); | |||||
} catch (DoesNotExistException $e) { | |||||
return null; | |||||
} | |||||
$data = $absenceData->toOutOufOfficeData($user); | |||||
$this->setCachedOutOfOfficeData($data); | |||||
return $data; | |||||
} | |||||
} |
<?php | |||||
declare(strict_types=1); | |||||
/** | |||||
* @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at> | |||||
* | |||||
* @author 2023 Christoph Wurst <christoph@winzerhof-wurst.at> | |||||
* | |||||
* @license GNU AGPL version 3 or any later version | |||||
* | |||||
* This program is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU Affero General Public License as | |||||
* published by the Free Software Foundation, either version 3 of the | |||||
* License, or (at your option) any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU Affero General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU Affero General Public License | |||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
namespace OC\User; | |||||
use OCP\IUser; | |||||
use OCP\User\IOutOfOfficeData; | |||||
class OutOfOfficeData implements IOutOfOfficeData { | |||||
public function __construct(private string $id, | |||||
private IUser $user, | |||||
private int $startDate, | |||||
private int $endDate, | |||||
private string $shortMessage, | |||||
private string $message) { | |||||
} | |||||
public function getId(): string { | |||||
return $this->id; | |||||
} | |||||
public function getUser(): IUser { | |||||
return $this->user; | |||||
} | |||||
public function getStartDate(): int { | |||||
return $this->startDate; | |||||
} | |||||
public function getEndDate(): int { | |||||
return $this->endDate; | |||||
} | |||||
public function getShortMessage(): string { | |||||
return $this->shortMessage; | |||||
} | |||||
public function getMessage(): string { | |||||
return $this->message; | |||||
} | |||||
} |
<?php | |||||
declare(strict_types=1); | |||||
/* | |||||
* @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at> | |||||
* | |||||
* @author 2023 Christoph Wurst <christoph@winzerhof-wurst.at> | |||||
* | |||||
* @license GNU AGPL version 3 or any later version | |||||
* | |||||
* This program is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU Affero General Public License as | |||||
* published by the Free Software Foundation, either version 3 of the | |||||
* License, or (at your option) any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU Affero General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU Affero General Public License | |||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
namespace OCP\User\Events; | |||||
use OCP\EventDispatcher\Event; | |||||
use OCP\User\IOutOfOfficeData; | |||||
/** | |||||
* Emitted when a user's out-of-office period has changed | |||||
* | |||||
* @since 28.0.0 | |||||
*/ | |||||
class OutOfOfficeChangedEvent extends Event { | |||||
/** | |||||
* @since 28.0.0 | |||||
*/ | |||||
public function __construct(private IOutOfOfficeData $data) { | |||||
parent::__construct(); | |||||
} | |||||
/** | |||||
* @since 28.0.0 | |||||
*/ | |||||
public function getData(): IOutOfOfficeData { | |||||
return $this->data; | |||||
} | |||||
} |
<?php | |||||
declare(strict_types=1); | |||||
/* | |||||
* @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at> | |||||
* | |||||
* @author 2023 Christoph Wurst <christoph@winzerhof-wurst.at> | |||||
* | |||||
* @license GNU AGPL version 3 or any later version | |||||
* | |||||
* This program is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU Affero General Public License as | |||||
* published by the Free Software Foundation, either version 3 of the | |||||
* License, or (at your option) any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU Affero General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU Affero General Public License | |||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
namespace OCP\User\Events; | |||||
use OCP\EventDispatcher\Event; | |||||
use OCP\User\IOutOfOfficeData; | |||||
/** | |||||
* Emitted when a user's out-of-office period is cleared | |||||
* | |||||
* @since 28.0.0 | |||||
*/ | |||||
class OutOfOfficeClearedEvent extends Event { | |||||
/** | |||||
* @since 28.0.0 | |||||
*/ | |||||
public function __construct(private IOutOfOfficeData $data) { | |||||
parent::__construct(); | |||||
} | |||||
/** | |||||
* @since 28.0.0 | |||||
*/ | |||||
public function getData(): IOutOfOfficeData { | |||||
return $this->data; | |||||
} | |||||
} |
<?php | |||||
declare(strict_types=1); | |||||
/* | |||||
* @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at> | |||||
* | |||||
* @author 2023 Christoph Wurst <christoph@winzerhof-wurst.at> | |||||
* | |||||
* @license GNU AGPL version 3 or any later version | |||||
* | |||||
* This program is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU Affero General Public License as | |||||
* published by the Free Software Foundation, either version 3 of the | |||||
* License, or (at your option) any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU Affero General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU Affero General Public License | |||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
namespace OCP\User\Events; | |||||
use OCP\EventDispatcher\Event; | |||||
use OCP\User\IOutOfOfficeData; | |||||
/** | |||||
* Emitted when a user's out-of-office period is scheduled | |||||
* | |||||
* @since 28.0.0 | |||||
*/ | |||||
class OutOfOfficeScheduledEvent extends Event { | |||||
/** | |||||
* @since 28.0.0 | |||||
*/ | |||||
public function __construct(private IOutOfOfficeData $data) { | |||||
parent::__construct(); | |||||
} | |||||
/** | |||||
* @since 28.0.0 | |||||
*/ | |||||
public function getData(): IOutOfOfficeData { | |||||
return $this->data; | |||||
} | |||||
} |
<?php | |||||
declare(strict_types=1); | |||||
/** | |||||
* @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at> | |||||
* | |||||
* @author 2023 Christoph Wurst <christoph@winzerhof-wurst.at> | |||||
* | |||||
* @license GNU AGPL version 3 or any later version | |||||
* | |||||
* This program is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU Affero General Public License as | |||||
* published by the Free Software Foundation, either version 3 of the | |||||
* License, or (at your option) any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU Affero General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU Affero General Public License | |||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
namespace OCP\User; | |||||
use OCP\IUser; | |||||
/** | |||||
* Coordinator for availability and out-of-office messages | |||||
* | |||||
* @since 28.0.0 | |||||
*/ | |||||
interface IAvailabilityCoordinator { | |||||
/** | |||||
* Get the user's out-of-office message, if any | |||||
* | |||||
* @since 28.0.0 | |||||
*/ | |||||
public function getCurrentOutOfOfficeData(IUser $user): ?IOutOfOfficeData; | |||||
} |
<?php | |||||
declare(strict_types=1); | |||||
/* | |||||
* @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at> | |||||
* | |||||
* @author 2023 Christoph Wurst <christoph@winzerhof-wurst.at> | |||||
* | |||||
* @license GNU AGPL version 3 or any later version | |||||
* | |||||
* This program is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU Affero General Public License as | |||||
* published by the Free Software Foundation, either version 3 of the | |||||
* License, or (at your option) any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU Affero General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU Affero General Public License | |||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
namespace OCP\User; | |||||
use OCP\IUser; | |||||
/** | |||||
* DTO to hold out-of-office information of a user | |||||
* | |||||
* @since 28.0.0 | |||||
*/ | |||||
interface IOutOfOfficeData { | |||||
/** | |||||
* Get the unique token assigned to the current out-of-office event | |||||
* | |||||
* @since 28.0.0 | |||||
*/ | |||||
public function getId(): string; | |||||
/** | |||||
* @since 28.0.0 | |||||
*/ | |||||
public function getUser(): IUser; | |||||
/** | |||||
* Get the accurate out-of-office start date | |||||
* | |||||
* This event is not guaranteed to be emitted exactly at start date | |||||
* | |||||
* @since 28.0.0 | |||||
*/ | |||||
public function getStartDate(): int; | |||||
/** | |||||
* Get the (preliminary) out-of-office end date | |||||
* | |||||
* @since 28.0.0 | |||||
*/ | |||||
public function getEndDate(): int; | |||||
/** | |||||
* Get the short summary text displayed in the user status and similar | |||||
* | |||||
* @since 28.0.0 | |||||
*/ | |||||
public function getShortMessage(): string; | |||||
/** | |||||
* Get the long out-of-office message for auto responders and similar | |||||
* | |||||
* @since 28.0.0 | |||||
*/ | |||||
public function getMessage(): string; | |||||
} |
<?php | |||||
declare(strict_types=1); | |||||
/** | |||||
* @copyright Copyright (c) 2023 Richard Steinmetz <richard@steinmetz.cloud> | |||||
* | |||||
* @author Richard Steinmetz <richard@steinmetz.cloud> | |||||
* | |||||
* @license AGPL-3.0-or-later | |||||
* | |||||
* This program is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation, either version 3 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
* | |||||
*/ | |||||
namespace Test\User; | |||||
use OC\User\AvailabilityCoordinator; | |||||
use OC\User\OutOfOfficeData; | |||||
use OCA\DAV\Db\Absence; | |||||
use OCA\DAV\Db\AbsenceMapper; | |||||
use OCP\ICache; | |||||
use OCP\ICacheFactory; | |||||
use OCP\IUser; | |||||
use Psr\Log\LoggerInterface; | |||||
use Test\TestCase; | |||||
class AvailabilityCoordinatorTest extends TestCase { | |||||
private AvailabilityCoordinator $availabilityCoordinator; | |||||
private ICacheFactory $cacheFactory; | |||||
private ICache $cache; | |||||
private AbsenceMapper $absenceMapper; | |||||
private LoggerInterface $logger; | |||||
protected function setUp(): void { | |||||
parent::setUp(); | |||||
$this->cacheFactory = $this->createMock(ICacheFactory::class); | |||||
$this->cache = $this->createMock(ICache::class); | |||||
$this->absenceMapper = $this->createMock(AbsenceMapper::class); | |||||
$this->logger = $this->createMock(LoggerInterface::class); | |||||
$this->cacheFactory->expects(self::once()) | |||||
->method('createLocal') | |||||
->willReturn($this->cache); | |||||
$this->availabilityCoordinator = new AvailabilityCoordinator( | |||||
$this->cacheFactory, | |||||
$this->absenceMapper, | |||||
$this->logger, | |||||
); | |||||
} | |||||
public function testGetOutOfOfficeData(): void { | |||||
$absence = new Absence(); | |||||
$absence->setId(420); | |||||
$absence->setUserId('user'); | |||||
$absence->setFirstDay('2023-10-01'); | |||||
$absence->setLastDay('2023-10-08'); | |||||
$absence->setStatus('Vacation'); | |||||
$absence->setMessage('On vacation'); | |||||
$user = $this->createMock(IUser::class); | |||||
$user->method('getUID') | |||||
->willReturn('user'); | |||||
$this->cache->expects(self::once()) | |||||
->method('get') | |||||
->with('user') | |||||
->willReturn(null); | |||||
$this->absenceMapper->expects(self::once()) | |||||
->method('findByUserId') | |||||
->with('user') | |||||
->willReturn($absence); | |||||
$this->cache->expects(self::once()) | |||||
->method('set') | |||||
->with('user', '{"id":"420","startDate":1696118400,"endDate":1696723200,"shortMessage":"Vacation","message":"On vacation"}', 300); | |||||
$expected = new OutOfOfficeData( | |||||
'420', | |||||
$user, | |||||
1696118400, | |||||
1696723200, | |||||
'Vacation', | |||||
'On vacation', | |||||
); | |||||
$actual = $this->availabilityCoordinator->getCurrentOutOfOfficeData($user); | |||||
self::assertEquals($expected, $actual); | |||||
} | |||||
public function testGetOutOfOfficeDataWithCachedData(): void { | |||||
$user = $this->createMock(IUser::class); | |||||
$user->method('getUID') | |||||
->willReturn('user'); | |||||
$this->cache->expects(self::once()) | |||||
->method('get') | |||||
->with('user') | |||||
->willReturn('{"id":"420","startDate":1696118400,"endDate":1696723200,"shortMessage":"Vacation","message":"On vacation"}'); | |||||
$this->absenceMapper->expects(self::never()) | |||||
->method('findByUserId'); | |||||
$this->cache->expects(self::never()) | |||||
->method('set'); | |||||
$expected = new OutOfOfficeData( | |||||
'420', | |||||
$user, | |||||
1696118400, | |||||
1696723200, | |||||
'Vacation', | |||||
'On vacation', | |||||
); | |||||
$actual = $this->availabilityCoordinator->getCurrentOutOfOfficeData($user); | |||||
self::assertEquals($expected, $actual); | |||||
} | |||||
public function testGetOutOfOfficeDataWithInvalidCachedData(): void { | |||||
$absence = new Absence(); | |||||
$absence->setId(420); | |||||
$absence->setUserId('user'); | |||||
$absence->setFirstDay('2023-10-01'); | |||||
$absence->setLastDay('2023-10-08'); | |||||
$absence->setStatus('Vacation'); | |||||
$absence->setMessage('On vacation'); | |||||
$user = $this->createMock(IUser::class); | |||||
$user->method('getUID') | |||||
->willReturn('user'); | |||||
$this->cache->expects(self::once()) | |||||
->method('get') | |||||
->with('user') | |||||
->willReturn('{"id":"420",}'); | |||||
$this->absenceMapper->expects(self::once()) | |||||
->method('findByUserId') | |||||
->with('user') | |||||
->willReturn($absence); | |||||
$this->cache->expects(self::once()) | |||||
->method('set') | |||||
->with('user', '{"id":"420","startDate":1696118400,"endDate":1696723200,"shortMessage":"Vacation","message":"On vacation"}', 300); | |||||
$expected = new OutOfOfficeData( | |||||
'420', | |||||
$user, | |||||
1696118400, | |||||
1696723200, | |||||
'Vacation', | |||||
'On vacation', | |||||
); | |||||
$actual = $this->availabilityCoordinator->getCurrentOutOfOfficeData($user); | |||||
self::assertEquals($expected, $actual); | |||||
} | |||||
} |