diff sat_pubsub/backend.py @ 459:cebcb7f56889

backend, delegation: update to XEP-0355 v0.5 (namespace bump) + disco: - delegation now uses namespace `urn:xmpp:delegation:2` - restored node metadata and made it work with PEP - `delegated` attribute is also set on recipient when available (needed to know when a disco query is delegated as the original stanza is lost by wokkel)
author Goffi <goffi@goffi.org>
date Fri, 15 Oct 2021 09:32:04 +0200
parents 0b5233981671
children 607616f9ef5b
line wrap: on
line diff
--- a/sat_pubsub/backend.py	Thu Oct 14 21:30:33 2021 +0200
+++ b/sat_pubsub/backend.py	Fri Oct 15 09:32:04 2021 +0200
@@ -67,7 +67,7 @@
 from zope.interface import implementer
 
 from twisted.application import service
-from twisted.python import components, log
+from twisted.python import components, failure, log
 from twisted.internet import defer, reactor
 from twisted.words.protocols.jabber.error import StanzaError
 from twisted.words.protocols.jabber import jid
@@ -1638,35 +1638,49 @@
 
         raise exc
 
-    def getInfo(self, requestor, service, nodeIdentifier, pep=None, recipient=None):
-        return [] # FIXME: disabled for now, need to manage PEP
+    async def _getInfo(
+        self,
+        requestor: jid.JID,
+        service: jid.JID,
+        nodeIdentifier: str,
+        pep: bool = False,
+        recipient: Optional[jid.JID] = None
+    ) -> Optional[dict]:
         if not requestor.resource:
-            # this avoid error when getting a disco request from server during namespace delegation
-            return []
+            # this avoid error when getting a disco request from server during namespace
+            # delegation
+            return None
         info = {}
-
-        def saveType(result):
-            info['type'] = result
-            return nodeIdentifier
-
-        def saveMetaData(result):
-            info['meta-data'] = result
+        try:
+            info["type"] = await self.backend.getNodeType(nodeIdentifier, pep, recipient)
+            info["meta-data"] = await self.backend.getNodeMetaData(
+                nodeIdentifier, pep, recipient
+            )
+        except error.NodeNotFound:
+            info["meta-data"] = None
+            return None
+        except failure.Failure as e:
+            self._mapErrors(e)
+        except Exception as e:
+            self._mapErrors(failure.Failure(e))
+        else:
             return info
 
-        def trapNotFound(failure):
-            failure.trap(error.NodeNotFound)
-            return info
+    def getInfo(self, requestor, service, nodeIdentifier):
+        try:
+            pep = service.delegated
+        except AttributeError:
+            pep = False
+            recipient = None
+        else:
+            recipient = service if pep else None
+        return defer.ensureDeferred(
+            self._getInfo(
+                requestor, service, nodeIdentifier, pep, recipient
+            )
+        )
 
-        d = defer.succeed(nodeIdentifier)
-        d.addCallback(self.backend.getNodeType)
-        d.addCallback(saveType)
-        d.addCallback(self.backend.getNodeMetaData)
-        d.addCallback(saveMetaData)
-        d.addErrback(trapNotFound)
-        d.addErrback(self._mapErrors)
-        return d
-
-    def getNodes(self, requestor, service, nodeIdentifier):
+    async def _getNodes(self, requestor, service, nodeIdentifier):
         """return nodes for disco#items
 
         Pubsub/PEP nodes will be returned if disco node is not specified
@@ -1679,25 +1693,35 @@
             pep = False
 
         if service.resource:
-            return defer.succeed([])
+            return []
 
         if nodeIdentifier:
-            d = self.backend.getItemsIds(nodeIdentifier,
-                                         requestor,
-                                         [],
-                                         requestor.userhostJID() == service,
-                                         None,
-                                         None,
-                                         pep,
-                                         service)
+            items = await self.backend.getItemsIds(
+                nodeIdentifier,
+                requestor,
+                [],
+                requestor.userhostJID() == service,
+                None,
+                None,
+                pep,
+                service
+            )
             # items must be set as name, not node
-            d.addCallback(lambda items: [(None, item) for item in items])
-
+            return [(None, item) for item in items]
         else:
-            d = self.backend.getNodes(requestor.userhostJID(),
-                                      pep,
-                                      service)
-        return d.addErrback(self._mapErrors)
+            try:
+                return await self.backend.getNodes(
+                    requestor.userhostJID(),
+                    pep,
+                    service
+                )
+            except failure.Failure as e:
+                self._mapErrors(e)
+            except Exception as e:
+                self._mapErrors(failure.Failure(e))
+
+    def getNodes(self, requestor, service, nodeIdentifier):
+        return defer.ensureDeferred(self._getNodes(requestor, service, nodeIdentifier))
 
     def getConfigurationOptions(self):
         return self.backend.nodeOptions