diff --git a/lib/Chat/ChatManager.php b/lib/Chat/ChatManager.php index 33eb200f177..0869bdac642 100644 --- a/lib/Chat/ChatManager.php +++ b/lib/Chat/ChatManager.php @@ -483,10 +483,25 @@ public function deleteMessage(Room $chat, IComment $comment, Participant $partic * @param \DateTime $editTime * @param string $message * @return IComment + * @throws \InvalidArgumentException When the message is empty or the shared object is not a file share with caption */ public function editMessage(Room $chat, IComment $comment, Participant $participant, \DateTime $editTime, string $message): IComment { - // FIXME "Caption" handling via $comment->getVerb() === self::VERB_OBJECT_SHARED - // TODO prevent editing other shares like polls, contacts, etc. + if (trim($message) === '') { + throw new \InvalidArgumentException('message'); + } + + if ($comment->getVerb() === ChatManager::VERB_OBJECT_SHARED) { + $messageData = json_decode($comment->getMessage(), true); + if (!isset($messageData['message']) || $messageData['message'] !== 'file_shared') { + // Not a file share + throw new \InvalidArgumentException('object_share'); + } + + $messageData['parameters'] ??= []; + $messageData['parameters']['metaData'] ??= []; + $messageData['parameters']['metaData']['caption'] = $message; + $message = json_encode($messageData); + } $metaData = $comment->getMetaData() ?? []; $metaData['last_edited_by_type'] = $participant->getAttendee()->getActorType(); diff --git a/lib/Controller/ChatController.php b/lib/Controller/ChatController.php index 914535ce9c0..0381e042cb0 100644 --- a/lib/Controller/ChatController.php +++ b/lib/Controller/ChatController.php @@ -753,11 +753,11 @@ public function deleteMessage(int $messageId): DataResponse { * @param int $messageId ID of the message * @param string $message the message to send * @psalm-param non-negative-int $messageId - * @return DataResponse|DataResponse, array{}> + * @return DataResponse|DataResponse|DataResponse, array{}> * * 200: Message edited successfully * 202: Message edited successfully, but Matterbridge is configured, so the information can be replicated elsewhere - * 400: Editing message is not possible + * 400: Editing message is not possible, e.g. when the new message is empty or the message is too old * 403: Missing permissions to edit message * 404: Message not found * 405: Editing this message type is not allowed @@ -797,16 +797,23 @@ public function editMessage(int $messageId, string $message): DataResponse { $maxAge->sub(new \DateInterval('P1D')); if ($comment->getCreationDateTime() < $maxAge) { // Message is too old - return new DataResponse([], Http::STATUS_BAD_REQUEST); + return new DataResponse(['error' => 'age'], Http::STATUS_BAD_REQUEST); } - $systemMessageComment = $this->chatManager->editMessage( - $this->room, - $comment, - $this->participant, - $this->timeFactory->getDateTime(), - $message - ); + try { + $systemMessageComment = $this->chatManager->editMessage( + $this->room, + $comment, + $this->participant, + $this->timeFactory->getDateTime(), + $message + ); + } catch (\InvalidArgumentException $e) { + if ($e->getMessage() === 'object_share') { + return new DataResponse([], Http::STATUS_METHOD_NOT_ALLOWED); + } + return new DataResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST); + } $systemMessage = $this->messageParser->createMessage($this->room, $this->participant, $systemMessageComment, $this->l); $this->messageParser->parseMessage($systemMessage); diff --git a/openapi.json b/openapi.json index 0beca30fc4f..c0ea7e43062 100644 --- a/openapi.json +++ b/openapi.json @@ -6282,7 +6282,7 @@ } }, "400": { - "description": "Editing message is not possible", + "description": "Editing message is not possible, e.g. when the new message is empty or the message is too old", "content": { "application/json": { "schema": { @@ -6301,7 +6301,17 @@ "meta": { "$ref": "#/components/schemas/OCSMeta" }, - "data": {} + "data": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } } } } diff --git a/tests/integration/features/chat-1/edit-message.feature b/tests/integration/features/chat-1/edit-message.feature index 9d6e25f1169..4af56cd0908 100644 --- a/tests/integration/features/chat-1/edit-message.feature +++ b/tests/integration/features/chat-1/edit-message.feature @@ -50,3 +50,25 @@ Feature: chat-1/edit-message Then user "participant2" sees the following messages in room "room" with 200 | room | actorType | actorId | actorDisplayName | message | messageParameters | parentMessage | | room | users | participant2 | participant2-displayname | Message 1 - Edit 2 | [] | | + And user "participant2" edits message "Message 1 - Edit 1" in room "room" to "" with 400 + Then user "participant1" sees the following messages in room "room" with 200 + | room | actorType | actorId | actorDisplayName | message | messageParameters | parentMessage | + | room | users | participant2 | participant2-displayname | Message 1 - Edit 2 | [] | | + + Scenario: Editing a caption + Given user "participant1" creates room "room" (v4) + | roomType | 3 | + | roomName | room | + And user "participant1" shares "welcome.txt" with room "room" + | talkMetaData | {"caption":"Caption 1"} | + And user "participant1" sees the following messages in room "room" with 200 + | room | actorType | actorId | actorDisplayName | message | messageParameters | + | room | users | participant1 | participant1-displayname | Caption 1 | "IGNORE" | + When user "participant1" edits message "Caption 1" in room "room" to "Caption 1 - Edit 1" with 200 + Then user "participant1" sees the following messages in room "room" with 200 + | room | actorType | actorId | actorDisplayName | message | messageParameters | + | room | users | participant1 | participant1-displayname | Caption 1 - Edit 1 | "IGNORE" | + When user "participant1" edits message "Caption 1" in room "room" to "" with 400 + Then user "participant1" sees the following messages in room "room" with 200 + | room | actorType | actorId | actorDisplayName | message | messageParameters | + | room | users | participant1 | participant1-displayname | Caption 1 - Edit 1 | "IGNORE" |