# HG changeset patch # User Goffi # Date 1655468123 -7200 # Node ID 865167c34b82df0a1a34659c18fd130292eb7ac1 # Parent c61233f51b86c58ce725317050be428acfc6165f 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 diff -r c61233f51b86 -r 865167c34b82 sat/plugins/plugin_comp_ap_gateway/__init__.py --- 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() diff -r c61233f51b86 -r 865167c34b82 sat/plugins/plugin_comp_ap_gateway/constants.py --- 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 diff -r c61233f51b86 -r 865167c34b82 sat/plugins/plugin_comp_ap_gateway/pubsub_service.py --- 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):