UserStatusController.php 7.6 KB

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