changeset 252:25a1dc7181cc

full items, with item-configuration, are returned if items are asked by the owner
author Goffi <goffi@goffi.org>
date Thu, 01 Nov 2012 19:28:43 +0100 (2012-11-01)
parents 0a7d43b3dad6
children 06494c9b25f2
files sat_pubsub/backend.py sat_pubsub/const.py sat_pubsub/error.py sat_pubsub/pgsql_storage.py
diffstat 4 files changed, 115 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/sat_pubsub/backend.py	Tue Oct 23 00:09:38 2012 +0200
+++ b/sat_pubsub/backend.py	Thu Nov 01 19:28:43 2012 +0100
@@ -80,6 +80,7 @@
 from sat_pubsub import error, iidavoll, const
 from sat_pubsub.iidavoll import IBackendService, ILeafNode
 
+from copy import deepcopy
 
 def _getAffiliation(node, entity):
     d = node.getAffiliation(entity)
@@ -476,6 +477,28 @@
     def _doGetItems(self, result, requestor, maxItems, itemIdentifiers):
         node, affiliation = result
 
+        def append_item_config(items_data):
+            ret = []
+            for data in items_data:
+                item, access_model, access_list = data
+                if access_model == const.VAL_OPEN:
+                    pass
+                elif access_model == const.VAL_ROSTER: 
+                    form = data_form.Form('submit', formNamespace=const.NS_ITEM_CONFIG)
+                    access = data_form.Field(None, const.OPT_ACCESS_MODEL, value=const.VAL_ROSTER)
+                    allowed = data_form.Field(None, const.OPT_ROSTER_GROUPS_ALLOWED, values=access_list)
+                    form.addField(access)
+                    form.addField(allowed)
+                    item.addChild(form.toElement())
+                elif access_model == const.VAL_JID:
+                    #FIXME: manage jid
+                    raise NotImplementedError
+                else:
+                    raise error.BadAccessTypeError(access_model)
+                
+                ret.append(item)
+            return ret
+
         def access_checked(access_data):
             authorized, roster = access_data
             if not authorized:
@@ -487,7 +510,11 @@
             if itemIdentifiers:
                 return node.getItemsById(authorized_groups, affiliation == 'owner', itemIdentifiers)
             else:
-                return node.getItems(authorized_groups, affiliation == 'owner', maxItems)
+                if affiliation == 'owner':
+                    d = node.getItems(authorized_groups, True, maxItems)
+                    return d.addCallback(append_item_config)
+                else:
+                    return node.getItems(authorized_groups, False, maxItems)
 
 
         if not ILeafNode.providedBy(node):
@@ -703,7 +730,6 @@
         if self.backend.supportsGroupBlog():
             self.features.append("groupblog")
 
-
     def _notify(self, data):
         items = data['items']
         node = data['node']
@@ -716,10 +742,10 @@
             #we filter items not allowed for the subscribers
             notifications_filtered = []
 
-            for subscriber, subscriptions, items in notifications:
+            for subscriber, subscriptions, _items in notifications:
                 allowed_items = [] #we keep only item which subscriber can access
 
-                for access_model, item_config, item in items:
+                for access_model, item_config, item in _items:
                     if access_model == 'open':
                         allowed_items.append(item)
                     elif access_model == 'roster':
@@ -740,11 +766,24 @@
             #FIXME: check if this comply with XEP-0060 (option needed ?)
             #TODO: item's access model have to be sent back to owner
             #TODO: same thing for getItems
+            
+            def getFullItem(item_data):
+                """ Attach item configuration to this item
+                Used to give item configuration back to node's owner (and *only* to owner)
+                """
+                #TODO: a test should check that only the owner get the item configuration back
+                
+                access_model, item_config, item = item_data
+                new_item = deepcopy(item)
+                if item_config:
+                    new_item.addChild(item_config.toElement())
+                return new_item
+
             notifications_filtered.append((owner_jid,
                                            set([Subscription(node.nodeIdentifier, 
                                                             owner_jid,
                                                             'subscribed')]),
-                                           [item for access_model, item_config, item in items])) 
+                                           [getFullItem(item_data) for item_data in items])) 
 
             return self.pubsubService.notifyPublish(
                                                 self.serviceJID,
--- a/sat_pubsub/const.py	Tue Oct 23 00:09:38 2012 +0200
+++ b/sat_pubsub/const.py	Thu Nov 01 19:28:43 2012 +0100
@@ -59,4 +59,5 @@
 OPT_ROSTER_GROUPS_ALLOWED = 'pubsub#roster_groups_allowed'
 VAL_OPEN = 'open'
 VAL_ROSTER = 'roster'
+VAL_JID = 'jid'
 VAL_DEFAULT = VAL_OPEN
--- a/sat_pubsub/error.py	Tue Oct 23 00:09:38 2012 +0200
+++ b/sat_pubsub/error.py	Thu Nov 01 19:28:43 2012 +0100
@@ -156,3 +156,6 @@
     """
     This node does not support publishing.
     """
+
+class BadAccessTypeError(Error):
+    pass
--- a/sat_pubsub/pgsql_storage.py	Tue Oct 23 00:09:38 2012 +0200
+++ b/sat_pubsub/pgsql_storage.py	Thu Nov 01 19:28:43 2012 +0100
@@ -571,14 +571,20 @@
 
 
     def getItems(self, authorized_groups, unrestricted, maxItems=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 tget
+        @return: list of (item, access_model, access_model) if unrestricted is True, else list of items
+        """
         return self.dbpool.runInteraction(self._getItems, authorized_groups, unrestricted, maxItems)
 
 
     def _getItems(self, cursor, authorized_groups, unrestricted, maxItems):
         self._checkNodeExists(cursor)
         if unrestricted:
-            query = ["""SELECT data FROM nodes
-                       INNER  JOIN items USING (node_id)
+            query = ["""SELECT data,items.access_model,item_id FROM nodes
+                       INNER JOIN items USING (node_id)
                        WHERE node=%s ORDER BY date DESC"""]
             args = [self.nodeIdentifier]
         else:
@@ -601,28 +607,75 @@
         cursor.execute(' '.join(query), args)
 
         result = cursor.fetchall()
+        if unrestricted:
+            ret = []
+            for data in result:
+                item = stripNamespace(parseXml(data[0]))
+                access_model = data[1]
+                item_id = data[2]
+                if access_model == 'roster': #TODO: jid access_model
+                    cursor.execute('SELECT groupname FROM item_groups_authorized WHERE item_id=%s', (item_id,))
+                    access_list = [r[0] for r in cursor.fetchall()] 
+                else:
+                    access_list = None
+
+                ret.append((item, access_model, access_list))
+            return ret
         items = [stripNamespace(parseXml(r[0])) for r in result]
         return items
 
 
     def getItemsById(self, authorized_groups, unrestricted, itemIdentifiers):
-        return self.dbpool.runInteraction(self._getItemsById, itemIdentifiers)
+        """ Get items which are in the given list
+        @param authorized_groups: we want to get items that these groups can access
+        @param unrestricted: if true, don't check permissions
+        @param itemIdentifiers: list of ids of the items we want to get
+        @return: list of (item, access_model, access_model) if unrestricted is True, else list of items
+        """
+        return self.dbpool.runInteraction(self._getItemsById, authorized_groups, unrestricted, itemIdentifiers)
 
 
     def _getItemsById(self, cursor, authorized_groups, unrestricted, itemIdentifiers):
         self._checkNodeExists(cursor)
-        items = []
-        for itemIdentifier in itemIdentifiers:
-            cursor.execute("""SELECT data FROM nodes
-                              INNER JOIN items USING (node_id)
-                              WHERE node=%s AND item=%s""",
-                           (self.nodeIdentifier,
-                            itemIdentifier))
-            result = cursor.fetchone()
-            if result:
-                items.append(parseXml(result[0]))
-        return items
+        ret = []
+        if unrestricted: #we get everything without checking permissions
+            for itemIdentifier in itemIdentifiers:
+                cursor.execute("""SELECT data,items.access_model,item_id FROM nodes
+                                  INNER JOIN items USING (node_id)
+                                  WHERE node=%s AND item=%s""",
+                               (self.nodeIdentifier,
+                                itemIdentifier))
+                result = cursor.fetchone()
+                if result:
+                    for data in result:
+                        item = stripNamespace(parseXml(data[0]))
+                        access_model = data[1]
+                        item_id = data[2]
+                        if access_model == 'roster': #TODO: jid access_model
+                            cursor.execute('SELECT groupname FROM item_groups_authorized WHERE item_id=%s', (item_id,))
+                            access_list = [r[0] for r in cursor.fetchall()] 
+                        else:
+                            access_list = None
 
+                        ret.append((item, access_model, access_list))
+        else: #we check permission before returning items
+            for itemIdentifier in itemIdentifiers:
+                args = [self.nodeIdentifier, itemIdentifier]
+                if authorized_groups:
+                    args.append(authorized_groups)
+                cursor.execute("""SELECT data FROM nodes
+                           INNER  JOIN items USING (node_id)
+                           LEFT JOIN item_groups_authorized USING (item_id)
+                           WHERE node=%s AND item=%s AND
+                           (items.access_model='open' """ + 
+                           ("or (items.access_model='roster' and groupname in %s)" if authorized_groups else '') + ")",
+                           args)
+
+                result = cursor.fetchone()
+                if result:
+                    ret.append(parseXml(result[0]))
+        
+        return ret
 
     def purge(self):
         return self.dbpool.runInteraction(self._purge)