diff sat_pubsub/backend.py @ 461:c9238fca1fb3

backend: fix node creation permission check for PEP
author Goffi <goffi@goffi.org>
date Fri, 15 Oct 2021 09:32:07 +0200
parents 607616f9ef5b
children f520ac3164b0
line wrap: on
line diff
--- a/sat_pubsub/backend.py	Fri Oct 15 09:32:07 2021 +0200
+++ b/sat_pubsub/backend.py	Fri Oct 15 09:32:07 2021 +0200
@@ -302,37 +302,26 @@
 
         return options
 
-    def _checkAuth(self, node, requestor):
+    async def _checkAuth(self, node, requestor):
         """ Check authorisation of publishing in node for requestor """
-
-        def check(affiliation):
-            d = defer.succeed((affiliation, node))
-            configuration = node.getConfiguration()
-            publish_model = configuration[const.OPT_PUBLISH_MODEL]
-            if publish_model == const.VAL_PMODEL_PUBLISHERS:
-                if affiliation not in ['owner', 'publisher']:
+        affiliation = await node.getAffiliation(requestor)
+        configuration = node.getConfiguration()
+        publish_model = configuration[const.OPT_PUBLISH_MODEL]
+        if publish_model == const.VAL_PMODEL_PUBLISHERS:
+            if affiliation not in ['owner', 'publisher']:
+                raise error.Forbidden()
+        elif publish_model == const.VAL_PMODEL_SUBSCRIBERS:
+            if affiliation not in ['owner', 'publisher']:
+                # we are in subscribers publish model, we must check that
+                # the requestor is a subscriber to allow him to publish
+                subscribed = await node.isSubscribed(requestor)
+                if not subscribed:
                     raise error.Forbidden()
-            elif publish_model == const.VAL_PMODEL_SUBSCRIBERS:
-                if affiliation not in ['owner', 'publisher']:
-                    # we are in subscribers publish model, we must check that
-                    # the requestor is a subscriber to allow him to publish
+        elif publish_model != const.VAL_PMODEL_OPEN:
+            # publish_model must be publishers (default), subscribers or open.
+            raise ValueError('Unexpected value')
 
-                    def checkSubscription(subscribed):
-                        if not subscribed:
-                            raise error.Forbidden()
-                        return (affiliation, node)
-
-                    d.addCallback(lambda __: node.isSubscribed(requestor))
-                    d.addCallback(checkSubscription)
-            elif publish_model != const.VAL_PMODEL_OPEN:
-                # publish_model must be publishers (default), subscribers or open.
-                raise ValueError('Unexpected value')
-
-            return d
-
-        d = node.getAffiliation(requestor)
-        d.addCallback(check)
-        return d
+        return (affiliation, node)
 
     def parseItemConfig(self, item):
         """Get and remove item configuration information
@@ -705,7 +694,21 @@
     def supportsInstantNodes(self):
         return True
 
-    def createNode(self, nodeIdentifier, requestor, options=None, pep=False, recipient=None):
+    async def _createNode(
+            self,
+            nodeIdentifier: Optional[str],
+            requestor: jid.JID,
+            options: Optional[dict] = None,
+            pep: bool = False,
+            recipient: Optional[jid.JID] = None
+    ) -> str:
+        if pep:
+            if recipient == self.server_jid:
+                if not self.isAdmin(requestor):
+                    raise error.Forbidden()
+            elif requestor.userhostJID() != recipient.userhostJID():
+                 raise error.Forbidden()
+
         if not nodeIdentifier:
             nodeIdentifier = 'generic/%s' % uuid.uuid4()
 
@@ -718,9 +721,26 @@
         config.update(options)
 
         # TODO: handle schema on creation
-        d = self.storage.createNode(nodeIdentifier, requestor, config, None, pep, recipient)
-        d.addCallback(lambda _: nodeIdentifier)
-        return d
+        await self.storage.createNode(
+            nodeIdentifier, requestor, config, None, pep, recipient
+        )
+        return nodeIdentifier
+
+    def createNode(
+            self,
+            nodeIdentifier: Optional[str],
+            requestor: jid.JID,
+            options: Optional[dict] = None,
+            pep: bool = False,
+            recipient: Optional[jid.JID] = None
+    ) -> defer.Deferred:
+        return defer.ensureDeferred(self._createNode(
+            nodeIdentifier=nodeIdentifier,
+            requestor=requestor,
+            options=options,
+            pep=pep,
+            recipient=recipient
+        ))
 
     def getDefaultConfiguration(self, nodeType):
         d = defer.succeed(self.storage.getDefaultConfiguration(nodeType))