UserStatusController.php 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @copyright Copyright (c) 2020, Georg Ehrke
  5. *
  6. * @author Georg Ehrke <oc.list@georgehrke.com>
  7. * @author Joas Schilling <coding@schilljs.com>
  8. * @author Simon Spannagel <simonspa@kth.se>
  9. * @author Kate Döen <kate.doeen@nextcloud.com>
  10. *
  11. * @license GNU AGPL version 3 or any later version
  12. *
  13. * This program is free software: you can redistribute it and/or modify
  14. * it under the terms of the GNU Affero General Public License as
  15. * published by the Free Software Foundation, either version 3 of the
  16. * License, or (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU Affero General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU Affero General Public License
  24. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  25. *
  26. */
  27. namespace OCA\UserStatus\Controller;
  28. use OCA\DAV\CalDAV\Status\StatusService as CalendarStatusService;
  29. use OCA\UserStatus\Db\UserStatus;
  30. use OCA\UserStatus\Exception\InvalidClearAtException;
  31. use OCA\UserStatus\Exception\InvalidMessageIdException;
  32. use OCA\UserStatus\Exception\InvalidStatusIconException;
  33. use OCA\UserStatus\Exception\InvalidStatusTypeException;
  34. use OCA\UserStatus\Exception\StatusMessageTooLongException;
  35. use OCA\UserStatus\ResponseDefinitions;
  36. use OCA\UserStatus\Service\StatusService;
  37. use OCP\AppFramework\Db\DoesNotExistException;
  38. use OCP\AppFramework\Http;
  39. use OCP\AppFramework\Http\Attribute\ApiRoute;
  40. use OCP\AppFramework\Http\DataResponse;
  41. use OCP\AppFramework\OCS\OCSBadRequestException;
  42. use OCP\AppFramework\OCS\OCSNotFoundException;
  43. use OCP\AppFramework\OCSController;
  44. use OCP\IRequest;
  45. use Psr\Log\LoggerInterface;
  46. /**
  47. * @psalm-import-type UserStatusType from ResponseDefinitions
  48. * @psalm-import-type UserStatusPrivate from ResponseDefinitions
  49. */
  50. class UserStatusController extends OCSController {
  51. public function __construct(
  52. string $appName,
  53. IRequest $request,
  54. private string $userId,
  55. private LoggerInterface $logger,
  56. private StatusService $service,
  57. private CalendarStatusService $calendarStatusService,
  58. ) {
  59. parent::__construct($appName, $request);
  60. }
  61. /**
  62. * Get the status of the current user
  63. *
  64. * @NoAdminRequired
  65. *
  66. * @return DataResponse<Http::STATUS_OK, UserStatusPrivate, array{}>
  67. * @throws OCSNotFoundException The user was not found
  68. *
  69. * 200: The status was found successfully
  70. */
  71. #[ApiRoute(verb: 'GET', url: '/api/v1/user_status')]
  72. public function getStatus(): DataResponse {
  73. try {
  74. $this->calendarStatusService->processCalendarStatus($this->userId);
  75. $userStatus = $this->service->findByUserId($this->userId);
  76. } catch (DoesNotExistException $ex) {
  77. throw new OCSNotFoundException('No status for the current user');
  78. }
  79. return new DataResponse($this->formatStatus($userStatus));
  80. }
  81. /**
  82. * Update the status type of the current user
  83. *
  84. * @NoAdminRequired
  85. *
  86. * @param string $statusType The new status type
  87. * @return DataResponse<Http::STATUS_OK, UserStatusPrivate, array{}>
  88. * @throws OCSBadRequestException The status type is invalid
  89. *
  90. * 200: The status was updated successfully
  91. */
  92. #[ApiRoute(verb: 'PUT', url: '/api/v1/user_status/status')]
  93. public function setStatus(string $statusType): DataResponse {
  94. try {
  95. $status = $this->service->setStatus($this->userId, $statusType, null, true);
  96. $this->service->removeBackupUserStatus($this->userId);
  97. return new DataResponse($this->formatStatus($status));
  98. } catch (InvalidStatusTypeException $ex) {
  99. $this->logger->debug('New user-status for "' . $this->userId . '" was rejected due to an invalid status type "' . $statusType . '"');
  100. throw new OCSBadRequestException($ex->getMessage(), $ex);
  101. }
  102. }
  103. /**
  104. * Set the message to a predefined message for the current user
  105. *
  106. * @NoAdminRequired
  107. *
  108. * @param string $messageId ID of the predefined message
  109. * @param int|null $clearAt When the message should be cleared
  110. * @return DataResponse<Http::STATUS_OK, UserStatusPrivate, array{}>
  111. * @throws OCSBadRequestException The clearAt or message-id is invalid
  112. *
  113. * 200: The message was updated successfully
  114. */
  115. #[ApiRoute(verb: 'PUT', url: '/api/v1/user_status/message/predefined')]
  116. public function setPredefinedMessage(string $messageId,
  117. ?int $clearAt): DataResponse {
  118. try {
  119. $status = $this->service->setPredefinedMessage($this->userId, $messageId, $clearAt);
  120. $this->service->removeBackupUserStatus($this->userId);
  121. return new DataResponse($this->formatStatus($status));
  122. } catch (InvalidClearAtException $ex) {
  123. $this->logger->debug('New user-status for "' . $this->userId . '" was rejected due to an invalid clearAt value "' . $clearAt . '"');
  124. throw new OCSBadRequestException($ex->getMessage(), $ex);
  125. } catch (InvalidMessageIdException $ex) {
  126. $this->logger->debug('New user-status for "' . $this->userId . '" was rejected due to an invalid message-id "' . $messageId . '"');
  127. throw new OCSBadRequestException($ex->getMessage(), $ex);
  128. }
  129. }
  130. /**
  131. * Set the message to a custom message for the current user
  132. *
  133. * @NoAdminRequired
  134. *
  135. * @param string|null $statusIcon Icon of the status
  136. * @param string|null $message Message of the status
  137. * @param int|null $clearAt When the message should be cleared
  138. * @return DataResponse<Http::STATUS_OK, UserStatusPrivate, array{}>
  139. * @throws OCSBadRequestException The clearAt or icon is invalid or the message is too long
  140. *
  141. * 200: The message was updated successfully
  142. */
  143. #[ApiRoute(verb: 'PUT', url: '/api/v1/user_status/message/custom')]
  144. public function setCustomMessage(?string $statusIcon,
  145. ?string $message,
  146. ?int $clearAt): DataResponse {
  147. try {
  148. if (($statusIcon !== null && $statusIcon !== '') || ($message !== null && $message !== '') || ($clearAt !== null && $clearAt !== 0)) {
  149. $status = $this->service->setCustomMessage($this->userId, $statusIcon, $message, $clearAt);
  150. } else {
  151. $this->service->clearMessage($this->userId);
  152. $status = $this->service->findByUserId($this->userId);
  153. }
  154. $this->service->removeBackupUserStatus($this->userId);
  155. return new DataResponse($this->formatStatus($status));
  156. } catch (InvalidClearAtException $ex) {
  157. $this->logger->debug('New user-status for "' . $this->userId . '" was rejected due to an invalid clearAt value "' . $clearAt . '"');
  158. throw new OCSBadRequestException($ex->getMessage(), $ex);
  159. } catch (InvalidStatusIconException $ex) {
  160. $this->logger->debug('New user-status for "' . $this->userId . '" was rejected due to an invalid icon value "' . $statusIcon . '"');
  161. throw new OCSBadRequestException($ex->getMessage(), $ex);
  162. } catch (StatusMessageTooLongException $ex) {
  163. $this->logger->debug('New user-status for "' . $this->userId . '" was rejected due to a too long status message.');
  164. throw new OCSBadRequestException($ex->getMessage(), $ex);
  165. }
  166. }
  167. /**
  168. * Clear the message of the current user
  169. *
  170. * @NoAdminRequired
  171. *
  172. * @return DataResponse<Http::STATUS_OK, array<empty>, array{}>
  173. *
  174. * 200: Message cleared successfully
  175. */
  176. #[ApiRoute(verb: 'DELETE', url: '/api/v1/user_status/message')]
  177. public function clearMessage(): DataResponse {
  178. $this->service->clearMessage($this->userId);
  179. return new DataResponse([]);
  180. }
  181. /**
  182. * Revert the status to the previous status
  183. *
  184. * @NoAdminRequired
  185. *
  186. * @param string $messageId ID of the message to delete
  187. *
  188. * @return DataResponse<Http::STATUS_OK, UserStatusPrivate|array<empty>, array{}>
  189. *
  190. * 200: Status reverted
  191. */
  192. #[ApiRoute(verb: 'DELETE', url: '/api/v1/user_status/revert/{messageId}')]
  193. public function revertStatus(string $messageId): DataResponse {
  194. $backupStatus = $this->service->revertUserStatus($this->userId, $messageId, true);
  195. if ($backupStatus) {
  196. return new DataResponse($this->formatStatus($backupStatus));
  197. }
  198. return new DataResponse([]);
  199. }
  200. /**
  201. * @param UserStatus $status
  202. * @return UserStatusPrivate
  203. */
  204. private function formatStatus(UserStatus $status): array {
  205. /** @var UserStatusType $visibleStatus */
  206. $visibleStatus = $status->getStatus();
  207. return [
  208. 'userId' => $status->getUserId(),
  209. 'message' => $status->getCustomMessage(),
  210. 'messageId' => $status->getMessageId(),
  211. 'messageIsPredefined' => $status->getMessageId() !== null,
  212. 'icon' => $status->getCustomIcon(),
  213. 'clearAt' => $status->getClearAt(),
  214. 'status' => $visibleStatus,
  215. 'statusIsUserDefined' => $status->getIsUserDefined(),
  216. ];
  217. }
  218. }