From 7c427d2cbb4bdb87a5c29a34c707cf5d7a3e8f5f Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 11 Oct 2024 14:02:30 +0200 Subject: [PATCH] feat(polls): Define returned errors Signed-off-by: Joas Schilling --- lib/Controller/PollController.php | 11 ++++--- lib/Exceptions/PollPropertyException.php | 32 +++++++++++++++++++ .../TalkV1/Controller/PollController.php | 6 ++-- lib/Service/PollService.php | 20 +++++++----- openapi-full.json | 18 ++++++++++- openapi.json | 18 ++++++++++- src/types/openapi/openapi-full.ts | 5 ++- src/types/openapi/openapi.ts | 5 ++- 8 files changed, 96 insertions(+), 19 deletions(-) create mode 100644 lib/Exceptions/PollPropertyException.php diff --git a/lib/Controller/PollController.php b/lib/Controller/PollController.php index 80aaa280368..0b4722d47c6 100644 --- a/lib/Controller/PollController.php +++ b/lib/Controller/PollController.php @@ -11,6 +11,7 @@ use JsonException; use OCA\Talk\Chat\ChatManager; +use OCA\Talk\Exceptions\PollPropertyException; use OCA\Talk\Exceptions\WrongPermissionsException; use OCA\Talk\Middleware\Attribute\FederationSupported; use OCA\Talk\Middleware\Attribute\RequireModeratorOrNoLobby; @@ -61,7 +62,7 @@ public function __construct( * @psalm-param Poll::MODE_* $resultMode Mode how the results will be shown * @param int $maxVotes Number of maximum votes per voter * @param bool $draft Whether the poll should be saved as a draft (only allowed for moderators and with `talk-polls-drafts` capability) - * @return DataResponse|DataResponse|DataResponse, array{}> + * @return DataResponse|DataResponse|DataResponse * * 200: Draft created successfully * 201: Poll created successfully @@ -82,11 +83,11 @@ public function createPoll(string $question, array $options, int $resultMode, in if ($this->room->getType() !== Room::TYPE_GROUP && $this->room->getType() !== Room::TYPE_PUBLIC) { - return new DataResponse([], Http::STATUS_BAD_REQUEST); + return new DataResponse(['error' => PollPropertyException::REASON_ROOM], Http::STATUS_BAD_REQUEST); } if ($draft === true && !$this->participant->hasModeratorPermissions()) { - return new DataResponse([], Http::STATUS_BAD_REQUEST); + return new DataResponse(['error' => PollPropertyException::REASON_DRAFT], Http::STATUS_BAD_REQUEST); } $attendee = $this->participant->getAttendee(); @@ -102,9 +103,9 @@ public function createPoll(string $question, array $options, int $resultMode, in $maxVotes, $draft, ); - } catch (\Exception $e) { + } catch (PollPropertyException $e) { $this->logger->error('Error creating poll', ['exception' => $e]); - return new DataResponse([], Http::STATUS_BAD_REQUEST); + return new DataResponse(['error' => $e->getReason()], Http::STATUS_BAD_REQUEST); } if ($draft) { diff --git a/lib/Exceptions/PollPropertyException.php b/lib/Exceptions/PollPropertyException.php new file mode 100644 index 00000000000..56200dfe2e1 --- /dev/null +++ b/lib/Exceptions/PollPropertyException.php @@ -0,0 +1,32 @@ +reason; + } +} diff --git a/lib/Federation/Proxy/TalkV1/Controller/PollController.php b/lib/Federation/Proxy/TalkV1/Controller/PollController.php index bc70c4f60a3..658c87f548c 100644 --- a/lib/Federation/Proxy/TalkV1/Controller/PollController.php +++ b/lib/Federation/Proxy/TalkV1/Controller/PollController.php @@ -126,9 +126,10 @@ public function votePoll(Room $room, Participant $participant, int $pollId, arra /** - * @return DataResponse|DataResponse|DataResponse, array{}> + * @return DataResponse|DataResponse|DataResponse * @throws CannotReachRemoteException * + * 200: Draft created successfully * 201: Poll created successfully * 400: Creating poll is not possible * @@ -150,7 +151,8 @@ public function createPoll(Room $room, Participant $participant, string $questio $status = $proxy->getStatusCode(); if ($status === Http::STATUS_BAD_REQUEST) { - return new DataResponse([], Http::STATUS_BAD_REQUEST); + $data = $this->proxy->getOCSData($proxy, [Http::STATUS_BAD_REQUEST]); + return new DataResponse($data, Http::STATUS_BAD_REQUEST); } /** @var TalkPoll $data */ diff --git a/lib/Service/PollService.php b/lib/Service/PollService.php index a3fd7d6d595..8f226bf3606 100644 --- a/lib/Service/PollService.php +++ b/lib/Service/PollService.php @@ -8,6 +8,7 @@ namespace OCA\Talk\Service; +use OCA\Talk\Exceptions\PollPropertyException; use OCA\Talk\Exceptions\WrongPermissionsException; use OCA\Talk\Model\Poll; use OCA\Talk\Model\PollMapper; @@ -29,23 +30,26 @@ public function __construct( ) { } + /** + * @throws PollPropertyException + */ public function createPoll(int $roomId, string $actorType, string $actorId, string $displayName, string $question, array $options, int $resultMode, int $maxVotes, bool $draft): Poll { $question = trim($question); if ($question === '' || strlen($question) > 32_000) { - throw new \UnexpectedValueException(); + throw new PollPropertyException(PollPropertyException::REASON_QUESTION); } try { json_encode($options, JSON_THROW_ON_ERROR, 1); - } catch (\Exception $e) { - throw new \RuntimeException(); + } catch (\Exception) { + throw new PollPropertyException(PollPropertyException::REASON_OPTIONS); } $validOptions = []; foreach ($options as $option) { if (!is_string($option)) { - throw new \RuntimeException(); + throw new PollPropertyException(PollPropertyException::REASON_OPTIONS); } $option = trim($option); @@ -55,17 +59,17 @@ public function createPoll(int $roomId, string $actorType, string $actorId, stri } if (count($validOptions) < 2) { - throw new \RuntimeException(); + throw new PollPropertyException(PollPropertyException::REASON_OPTIONS); } try { $jsonOptions = json_encode($validOptions, JSON_THROW_ON_ERROR, 1); - } catch (\Exception $e) { - throw new \RuntimeException(); + } catch (\Exception) { + throw new PollPropertyException(PollPropertyException::REASON_OPTIONS); } if (strlen($jsonOptions) > 60_000) { - throw new \UnexpectedValueException(); + throw new PollPropertyException(PollPropertyException::REASON_OPTIONS); } $poll = new Poll(); diff --git a/openapi-full.json b/openapi-full.json index 78ce1d2c395..3a17270c787 100644 --- a/openapi-full.json +++ b/openapi-full.json @@ -8889,7 +8889,23 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": {} + "data": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string", + "enum": [ + "draft", + "options", + "question", + "room" + ] + } + } + } } } } diff --git a/openapi.json b/openapi.json index e61672fee0d..11b00cbcb3e 100644 --- a/openapi.json +++ b/openapi.json @@ -8776,7 +8776,23 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": {} + "data": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string", + "enum": [ + "draft", + "options", + "question", + "room" + ] + } + } + } } } } diff --git a/src/types/openapi/openapi-full.ts b/src/types/openapi/openapi-full.ts index 3469d50f988..b9a3b9df1af 100644 --- a/src/types/openapi/openapi-full.ts +++ b/src/types/openapi/openapi-full.ts @@ -5188,7 +5188,10 @@ export interface operations { "application/json": { ocs: { meta: components["schemas"]["OCSMeta"]; - data: unknown; + data: { + /** @enum {string} */ + error: "draft" | "options" | "question" | "room"; + }; }; }; }; diff --git a/src/types/openapi/openapi.ts b/src/types/openapi/openapi.ts index 40389a7f3b4..a369c986d59 100644 --- a/src/types/openapi/openapi.ts +++ b/src/types/openapi/openapi.ts @@ -4669,7 +4669,10 @@ export interface operations { "application/json": { ocs: { meta: components["schemas"]["OCSMeta"]; - data: unknown; + data: { + /** @enum {string} */ + error: "draft" | "options" | "question" | "room"; + }; }; }; };