diff libervia/backend/plugins/plugin_xep_0308.py @ 4198:b1207332cea2

plugin XEP-0308: fix ID used, recipients and author check.
author Goffi <goffi@goffi.org>
date Wed, 13 Dec 2023 22:00:25 +0100
parents a1f7040b5a15
children 0d7bb4df2343
line wrap: on
line diff
--- a/libervia/backend/plugins/plugin_xep_0308.py	Wed Dec 13 22:00:25 2023 +0100
+++ b/libervia/backend/plugins/plugin_xep_0308.py	Wed Dec 13 22:00:25 2023 +0100
@@ -16,6 +16,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import time
+import uuid
 
 from sqlalchemy.orm.attributes import flag_modified
 from twisted.internet import defer
@@ -83,6 +84,7 @@
                 .where(
                     History.profile_id == profile_id,
                     History.source == from_jid.userhost(),
+                    History.dest == client.jid.userhost(),
                     History.type == message_type,
                 )
                 .options(joinedload(History.messages))
@@ -154,6 +156,7 @@
         message_elt: domish.Element,
         post_treat: defer.Deferred,
     ) -> bool:
+        from_jid = jid.JID(message_elt["from"])
         replace_elt = next(message_elt.elements(NS_MESSAGE_CORRECT, "replace"), None)
         if not replace_elt:
             return True
@@ -167,21 +170,32 @@
             edited_history = await self.get_last_history(client, message_elt)
             if edited_history is None:
                 log.warning(
-                    f"No message found from {message_elt['from']}, can't correct "
+                    f"No message found from {from_jid.full()}, can't correct "
                     f"anything: {message_elt.toXml()}"
                 )
-                return False
-            if edited_history.extra.get("message_id") != replace_id:
+                return True
+            check_id = edited_history.origin_id or edited_history.extra.get("message_id")
+            if check_id != replace_id:
                 log.warning(
-                    "Can't apply correction: it doesn't reference the last one: "
-                    f"{message_elt.toXml}"
+                    "Can't apply correction: it doesn't reference the last one:\n"
+                    f"{message_elt.toXml()}"
                 )
-                return False
+                return True
+            # TODO: this only accept same full JID, if we do more than last message
+            #    correction, we may want to accept different resource for non groupchat
+            #    messages (in case of reconnection with resource change for instance).
+            if edited_history.source_jid != from_jid:
+                log.warning(
+                    "Can't apply correction: correction doesn't come from same author "
+                    f"{edited_history.source_jid.full()}:\n{message_elt.toXml()}"
+                )
+                return True
+
             previous_message_data = edited_history.serialise()
             message_data = client.messageProt.parse_message(message_elt)
             if not message_data["message"] and not message_data["subject"]:
                 log.warning(
-                    "Message correction doesn't have body not subject, we can't edit "
+                    "Message correction doesn't have body nor subject, we can't edit "
                     "anything"
                 )
                 return False
@@ -227,7 +241,8 @@
             )
         if edited_history.type == C.MESS_TYPE_GROUPCHAT:
             is_group_chat = True
-            peer_jid = edited_history.dest_jid
+            # In the case of group chat, our message is sent by ourself with our room JID.
+            peer_jid = edited_history.source_jid
         else:
             is_group_chat = False
             peer_jid = jid.JID(edited_history.dest)
@@ -236,7 +251,7 @@
         )
         if not history_data:
             raise exceptions.NotFound(
-                "No message found in conversation with {peer_jid.full()}"
+                "No message found in conversation with {peer_jid.userhost()}"
             )
         last_mess = history_data[0]
         if last_mess[0] != message_id:
@@ -260,12 +275,14 @@
         )
 
         serialised = edited_history.serialise()
-        serialised["from"] = jid.JID(serialised["from"])
-        serialised["to"] = jid.JID(serialised["to"])
+        serialised["uid"] = str(uuid.uuid4())
+        serialised["from"] = client.jid
+        # for group chat, we want to send the correction to the room
+        serialised["to"] = peer_jid.userhostJID() if is_group_chat else peer_jid
 
         message_elt = client.generate_message_xml(serialised)["xml"]
         replace_elt = message_elt.addElement((NS_MESSAGE_CORRECT, "replace"))
-        replace_elt["id"] = message_id
+        replace_elt["id"] = edited_history.origin_id
         self._h.add_hint_elements(message_elt, [self._h.HINT_STORE])
         client.send(message_elt)