1
0

UserStatusController.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OCA\UserStatus\Controller;
  8. use OCA\DAV\CalDAV\Status\StatusService as CalendarStatusService;
  9. use OCA\UserStatus\Db\UserStatus;
  10. use OCA\UserStatus\Exception\InvalidClearAtException;
  11. use OCA\UserStatus\Exception\InvalidMessageIdException;
  12. use OCA\UserStatus\Exception\InvalidStatusIconException;
  13. use OCA\UserStatus\Exception\InvalidStatusTypeException;
  14. use OCA\UserStatus\Exception\StatusMessageTooLongException;
  15. use OCA\UserStatus\ResponseDefinitions;
  16. use OCA\UserStatus\Service\StatusService;
  17. use OCP\AppFramework\Db\DoesNotExistException;
  18. use OCP\AppFramework\Http;
  19. use OCP\AppFramework\Http\Attribute\ApiRoute;
  20. use OCP\AppFramework\Http\DataResponse;
  21. use OCP\AppFramework\OCS\OCSBadRequestException;
  22. use OCP\AppFramework\OCS\OCSNotFoundException;
  23. use OCP\AppFramework\OCSController;
  24. use OCP\IRequest;
  25. use Psr\Log\LoggerInterface;
  26. /**
  27. * @psalm-import-type UserStatusType from ResponseDefinitions
  28. * @psalm-import-type UserStatusPrivate from ResponseDefinitions
  29. */
  30. class UserStatusController extends OCSController {
  31. public function __construct(
  32. string $appName,
  33. IRequest $request,
  34. private string $userId,
  35. private LoggerInterface $logger,
  36. private StatusService $service,
  37. private CalendarStatusService $calendarStatusService,
  38. ) {
  39. parent::__construct($appName, $request);
  40. }
  41. /**
  42. * Get the status of the current user
  43. *
  44. * @NoAdminRequired
  45. *
  46. * @return DataResponse<Http::STATUS_OK, UserStatusPrivate, array{}>
  47. * @throws OCSNotFoundException The user was not found
  48. *
  49. * 200: The status was found successfully
  50. */
  51. #[ApiRoute(verb: 'GET', url: '/api/v1/user_status')]
  52. public function getStatus(): DataResponse {
  53. try {
  54. $this->calendarStatusService->processCalendarStatus($this->userId);
  55. $userStatus = $this->service->findByUserId($this->userId);
  56. } catch (DoesNotExistException $ex) {
  57. throw new OCSNotFoundException('No status for the current user');
  58. }
  59. return new DataResponse($this->formatStatus($userStatus));
  60. }
  61. /**
  62. * Update the status type of the current user
  63. *
  64. * @NoAdminRequired
  65. *
  66. * @param string $statusType The new status type
  67. * @return DataResponse<Http::STATUS_OK, UserStatusPrivate, array{}>
  68. * @throws OCSBadRequestException The status type is invalid
  69. *
  70. * 200: The status was updated successfully
  71. */
  72. #[ApiRoute(verb: 'PUT', url: '/api/v1/user_status/status')]
  73. public function setStatus(string $statusType): DataResponse {
  74. try {
  75. $status = $this->service->setStatus($this->userId, $statusType, null, true);
  76. $this->service->removeBackupUserStatus($this->userId);
  77. return new DataResponse($this->formatStatus($status));
  78. } catch (InvalidStatusTypeException $ex) {
  79. $this->logger->debug('New user-status for "' . $this->userId . '" was rejected due to an invalid status type "' . $statusType . '"');
  80. throw new OCSBadRequestException($ex->getMessage(), $ex);
  81. }
  82. }
  83. /**
  84. * Set the message to a predefined message for the current user
  85. *
  86. * @NoAdminRequired
  87. *
  88. * @param string $messageId ID of the predefined message
  89. * @param int|null $clearAt When the message should be cleared
  90. * @return DataResponse<Http::STATUS_OK, UserStatusPrivate, array{}>
  91. * @throws OCSBadRequestException The clearAt or message-id is invalid
  92. *
  93. * 200: The message was updated successfully
  94. */
  95. #[ApiRoute(verb: 'PUT', url: '/api/v1/user_status/message/predefined')]
  96. public function setPredefinedMessage(string $messageId,
  97. ?int $clearAt): DataResponse {
  98. try {
  99. $status = $this->service->setPredefinedMessage($this->userId, $messageId, $clearAt);
  100. $this->service->removeBackupUserStatus($this->userId);
  101. return new DataResponse($this->formatStatus($status));
  102. } catch (InvalidClearAtException $ex) {
  103. $this->logger->debug('New user-status for "' . $this->userId . '" was rejected due to an invalid clearAt value "' . $clearAt . '"');
  104. throw new OCSBadRequestException($ex->getMessage(), $ex);
  105. } catch (InvalidMessageIdException $ex) {
  106. $this->logger->debug('New user-status for "' . $this->userId . '" was rejected due to an invalid message-id "' . $messageId . '"');
  107. throw new OCSBadRequestException($ex->getMessage(), $ex);
  108. }
  109. }
  110. /**
  111. * Set the message to a custom message for the current user
  112. *
  113. * @NoAdminRequired
  114. *
  115. * @param string|null $statusIcon Icon of the status
  116. * @param string|null $message Message of the status
  117. * @param int|null $clearAt When the message should be cleared
  118. * @return DataResponse<Http::STATUS_OK, UserStatusPrivate, array{}>
  119. * @throws OCSBadRequestException The clearAt or icon is invalid or the message is too long
  120. *
  121. * 200: The message was updated successfully
  122. */
  123. #[ApiRoute(verb: 'PUT', url: '/api/v1/user_status/message/custom')]
  124. public function setCustomMessage(?string $statusIcon,
  125. ?string $message,
  126. ?int $clearAt): DataResponse {
  127. try {
  128. if (($statusIcon !== null && $statusIcon !== '') || ($message !== null && $message !== '') || ($clearAt !== null && $clearAt !== 0)) {
  129. $status = $this->service->setCustomMessage($this->userId, $statusIcon, $message, $clearAt);
  130. } else {
  131. $this->service->clearMessage($this->userId);
  132. $status = $this->service->findByUserId($this->userId);
  133. }
  134. $this->service->removeBackupUserStatus($this->userId);
  135. return new DataResponse($this->formatStatus($status));
  136. } catch (InvalidClearAtException $ex) {
  137. $this->logger->debug('New user-status for "' . $this->userId . '" was rejected due to an invalid clearAt value "' . $clearAt . '"');
  138. throw new OCSBadRequestException($ex->getMessage(), $ex);
  139. } catch (InvalidStatusIconException $ex) {
  140. $this->logger->debug('New user-status for "' . $this->userId . '" was rejected due to an invalid icon value "' . $statusIcon . '"');
  141. throw new OCSBadRequestException($ex->getMessage(), $ex);
  142. } catch (StatusMessageTooLongException $ex) {
  143. $this->logger->debug('New user-status for "' . $this->userId . '" was rejected due to a too long status message.');
  144. throw new OCSBadRequestException($ex->getMessage(), $ex);
  145. }
  146. }
  147. /**
  148. * Clear the message of the current user
  149. *
  150. * @NoAdminRequired
  151. *
  152. * @return DataResponse<Http::STATUS_OK, array<empty>, array{}>
  153. *
  154. * 200: Message cleared successfully
  155. */
  156. #[ApiRoute(verb: 'DELETE', url: '/api/v1/user_status/message')]
  157. public function clearMessage(): DataResponse {
  158. $this->service->clearMessage($this->userId);
  159. return new DataResponse([]);
  160. }
  161. /**
  162. * Revert the status to the previous status
  163. *
  164. * @NoAdminRequired
  165. *
  166. * @param string $messageId ID of the message to delete
  167. *
  168. * @return DataResponse<Http::STATUS_OK, UserStatusPrivate|array<empty>, array{}>
  169. *
  170. * 200: Status reverted
  171. */
  172. #[ApiRoute(verb: 'DELETE', url: '/api/v1/user_status/revert/{messageId}')]
  173. public function revertStatus(string $messageId): DataResponse {
  174. $backupStatus = $this->service->revertUserStatus($this->userId, $messageId, true);
  175. if ($backupStatus) {
  176. return new DataResponse($this->formatStatus($backupStatus));
  177. }
  178. return new DataResponse([]);
  179. }
  180. /**
  181. * @param UserStatus $status
  182. * @return UserStatusPrivate
  183. */
  184. private function formatStatus(UserStatus $status): array {
  185. /** @var UserStatusType $visibleStatus */
  186. $visibleStatus = $status->getStatus();
  187. return [
  188. 'userId' => $status->getUserId(),
  189. 'message' => $status->getCustomMessage(),
  190. 'messageId' => $status->getMessageId(),
  191. 'messageIsPredefined' => $status->getMessageId() !== null,
  192. 'icon' => $status->getCustomIcon(),
  193. 'clearAt' => $status->getClearAt(),
  194. 'status' => $visibleStatus,
  195. 'statusIsUserDefined' => $status->getIsUserDefined(),
  196. ];
  197. }
  198. }