changeset 346:3bbab2173ebc

implemented disco items: - new getItemsIds method to get only ids of items, without payload or extra data - added delegation (PEP) data for disco items requests. It's a really dirty hack, but there is not clean way to do it beside rewriting the whole thing - authorized node items are returned on disco items when node is specified - if no node is specified, the nodes list is returned
author Goffi <goffi@goffi.org>
date Thu, 24 Aug 2017 01:17:28 +0200
parents 83122f15b993
children f33406fcab5c
files sat_pubsub/backend.py sat_pubsub/delegation.py sat_pubsub/pgsql_storage.py
diffstat 3 files changed, 76 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/sat_pubsub/backend.py	Sun Aug 20 22:55:28 2017 +0200
+++ b/sat_pubsub/backend.py	Thu Aug 24 01:17:28 2017 +0200
@@ -662,6 +662,15 @@
         return d
 
 
+    def getItemsIds(self, nodeIdentifier, authorized_groups, unrestricted, maxItems=None, ext_data=None, pep=False, recipient=None):
+        d = self.storage.getNode(nodeIdentifier, pep, recipient)
+        d.addCallback(lambda node: node.getItemsIds(authorized_groups,
+                                                    unrestricted,
+                                                    maxItems,
+                                                    ext_data))
+        return d
+
+
     def getItems(self, nodeIdentifier, requestor, recipient, maxItems=None,
                        itemIdentifiers=None, ext_data=None):
         d = self.getItemsData(nodeIdentifier, requestor, recipient, maxItems, itemIdentifiers, ext_data)
@@ -1276,12 +1285,26 @@
         d.addErrback(self._mapErrors)
         return d
 
+    def getNodes(self, requestor, service, nodeIdentifier):
+        try:
+            pep = service.pep
+        except AttributeError:
+            pep = False
 
-    def getNodes(self, requestor, service, nodeIdentifier, pep=None):
-        return defer.succeed([]) # FIXME: disabled for now, need to manage PEP
         if service.resource:
             return defer.succeed([])
-        d = self.backend.getNodes(pep)
+
+        if nodeIdentifier:
+            d = self.backend.getItemsIds(nodeIdentifier,
+                                         [],
+                                         requestor.userhostJID() == service,
+                                         None,
+                                         None,
+                                         pep,
+                                         service)
+
+        else:
+            d = self.backend.getNodes(pep)
         return d.addErrback(self._mapErrors)
 
 
--- a/sat_pubsub/delegation.py	Sun Aug 20 22:55:28 2017 +0200
+++ b/sat_pubsub/delegation.py	Thu Aug 24 01:17:28 2017 +0200
@@ -266,3 +266,28 @@
 
     def getDiscoItems(self, requestor, target, nodeIdentifier=''):
         return []
+
+
+# we monkeypatch DiscoHandler to add delegation informations
+def _onDiscoItems(self, iq):
+    request = disco._DiscoRequest.fromElement(iq)
+    # it's really ugly to attach pep data to recipient
+    # but we don't have many options
+    request.recipient.pep = iq.delegated
+
+    def toResponse(items):
+        response = disco.DiscoItems()
+        response.nodeIdentifier = request.nodeIdentifier
+
+        for item in items:
+            response.append(item)
+
+        return response.toElement()
+
+    d = self.items(request.sender, request.recipient,
+                   request.nodeIdentifier)
+    d.addCallback(toResponse)
+    return d
+
+
+disco.DiscoHandler._onDiscoItems = _onDiscoItems
--- a/sat_pubsub/pgsql_storage.py	Sun Aug 20 22:55:28 2017 +0200
+++ b/sat_pubsub/pgsql_storage.py	Thu Aug 24 01:17:28 2017 +0200
@@ -784,6 +784,7 @@
 
     def getItems(self, authorized_groups, unrestricted, maxItems=None, ext_data=None):
         """ Get all authorised items
+
         @param authorized_groups: we want to get items that these groups can access
         @param unrestricted: if true, don't check permissions (i.e.: get all items)
         @param maxItems: nb of items we want to get
@@ -796,6 +797,20 @@
             ext_data = {}
         return self.dbpool.runInteraction(self._getItems, authorized_groups, unrestricted, maxItems, ext_data)
 
+    def getItemsIds(self, authorized_groups, unrestricted, maxItems=None, ext_data=None):
+        """ Get all authorised items ids
+
+        @param authorized_groups: we want to get items that these groups can access
+        @param unrestricted: if true, don't check permissions (i.e.: get all items)
+        @param maxItems: nb of items we want to get
+        @param ext_data: options for extra features like RSM and MAM
+
+        @return list(unicode): list of ids
+        """
+        if ext_data is None:
+            ext_data = {}
+        return self.dbpool.runInteraction(self._getItems, authorized_groups, unrestricted, maxItems, ext_data, ids_only=True)
+
     def _appendSourcesAndFilters(self, query, args, authorized_groups, unrestricted, ext_data):
         """append sources and filters to sql query requesting items and return ORDER BY
 
@@ -847,7 +862,7 @@
 
         return "ORDER BY item_id DESC"
 
-    def _getItems(self, cursor, authorized_groups, unrestricted, maxItems, ext_data):
+    def _getItems(self, cursor, authorized_groups, unrestricted, maxItems, ext_data, ids_only):
         self._checkNodeExists(cursor)
 
         if maxItems == 0:
@@ -856,7 +871,10 @@
         args = []
 
         # SELECT
-        query = ["SELECT data,items.access_model,item_id,date"]
+        if ids_only:
+            query = ["SELECT item"]
+        else:
+            query = ["SELECT data,items.access_model,item_id,date"]
 
         query_order = self._appendSourcesAndFilters(query, args, authorized_groups, unrestricted, ext_data)
 
@@ -901,7 +919,7 @@
         cursor.execute(' '.join(query), args)
 
         result = cursor.fetchall()
-        if unrestricted:
+        if unrestricted and not ids_only:
             # with unrestricted query, we need to fill the access_list for a roster access items
             ret = []
             for data in result:
@@ -918,7 +936,10 @@
                 # TODO: whitelist item access model
             return ret
 
-        items_data = [container.ItemData(generic.stripNamespace(parseXml(r[0])), r[1], r[2], date=r[3]) for r in result]
+        if ids_only:
+            return [r[0] for r in result]
+        else:
+            items_data = [container.ItemData(generic.stripNamespace(parseXml(r[0])), r[1], r[2], date=r[3]) for r in result]
         return items_data
 
     def getItemsById(self, authorized_groups, unrestricted, itemIdentifiers):