changeset 3792:865167c34b82

comp AP gateway: convert pubsub item retractation to AP `Delete` activity: when an item `retract` is received from a node from which an AP actor is subscribed, a corresponding `Delete` activity is created and sent to AP followers. Trying to retract an item from a virtual node of the gateway pubsub service now return a `forbidden` stanza error (those nodes are handled on AP side and thus are not owned by XMPP entities). rel 367
author Goffi <goffi@goffi.org>
date Fri, 17 Jun 2022 14:15:23 +0200
parents c61233f51b86
children b5c9021020df
files sat/plugins/plugin_comp_ap_gateway/__init__.py sat/plugins/plugin_comp_ap_gateway/constants.py sat/plugins/plugin_comp_ap_gateway/pubsub_service.py
diffstat 3 files changed, 30 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/sat/plugins/plugin_comp_ap_gateway/__init__.py	Fri Jun 17 14:15:23 2022 +0200
+++ b/sat/plugins/plugin_comp_ap_gateway/__init__.py	Fri Jun 17 14:15:23 2022 +0200
@@ -68,6 +68,7 @@
     TYPE_ACTOR,
     TYPE_ITEM,
     TYPE_FOLLOWERS,
+    TYPE_TOMBSTONE,
     NS_AP_PUBLIC,
     PUBLIC_TUPLE
 )
@@ -470,7 +471,7 @@
             raise exceptions.InternalError("Client is not set yet")
 
         if jid_.host == self.client.jid.userhost():
-            # this is an proxy JId to an AP Actor
+            # this is an proxy JID to an AP Actor
             return self._e.unescape(jid_.user)
 
         if node and not jid_.user and not self.mustEncode(node):
@@ -860,15 +861,32 @@
         actor_id = await self.getAPActorIdFromAccount(ap_account)
         inbox = await self.getAPInboxFromId(actor_id)
         for item in items:
-            mb_data = await self._m.item2mbdata(client, item, service, node)
-            if subscribe_comments_nodes:
-                # we subscribe automatically to comment nodes if any
-                for comment_data in mb_data.get("comments", []):
-                    comment_service = jid.JID(comment_data["service"])
-                    comment_node = comment_data["node"]
-                    await self._p.subscribe(client, comment_service, comment_node)
-            ap_item = await self.mbdata2APitem(client, mb_data)
-            url_actor = ap_item["object"]["attributedTo"]
+            if item.name == "item":
+                mb_data = await self._m.item2mbdata(client, item, service, node)
+                if subscribe_comments_nodes:
+                    # we subscribe automatically to comment nodes if any
+                    for comment_data in mb_data.get("comments", []):
+                        comment_service = jid.JID(comment_data["service"])
+                        comment_node = comment_data["node"]
+                        await self._p.subscribe(client, comment_service, comment_node)
+                ap_item = await self.mbdata2APitem(client, mb_data)
+                url_actor = ap_item["object"]["attributedTo"]
+            elif item.name == "retract":
+                author_account = await self.getAPAccountFromJidAndNode(client.jid, node)
+                author_actor_id = self.buildAPURL(TYPE_ACTOR, author_account)
+                url_item = self.buildAPURL(TYPE_ITEM, author_account, item["id"])
+                ap_item = self.createActivity(
+                    "Delete",
+                    author_actor_id,
+                    {
+                        "id": url_item,
+                        "type": TYPE_TOMBSTONE
+                    }
+                )
+                ap_item["to"] = [NS_AP_PUBLIC]
+                url_actor = author_actor_id
+            else:
+                raise exceptions.InternalError(f"unexpected element: {item.toXml()}")
             resp = await self.signAndPost(inbox, url_actor, ap_item)
             if resp.code >= 300:
                 text = await resp.text()
--- a/sat/plugins/plugin_comp_ap_gateway/constants.py	Fri Jun 17 14:15:23 2022 +0200
+++ b/sat/plugins/plugin_comp_ap_gateway/constants.py	Fri Jun 17 14:15:23 2022 +0200
@@ -27,6 +27,7 @@
 TYPE_FOLLOWERS = "followers"
 TYPE_FOLLOWING = "following"
 TYPE_ITEM = "item"
+TYPE_TOMBSTONE = "Tombstone"
 MEDIA_TYPE_AP = "application/activity+json"
 NS_AP_PUBLIC = "https://www.w3.org/ns/activitystreams#Public"
 # 3 values can be used, see https://www.w3.org/TR/activitypub/#public-addressing
--- a/sat/plugins/plugin_comp_ap_gateway/pubsub_service.py	Fri Jun 17 14:15:23 2022 +0200
+++ b/sat/plugins/plugin_comp_ap_gateway/pubsub_service.py	Fri Jun 17 14:15:23 2022 +0200
@@ -255,7 +255,7 @@
 
     @ensure_deferred
     async def retract(self, requestor, service, nodeIdentifier, itemIdentifiers):
-        raise NotImplementedError
+        raise error.StanzaError("forbidden")
 
     @ensure_deferred
     async def subscribe(self, requestor, service, nodeIdentifier, subscriber):