diff sat_pubsub/backend.py @ 354:18b983fe9e1b

backend: added "presence" access_model: - move presence checking method in separated method so they can be use for get and subscriptions - added VAL_AMODEL_PRESENCE constant
author Goffi <goffi@goffi.org>
date Fri, 08 Sep 2017 08:02:05 +0200
parents 7c5d85c6fb3a
children c72fcbdcdab7
line wrap: on
line diff
--- a/sat_pubsub/backend.py	Fri Sep 08 08:02:05 2017 +0200
+++ b/sat_pubsub/backend.py	Fri Sep 08 08:02:05 2017 +0200
@@ -124,6 +124,7 @@
                  "label": "Who can subscribe to this node",
                  "options": {
                      const.VAL_AMODEL_OPEN: "Public node",
+                     const.VAL_AMODEL_PRESENCE: "Node restricted to entites subscribed to owner presence",
                      const.VAL_AMODEL_PUBLISHER_ROSTER: "Node restricted to some groups of publisher's roster",
                      const.VAL_AMODEL_WHITELIST: "Node restricted to some jids",
                      }
@@ -471,7 +472,15 @@
 
         access_model = node.getAccessModel()
 
-        if access_model != const.VAL_AMODEL_OPEN:
+        if access_model == const.VAL_AMODEL_OPEN:
+            d = defer.succeed(None)
+        elif access_model == const.VAL_AMODEL_PRESENCE:
+            d = self.checkPresenceSubscription(node, subscriber)
+        elif access_model == const.VAL_AMODEL_PUBLISHER_ROSTER:
+            d = self.checkRosterGroups(node, subscriber)
+        elif access_model == const.VAL_AMODEL_WHITELIST:
+            d = self.checkNodeAffiliations(node, subscriber)
+        else:
             raise NotImplementedError
 
         def trapExists(failure):
@@ -766,6 +775,67 @@
         for item_data in items_to_remove:
             items_data.remove(item_data)
 
+    def checkPresenceSubscription(self, node, requestor):
+        """check if requestor has presence subscription from node owner
+
+        @param node(Node): node to check
+        @param requestor(jid.JID): entity who want to access node
+        """
+        def gotRoster(roster):
+            if roster is None:
+                raise error.Forbidden()
+
+            if requestor not in roster:
+                raise error.Forbidden()
+
+            if not roster[requestor].subscriptionFrom:
+                raise error.Forbidden()
+
+        d = self.getOwnerRoster(node)
+        d.addCallback(gotRoster)
+        return d
+
+    @defer.inlineCallbacks
+    def checkRosterGroups(self, node, requestor):
+        """check if requestor is in allowed groups of a node
+
+        @param node(Node): node to check
+        @param requestor(jid.JID): entity who want to access node
+        """
+        roster = yield self.getOwnerRoster(node)
+
+        if roster is None:
+            raise error.Forbidden()
+
+        if requestor not in roster:
+            raise error.Forbidden()
+
+        authorized_groups = yield node.getAuthorizedGroups()
+
+        if not roster[requestor].groups.intersection(authorized_groups):
+            # requestor is in roster but not in one of the allowed groups
+            raise error.Forbidden()
+
+    @defer.inlineCallbacks
+    def checkNodeAffiliations(self, node, requestor):
+        """check if requestor is in white list of a node
+
+        @param node(Node): node to check
+        @param requestor(jid.JID): entity who want to access node
+        """
+        def gotAffiliations(affiliations):
+            try:
+                affiliation = affiliations[requestor.userhostJID()]
+            except KeyError:
+                raise error.Forbidden()
+            else:
+                if affiliation not in ('owner', 'publisher', 'member'):
+                    raise error.Forbidden()
+
+        d = node.getAffiliations()
+        d.addCallback(gotAffiliations)
+        return d
+
     @defer.inlineCallbacks
     def checkNodeAccess(self, node, requestor):
         """check if a requestor can access data of a node
@@ -795,30 +865,13 @@
 
         if access_model == const.VAL_AMODEL_OPEN or owner:
             pass
+        elif access_model == const.VAL_AMODEL_PRESENCE:
+            yield self.checkPresenceSubscription(node, requestor)
         elif access_model == const.VAL_AMODEL_PUBLISHER_ROSTER:
-            # FIXME: publisher roster should be used, not owner
-            roster = yield self.getOwnerRoster(node)
-
-            if roster is None:
-                raise error.Forbidden()
-
-            if requestor not in roster:
-                raise error.Forbidden()
-
-            authorized_groups = yield node.getAuthorizedGroups()
-
-            if not roster[requestor].groups.intersection(authorized_groups):
-                # requestor is in roster but not in one of the allowed groups
-                raise error.Forbidden()
+            # FIXME: for node, access should be renamed owner-roster, not publisher
+            yield self.checkRosterGroups(node, requestor)
         elif access_model == const.VAL_AMODEL_WHITELIST:
-            affiliations = yield node.getAffiliations()
-            try:
-                affiliation = affiliations[requestor.userhostJID()]
-            except KeyError:
-                raise error.Forbidden()
-            else:
-                if affiliation not in ('owner', 'publisher', 'member'):
-                    raise error.Forbidden()
+            yield self.checkNodeAffiliations(node, requestor)
         else:
             raise Exception(u"Unknown access_model")
 
@@ -1501,8 +1554,9 @@
         return d.addErrback(self._mapErrors)
 
     def subscriptions(self, request):
-        d = self.backend.getSubscriptions(self._isPep(request),
-                                          request.sender)
+        d = self.backend.getSubscriptions(request.sender,
+                                          self._isPep(request),
+                                          request.recipient)
         return d.addErrback(self._mapErrors)
 
     def affiliations(self, request):