# HG changeset patch # User Goffi # Date 1351794523 -3600 # Node ID 25a1dc7181ccc137350d5d3f478d3b20abf6d683 # Parent 0a7d43b3dad61fe7650c7dee9a92189df5344e9b full items, with item-configuration, are returned if items are asked by the owner diff -r 0a7d43b3dad6 -r 25a1dc7181cc sat_pubsub/backend.py --- 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, diff -r 0a7d43b3dad6 -r 25a1dc7181cc sat_pubsub/const.py --- 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 diff -r 0a7d43b3dad6 -r 25a1dc7181cc sat_pubsub/error.py --- 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 diff -r 0a7d43b3dad6 -r 25a1dc7181cc sat_pubsub/pgsql_storage.py --- 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)