Mercurial > libervia-pubsub
comparison src/backend.py @ 394:dc83b1d837cf
backend: fixed recursion error on getFullItem:
getFullItem was doing a deepcopy of the item which could lead to infinite recursion if element had children. This has been fixed by doing a specialised copy function.
For the same reason, an itemDataCopy function has also been implemented.
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 18 Feb 2019 19:12:04 +0100 |
parents | 3fb2ff438f09 |
children | 9bc3fbf3e685 |
comparison
equal
deleted
inserted
replaced
393:728b08c0d000 | 394:dc83b1d837cf |
---|---|
59 U{XEP-0060<http://www.xmpp.org/extensions/xep-0060.html>} that interacts with | 59 U{XEP-0060<http://www.xmpp.org/extensions/xep-0060.html>} that interacts with |
60 a given storage facility. It also provides an adapter from the XMPP | 60 a given storage facility. It also provides an adapter from the XMPP |
61 publish-subscribe protocol. | 61 publish-subscribe protocol. |
62 """ | 62 """ |
63 | 63 |
64 import copy | |
64 import uuid | 65 import uuid |
65 | 66 |
66 from zope.interface import implements | 67 from zope.interface import implements |
67 | 68 |
68 from twisted.application import service | 69 from twisted.application import service |
82 from sat_pubsub import error | 83 from sat_pubsub import error |
83 from sat_pubsub import iidavoll | 84 from sat_pubsub import iidavoll |
84 from sat_pubsub import const | 85 from sat_pubsub import const |
85 from sat_pubsub import container | 86 from sat_pubsub import container |
86 | 87 |
87 from copy import deepcopy | |
88 | |
89 | 88 |
90 def _getAffiliation(node, entity): | 89 def _getAffiliation(node, entity): |
91 d = node.getAffiliation(entity) | 90 d = node.getAffiliation(entity) |
92 d.addCallback(lambda affiliation: (node, affiliation)) | 91 d.addCallback(lambda affiliation: (node, affiliation)) |
93 return d | 92 return d |
93 | |
94 | |
95 def elementCopy(element): | |
96 """Make a copy of a domish.Element | |
97 | |
98 The copy will have its own children list, so other elements | |
99 can be added as direct children without modifying orignal one. | |
100 Children are not deeply copied, so if an element is added to a child or grandchild, | |
101 it will also affect original element. | |
102 @param element(domish.Element): Element to clone | |
103 """ | |
104 new_elt = domish.Element( | |
105 (element.uri, element.name), | |
106 defaultUri = element.defaultUri, | |
107 attribs = element.attributes, | |
108 localPrefixes = element.localPrefixes) | |
109 new_elt.parent = element.parent | |
110 new_elt.children = element.children[:] | |
111 return new_elt | |
112 | |
113 | |
114 def itemDataCopy(item_data): | |
115 """Make a copy of an item_data | |
116 | |
117 deep copy every element of the tuple but item | |
118 do an elementCopy of item_data.item | |
119 @param item_data(ItemData): item data to copy | |
120 @return (ItemData): copied data | |
121 """ | |
122 return container.ItemData(*[elementCopy(item_data.item)] | |
123 + [copy.deepcopy(d) for d in item_data[1:]]) | |
94 | 124 |
95 | 125 |
96 class BackendService(service.Service, utility.EventDispatcher): | 126 class BackendService(service.Service, utility.EventDispatcher): |
97 """ | 127 """ |
98 Generic publish-subscribe backend service. | 128 Generic publish-subscribe backend service. |
1299 Used to give item configuration back to node's owner (and *only* to owner) | 1329 Used to give item configuration back to node's owner (and *only* to owner) |
1300 """ | 1330 """ |
1301 # TODO: a test should check that only the owner get the item configuration back | 1331 # TODO: a test should check that only the owner get the item configuration back |
1302 | 1332 |
1303 item, item_config = item_data.item, item_data.config | 1333 item, item_config = item_data.item, item_data.config |
1304 new_item = deepcopy(item) | |
1305 if item_config: | 1334 if item_config: |
1335 new_item = elementCopy(item) | |
1306 new_item.addChild(item_config.toElement()) | 1336 new_item.addChild(item_config.toElement()) |
1307 return new_item | 1337 return new_item |
1338 else: | |
1339 return item | |
1308 | 1340 |
1309 @defer.inlineCallbacks | 1341 @defer.inlineCallbacks |
1310 def _notifyPublish(self, data): | 1342 def _notifyPublish(self, data): |
1311 items_data = data['items_data'] | 1343 items_data = data['items_data'] |
1312 node = data['node'] | 1344 node = data['node'] |
1421 # we ignore owner if he is here | 1453 # we ignore owner if he is here |
1422 continue | 1454 continue |
1423 allowed_items = [] #we keep only item which subscriber can access | 1455 allowed_items = [] #we keep only item which subscriber can access |
1424 | 1456 |
1425 if schema is not None: | 1457 if schema is not None: |
1426 # we have to deepcopy items because different subscribers may receive | 1458 # we have to copy items_data because different subscribers may receive |
1427 # different items (e.g. read restriction in schema) | 1459 # different items (e.g. read restriction in schema) |
1428 items_data = deepcopy(items_data) | 1460 items_data = itemDataCopy(items_data) |
1429 self.backend.filterItemsWithSchema(items_data, schema, False) | 1461 self.backend.filterItemsWithSchema(items_data, schema, False) |
1430 | 1462 |
1431 for item_data in items_data: | 1463 for item_data in items_data: |
1432 item, access_model = item_data.item, item_data.access_model | 1464 item, access_model = item_data.item, item_data.access_model |
1433 access_list = item_data.config | 1465 access_list = item_data.config |