changeset 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 e6a9a3c93314
files sat_pubsub/backend.py sat_pubsub/const.py sat_pubsub/pgsql_storage.py
diffstat 3 files changed, 24 insertions(+), 47 deletions(-) [+]
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)
 
--- a/sat_pubsub/const.py	Fri Dec 18 13:01:02 2015 +0100
+++ b/sat_pubsub/const.py	Mon Dec 21 13:41:15 2015 +0100
@@ -70,8 +70,6 @@
 VAL_PMODEL_SUBSCRIBERS = 'subscribers'
 VAL_PMODEL_OPEN = 'open'
 VAL_PMODEL_DEFAULT = VAL_PMODEL_PUBLISHERS
-
-# FLAG_RETRACT_ALLOW_PUBLISHER = True  # XXX: see the method BackendService._doRetractAllowPublisher
+VAL_RSM_MAX_DEFAULT = 10
 FLAG_ENABLE_RSM = True
-VAL_RSM_MAX_DEFAULT = 10
 FLAG_ENABLE_MAM = True
--- a/sat_pubsub/pgsql_storage.py	Fri Dec 18 13:01:02 2015 +0100
+++ b/sat_pubsub/pgsql_storage.py	Mon Dec 21 13:41:15 2015 +0100
@@ -945,20 +945,6 @@
                           node_id=%s""",
                        (self.nodeDbId,))
 
-   # FIXME: to be checked
-   #  def filterItemsWithPublisher(self, itemIdentifiers, recipient):
-   #      return self.dbpool.runInteraction(self._filterItemsWithPublisher, itemIdentifiers, recipient)
-
-   #  def _filterItemsWithPublisher(self, cursor, itemIdentifiers, requestor):
-   #      self._checkNodeExists(cursor)
-   #      ret = []
-   #      for itemIdentifier in itemIdentifiers:
-   #          args = ["%s/%%" % requestor.userhost(), itemIdentifier]
-   #          cursor.execute("""SELECT item FROM items WHERE publisher LIKE %s AND item=%s""", args)
-   #          result = cursor.fetchone()
-   #          if result:
-   #              ret.append(result[0])
-   #      return ret
 
 class CollectionNode(Node):