Mercurial > libervia-pubsub
comparison sat_pubsub/backend.py @ 301:05c875a13a62
categories are now stored in a dedicated table if item contain an atom entry:
- database creation/update files include the new table
- item data are now stored in a ItemData namedtuple
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 25 Nov 2015 18:33:38 +0100 |
parents | c5acb4995fde |
children | b8b25efae0bc |
comparison
equal
deleted
inserted
replaced
300:c5acb4995fde | 301:05c875a13a62 |
---|---|
79 | 79 |
80 from sat_pubsub import error, iidavoll, const | 80 from sat_pubsub import error, iidavoll, const |
81 from sat_pubsub.iidavoll import IBackendService, ILeafNode | 81 from sat_pubsub.iidavoll import IBackendService, ILeafNode |
82 | 82 |
83 from copy import deepcopy | 83 from copy import deepcopy |
84 from collections import namedtuple | |
85 | |
86 | |
87 ItemData = namedtuple('ItemData', ('item', 'access_model', 'config', 'categories')) | |
84 | 88 |
85 | 89 |
86 def _getAffiliation(node, entity): | 90 def _getAffiliation(node, entity): |
87 d = node.getAffiliation(entity) | 91 d = node.getAffiliation(entity) |
88 d.addCallback(lambda affiliation: (node, affiliation)) | 92 d.addCallback(lambda affiliation: (node, affiliation)) |
243 d.addCallback(check) | 247 d.addCallback(check) |
244 return d | 248 return d |
245 | 249 |
246 def parseItemConfig(self, item): | 250 def parseItemConfig(self, item): |
247 """Get and remove item configuration information | 251 """Get and remove item configuration information |
248 @param item: | 252 |
253 @param item (domish.Element): item to parse | |
254 @return (tuple[unicode, dict)): (access_model, item_config) | |
249 """ | 255 """ |
250 item_config = None | 256 item_config = None |
251 access_model = const.VAL_AMODEL_DEFAULT | 257 access_model = const.VAL_AMODEL_DEFAULT |
252 for idx, elt in enumerate(item.children): | 258 for idx, elt in enumerate(item.children): |
253 if elt.uri != 'data_form.NS_X_DATA' or elt.name != 'x': | 259 if elt.uri != 'data_form.NS_X_DATA' or elt.name != 'x': |
259 break | 265 break |
260 | 266 |
261 if item_config: | 267 if item_config: |
262 access_model = item_config.get(const.OPT_ACCESS_MODEL, const.VAL_AMODEL_DEFAULT) | 268 access_model = item_config.get(const.OPT_ACCESS_MODEL, const.VAL_AMODEL_DEFAULT) |
263 return (access_model, item_config) | 269 return (access_model, item_config) |
270 | |
271 def parseCategories(self, item_elt): | |
272 """Check if item contain an atom entry, and parse categories if possible | |
273 | |
274 @param item (domish.Element): item to parse | |
275 @return (list): list of found categories | |
276 """ | |
277 categories = [] | |
278 try: | |
279 entry_elt = item_elt.elements(const.NS_ATOM, "entry").next() | |
280 except StopIteration: | |
281 return categories | |
282 | |
283 for category_elt in entry_elt.elements(const.NS_ATOM, 'category'): | |
284 category = category_elt.getAttribute('term') | |
285 if category: | |
286 categories.append(category) | |
287 | |
288 return categories | |
264 | 289 |
265 def _checkOverwrite(self, node, itemIdentifiers, publisher): | 290 def _checkOverwrite(self, node, itemIdentifiers, publisher): |
266 """Check that the itemIdentifiers correspond to items published | 291 """Check that the itemIdentifiers correspond to items published |
267 by the current publisher""" | 292 by the current publisher""" |
268 def doCheck(item_pub_map): | 293 def doCheck(item_pub_map): |
309 if not item.getAttribute("id"): | 334 if not item.getAttribute("id"): |
310 item["id"] = str(uuid.uuid4()) | 335 item["id"] = str(uuid.uuid4()) |
311 else: | 336 else: |
312 check_overwrite = True | 337 check_overwrite = True |
313 access_model, item_config = self.parseItemConfig(item) | 338 access_model, item_config = self.parseItemConfig(item) |
314 items_data.append((item, access_model, item_config)) | 339 categories = self.parseCategories(item) |
340 items_data.append(ItemData(item, access_model, item_config, categories)) | |
315 | 341 |
316 if persistItems: | 342 if persistItems: |
317 if check_overwrite and affiliation != 'owner': | 343 if check_overwrite and affiliation != 'owner': |
318 # we don't want a publisher to overwrite the item | 344 # we don't want a publisher to overwrite the item |
319 # of an other publisher | 345 # of an other publisher |
329 return d | 355 return d |
330 | 356 |
331 | 357 |
332 def _doNotify(self, result, node, items_data, deliverPayloads, pep, recipient): | 358 def _doNotify(self, result, node, items_data, deliverPayloads, pep, recipient): |
333 if items_data and not deliverPayloads: | 359 if items_data and not deliverPayloads: |
334 for access_model, item_config, item in items_data: | 360 for item_data in items_data: |
335 item.children = [] | 361 item_data.item.children = [] |
336 self.dispatch({'items_data': items_data, 'node': node, 'pep': pep, 'recipient': recipient}, | 362 self.dispatch({'items_data': items_data, 'node': node, 'pep': pep, 'recipient': recipient}, |
337 '//event/pubsub/notify') | 363 '//event/pubsub/notify') |
338 | 364 |
339 | 365 |
340 def getNotifications(self, nodeDbId, items_data): | 366 def getNotifications(self, nodeDbId, items_data): |
573 ext_data): | 599 ext_data): |
574 node, affiliation = result | 600 node, affiliation = result |
575 | 601 |
576 def append_item_config(items_data): | 602 def append_item_config(items_data): |
577 ret = [] | 603 ret = [] |
578 for data in items_data: | 604 for item, access_model, access_list in items_data: |
579 item, access_model, access_list = data | |
580 if access_model == const.VAL_AMODEL_OPEN: | 605 if access_model == const.VAL_AMODEL_OPEN: |
581 pass | 606 pass |
582 elif access_model == const.VAL_AMODEL_ROSTER: | 607 elif access_model == const.VAL_AMODEL_ROSTER: |
583 form = data_form.Form('submit', formNamespace=const.NS_ITEM_CONFIG) | 608 form = data_form.Form('submit', formNamespace=const.NS_ITEM_CONFIG) |
584 access = data_form.Field(None, const.OPT_ACCESS_MODEL, value=const.VAL_AMODEL_ROSTER) | 609 access = data_form.Field(None, const.OPT_ACCESS_MODEL, value=const.VAL_AMODEL_ROSTER) |
734 # we need to get the items before removing them, for the notifications | 759 # we need to get the items before removing them, for the notifications |
735 | 760 |
736 def removeItems(items_data): | 761 def removeItems(items_data): |
737 """Remove the items and keep only actually removed ones in items_data""" | 762 """Remove the items and keep only actually removed ones in items_data""" |
738 d = node.removeItems(itemIdentifiers) | 763 d = node.removeItems(itemIdentifiers) |
739 d.addCallback(lambda removed: [item_data for item_data in items_data if item_data[0]["id"] in removed]) | 764 d.addCallback(lambda removed: [item_data for item_data in items_data if item_data.item["id"] in removed]) |
740 return d | 765 return d |
741 | 766 |
742 d = node.getItemsById(None, True, itemIdentifiers) | 767 d = node.getItemsById(None, True, itemIdentifiers) |
743 d.addCallback(removeItems) | 768 d.addCallback(removeItems) |
744 | 769 |
943 """ Attach item configuration to this item | 968 """ Attach item configuration to this item |
944 Used to give item configuration back to node's owner (and *only* to owner) | 969 Used to give item configuration back to node's owner (and *only* to owner) |
945 """ | 970 """ |
946 #TODO: a test should check that only the owner get the item configuration back | 971 #TODO: a test should check that only the owner get the item configuration back |
947 | 972 |
948 item, access_model, item_config = item_data | 973 item, item_config = item_data.item, item_data.config |
949 new_item = deepcopy(item) | 974 new_item = deepcopy(item) |
950 if item_config: | 975 if item_config: |
951 new_item.addChild(item_config.toElement()) | 976 new_item.addChild(item_config.toElement()) |
952 return new_item | 977 return new_item |
953 | 978 |
1029 notifications, (owner_jid,roster) = result | 1054 notifications, (owner_jid,roster) = result |
1030 | 1055 |
1031 #we filter items not allowed for the subscribers | 1056 #we filter items not allowed for the subscribers |
1032 notifications_filtered = [] | 1057 notifications_filtered = [] |
1033 | 1058 |
1034 for subscriber, subscriptions, _items_data in notifications: | 1059 for subscriber, subscriptions, items_data in notifications: |
1035 if subscriber == owner_jid: | 1060 if subscriber == owner_jid: |
1036 # as notification is always sent to owner, | 1061 # as notification is always sent to owner, |
1037 # we ignore owner if he is here | 1062 # we ignore owner if he is here |
1038 continue | 1063 continue |
1039 allowed_items = [] #we keep only item which subscriber can access | 1064 allowed_items = [] #we keep only item which subscriber can access |
1040 | 1065 |
1041 for item, access_model, access_list in _items_data: | 1066 for item_data in items_data: |
1067 item, access_model = item_data.item, item_data.access_model | |
1068 access_list = item_data.config | |
1042 if access_model == const.VAL_AMODEL_OPEN: | 1069 if access_model == const.VAL_AMODEL_OPEN: |
1043 allowed_items.append(item) | 1070 allowed_items.append(item) |
1044 elif access_model == const.VAL_AMODEL_ROSTER: | 1071 elif access_model == const.VAL_AMODEL_ROSTER: |
1045 _subscriber = subscriber.userhostJID() | 1072 _subscriber = subscriber.userhostJID() |
1046 if not _subscriber in roster: | 1073 if not _subscriber in roster: |