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