diff sat_pubsub/delegation.py @ 288:073161f6f143

namespace delegation: disco nesting management
author Goffi <goffi@goffi.org>
date Fri, 17 Apr 2015 21:09:37 +0200
parents 61f92273fb69
children f08f8536cab8
line wrap: on
line diff
--- a/sat_pubsub/delegation.py	Thu Apr 16 21:06:19 2015 +0200
+++ b/sat_pubsub/delegation.py	Fri Apr 17 21:09:37 2015 +0200
@@ -25,16 +25,23 @@
 
 from wokkel.subprotocols import XMPPHandler
 from wokkel import pubsub
+from wokkel import disco, iwokkel
 from twisted.python import log
+from twisted.words.protocols.jabber import error
+from zope.interface import implements
 
 DELEGATION_NS = 'urn:xmpp:delegation:1'
 FORWARDED_NS = 'urn:xmpp:forward:0'
 DELEGATION_ADV_XPATH = '/message/delegation[@xmlns="{}"]'.format(DELEGATION_NS)
 
+DELEGATION_MAIN_SEP = "::"
+DELEGATION_BARE_SEP = ":bare:"
+
 class InvalidStanza(Exception):
     pass
 
 class DelegationsHandler(XMPPHandler):
+    implements(iwokkel.IDisco)
 
     def __init__(self):
         super(DelegationsHandler, self).__init__()
@@ -71,3 +78,53 @@
         if not pubsub.NS_PUBSUB in delegated:
             log.msg(u"Didn't got pubsub delegation from server, can't act as a PEP service")
 
+    def getDiscoInfo(self, requestor, target, nodeIdentifier=''):
+        """Manage disco nesting
+
+        This method looks for DiscoHandler in sibling handlers and use it to
+        collect main disco infos. It then filters by delegated namespace and return it.
+        An identity is added for PEP if pubsub namespace is requested.
+
+        The same features/identities are returned for main and bare nodes
+        """
+        if not nodeIdentifier.startswith(DELEGATION_NS):
+            return []
+
+        try:
+            _, namespace = nodeIdentifier.split(DELEGATION_MAIN_SEP, 1)
+        except ValueError:
+            try:
+                _, namespace = nodeIdentifier.split(DELEGATION_BARE_SEP, 1)
+            except ValueError:
+                log.msg("Unexpected disco node: {}".format(nodeIdentifier))
+                raise error.StanzaError('not-acceptable')
+
+        if not namespace:
+            log.msg("No namespace found in node {}".format(nodeIdentifier))
+            return []
+
+        def gotInfos(infos):
+            ns_features = []
+            for info in infos:
+                if isinstance(info, disco.DiscoFeature) and info.startswith(namespace):
+                    ns_features.append(info)
+
+            if namespace == pubsub.NS_PUBSUB:
+                ns_features.append(disco.DiscoIdentity('pubsub', 'pep'))
+
+            return ns_features
+
+        for handler in self.parent.handlers:
+            if isinstance(handler, disco.DiscoHandler):
+                break
+
+        if not isinstance(handler, disco.DiscoHandler):
+            log.err("Can't find DiscoHandler")
+            return []
+
+        d = handler.info(requestor, target, '')
+        d.addCallback(gotInfos)
+        return d
+
+    def getDiscoItems(self, requestor, target, nodeIdentifier=''):
+        return []