diff sat_pubsub/backend.py @ 309:890b24b37b56

Re-implemented feature which allows an entity to retract an item from somebody else node (i.e. a node from which he is neither owner or publisher) if he is the publisher of the item.
author Goffi <goffi@goffi.org>
date Mon, 21 Dec 2015 13:41:15 +0100
parents 087b705493a6
children a776544d84e5
line wrap: on
line diff
--- a/sat_pubsub/backend.py	Fri Dec 18 13:01:02 2015 +0100
+++ b/sat_pubsub/backend.py	Mon Dec 21 13:41:15 2015 +0100
@@ -731,40 +731,13 @@
     def retractItem(self, nodeIdentifier, itemIdentifiers, requestor, notify, pep, recipient):
         d = self.storage.getNode(nodeIdentifier, pep, recipient)
         d.addCallback(_getAffiliation, requestor)
-        # FIXME: to be checked
-        # if const.FLAG_RETRACT_ALLOW_PUBLISHER:
-        #     d.addCallback(self._doRetractAllowPublisher, itemIdentifiers, requestor)
-        # else:
-        #     d.addCallback(self._doRetract, itemIdentifiers)
-        d.addCallback(self._doRetract, itemIdentifiers, notify, pep, recipient)
+        d.addCallback(self._doRetract, itemIdentifiers, requestor, notify, pep, recipient)
         return d
 
-    # FIXME: to be checked
-    # def _doRetractAllowPublisher(self, result, itemIdentifiers, requestor):
-    #     """This method has been added to allow the publisher
-    #     of an item to retract it, even if he has no affiliation
-    #     to that item. For instance, this allows you to delete
-    #     an item you posted in a node of "open" publish model.
-    #     """
-    #     node, affiliation = result
-    #     if affiliation in ['owner', 'publisher']:
-    #         return self._doRetract(result, itemIdentifiers)
-    #     d = node.filterItemsWithPublisher(itemIdentifiers, requestor)
-    #     def filterCb(filteredItems):
-    #         if not filteredItems:
-    #             return self._doRetract(result, itemIdentifiers)
-    #         # XXX: fake an affiliation that does NOT exist
-    #         return self._doRetract((node, 'publisher'), filteredItems)
-    #     d.addCallback(filterCb)
-    #     return d
-
-    def _doRetract(self, result, itemIdentifiers, notify, pep, recipient):
+    def _doRetract(self, result, itemIdentifiers, requestor, notify, pep, recipient):
         node, affiliation = result
         persistItems = node.getConfiguration()[const.OPT_PERSIST_ITEMS]
 
-        if affiliation not in ['owner', 'publisher']:
-            raise error.Forbidden()
-
         if not persistItems:
             raise error.NodeNotPersistent()
 
@@ -776,7 +749,27 @@
             d.addCallback(lambda removed: [item_data for item_data in items_data if item_data.item["id"] in removed])
             return d
 
-        d = node.getItemsById(None, True, itemIdentifiers)
+        def checkPublishers(publishers_map):
+            """Called when requestor is neither owner neither publisher of the Node
+
+            We check that requestor is publisher of all the items he wants to retract
+            and raise error.Forbidden if it is not the case
+            """
+            # TODO: the behaviour should be configurable (per node ?)
+            if any((requestor.userhostJID() != publisher.userhostJID() for publisher in publishers_map.itervalues())):
+                raise error.Forbidden()
+
+        if affiliation in ['owner', 'publisher']:
+            # the requestor is owner or publisher of the node
+            # he can retract what he wants
+            d = defer.succeed(None)
+        else:
+            # the requestor doesn't have right to retract on the whole node
+            # we check if he is a publisher for all items he wants to retract
+            # and forbid the retraction else.
+            d = node.getItemsPublishers(itemIdentifiers)
+            d.addCallback(checkPublishers)
+        d.addCallback(lambda dummy: node.getItemsById(None, True, itemIdentifiers))
         d.addCallback(self._tuple2ItemData)
         d.addCallback(removeItems)