Mercurial > libervia-backend
comparison sat/memory/params.py @ 2624:56f94936df1e
code style reformatting using black
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 27 Jun 2018 20:14:46 +0200 |
parents | 26edcf3a30eb |
children | e9cd473a2f46 |
comparison
equal
deleted
inserted
replaced
2623:49533de4540b | 2624:56f94936df1e |
---|---|
22 from sat.core import exceptions | 22 from sat.core import exceptions |
23 from sat.core.constants import Const as C | 23 from sat.core.constants import Const as C |
24 from sat.memory.crypto import BlockCipher, PasswordHasher | 24 from sat.memory.crypto import BlockCipher, PasswordHasher |
25 from xml.dom import minidom, NotFoundErr | 25 from xml.dom import minidom, NotFoundErr |
26 from sat.core.log import getLogger | 26 from sat.core.log import getLogger |
27 | |
27 log = getLogger(__name__) | 28 log = getLogger(__name__) |
28 from twisted.internet import defer | 29 from twisted.internet import defer |
29 from twisted.python.failure import Failure | 30 from twisted.python.failure import Failure |
30 from twisted.words.xish import domish | 31 from twisted.words.xish import domish |
31 from twisted.words.protocols.jabber import jid | 32 from twisted.words.protocols.jabber import jid |
41 | 42 |
42 @param jids(iterable[id.jID]): jids to use | 43 @param jids(iterable[id.jID]): jids to use |
43 @return (generator[domish.Element]): <jid/> elements | 44 @return (generator[domish.Element]): <jid/> elements |
44 """ | 45 """ |
45 for jid_ in jids: | 46 for jid_ in jids: |
46 jid_elt = domish.Element((None, 'jid')) | 47 jid_elt = domish.Element((None, "jid")) |
47 jid_elt.addContent(jid_.full()) | 48 jid_elt.addContent(jid_.full()) |
48 yield jid_elt | 49 yield jid_elt |
49 | 50 |
50 | 51 |
51 class Params(object): | 52 class Params(object): |
52 """This class manage parameters with xml""" | 53 """This class manage parameters with xml""" |
54 | |
53 ### TODO: add desciption in params | 55 ### TODO: add desciption in params |
54 | 56 |
55 #TODO: when priority is changed, a new presence stanza must be emitted | 57 # TODO: when priority is changed, a new presence stanza must be emitted |
56 #TODO: int type (Priority should be int instead of string) | 58 # TODO: int type (Priority should be int instead of string) |
57 default_xml = u""" | 59 default_xml = u""" |
58 <params> | 60 <params> |
59 <general> | 61 <general> |
60 </general> | 62 </general> |
61 <individual> | 63 <individual> |
75 <param name="autodisconnect" label="%(autodisconnect_label)s" value="false" type="bool" security="50" /> | 77 <param name="autodisconnect" label="%(autodisconnect_label)s" value="false" type="bool" security="50" /> |
76 </category> | 78 </category> |
77 </individual> | 79 </individual> |
78 </params> | 80 </params> |
79 """ % { | 81 """ % { |
80 'category_general': D_("General"), | 82 "category_general": D_("General"), |
81 'category_connection': D_("Connection"), | 83 "category_connection": D_("Connection"), |
82 'history_param': C.HISTORY_LIMIT, | 84 "history_param": C.HISTORY_LIMIT, |
83 'history_label': D_('Chat history limit'), | 85 "history_label": D_("Chat history limit"), |
84 'show_offline_contacts': C.SHOW_OFFLINE_CONTACTS, | 86 "show_offline_contacts": C.SHOW_OFFLINE_CONTACTS, |
85 'show_offline_contacts_label': D_('Show offline contacts'), | 87 "show_offline_contacts_label": D_("Show offline contacts"), |
86 'show_empty_groups': C.SHOW_EMPTY_GROUPS, | 88 "show_empty_groups": C.SHOW_EMPTY_GROUPS, |
87 'show_empty_groups_label': D_('Show empty groups'), | 89 "show_empty_groups_label": D_("Show empty groups"), |
88 'force_server_param': C.FORCE_SERVER_PARAM, | 90 "force_server_param": C.FORCE_SERVER_PARAM, |
89 'force_port_param': C.FORCE_PORT_PARAM, | 91 "force_port_param": C.FORCE_PORT_PARAM, |
90 'new_account_label': D_("Register new account"), | 92 "new_account_label": D_("Register new account"), |
91 'autoconnect_label': D_('Connect on frontend startup'), | 93 "autoconnect_label": D_("Connect on frontend startup"), |
92 'autodisconnect_label': D_('Disconnect on frontend closure'), | 94 "autodisconnect_label": D_("Disconnect on frontend closure"), |
93 } | 95 } |
94 | 96 |
95 def load_default_params(self): | 97 def load_default_params(self): |
96 self.dom = minidom.parseString(Params.default_xml.encode('utf-8')) | 98 self.dom = minidom.parseString(Params.default_xml.encode("utf-8")) |
97 | 99 |
98 def _mergeParams(self, source_node, dest_node): | 100 def _mergeParams(self, source_node, dest_node): |
99 """Look for every node in source_node and recursively copy them to dest if they don't exists""" | 101 """Look for every node in source_node and recursively copy them to dest if they don't exists""" |
100 | 102 |
101 def getNodesMap(children): | 103 def getNodesMap(children): |
102 ret = {} | 104 ret = {} |
103 for child in children: | 105 for child in children: |
104 if child.nodeType == child.ELEMENT_NODE: | 106 if child.nodeType == child.ELEMENT_NODE: |
105 ret[(child.tagName, child.getAttribute('name'))] = child | 107 ret[(child.tagName, child.getAttribute("name"))] = child |
106 return ret | 108 return ret |
109 | |
107 source_map = getNodesMap(source_node.childNodes) | 110 source_map = getNodesMap(source_node.childNodes) |
108 dest_map = getNodesMap(dest_node.childNodes) | 111 dest_map = getNodesMap(dest_node.childNodes) |
109 source_set = set(source_map.keys()) | 112 source_set = set(source_map.keys()) |
110 dest_set = set(dest_map.keys()) | 113 dest_set = set(dest_map.keys()) |
111 to_add = source_set.difference(dest_set) | 114 to_add = source_set.difference(dest_set) |
118 self._mergeParams(source_map[node_key], dest_map[node_key]) | 121 self._mergeParams(source_map[node_key], dest_map[node_key]) |
119 | 122 |
120 def load_xml(self, xml_file): | 123 def load_xml(self, xml_file): |
121 """Load parameters template from xml file""" | 124 """Load parameters template from xml file""" |
122 self.dom = minidom.parse(xml_file) | 125 self.dom = minidom.parse(xml_file) |
123 default_dom = minidom.parseString(Params.default_xml.encode('utf-8')) | 126 default_dom = minidom.parseString(Params.default_xml.encode("utf-8")) |
124 self._mergeParams(default_dom.documentElement, self.dom.documentElement) | 127 self._mergeParams(default_dom.documentElement, self.dom.documentElement) |
125 | 128 |
126 def loadGenParams(self): | 129 def loadGenParams(self): |
127 """Load general parameters data from storage | 130 """Load general parameters data from storage |
128 | 131 |
138 @param cache: if not None, will be used to store the value, as a short time cache | 141 @param cache: if not None, will be used to store the value, as a short time cache |
139 @return: deferred triggered once params are loaded | 142 @return: deferred triggered once params are loaded |
140 """ | 143 """ |
141 if cache is None: | 144 if cache is None: |
142 self.params[profile] = {} | 145 self.params[profile] = {} |
143 return self.storage.loadIndParams(self.params[profile] if cache is None else cache, profile) | 146 return self.storage.loadIndParams( |
147 self.params[profile] if cache is None else cache, profile | |
148 ) | |
144 | 149 |
145 def purgeProfile(self, profile): | 150 def purgeProfile(self, profile): |
146 """Remove cache data of a profile | 151 """Remove cache data of a profile |
147 | 152 |
148 @param profile: %(doc_profile)s | 153 @param profile: %(doc_profile)s |
149 """ | 154 """ |
150 try: | 155 try: |
151 del self.params[profile] | 156 del self.params[profile] |
152 except KeyError: | 157 except KeyError: |
153 log.error(_(u"Trying to purge cache of a profile not in memory: [%s]") % profile) | 158 log.error( |
159 _(u"Trying to purge cache of a profile not in memory: [%s]") % profile | |
160 ) | |
154 | 161 |
155 def save_xml(self, filename): | 162 def save_xml(self, filename): |
156 """Save parameters template to xml file""" | 163 """Save parameters template to xml file""" |
157 with open(filename, 'wb') as xml_file: | 164 with open(filename, "wb") as xml_file: |
158 xml_file.write(self.dom.toxml('utf-8')) | 165 xml_file.write(self.dom.toxml("utf-8")) |
159 | 166 |
160 def __init__(self, host, storage): | 167 def __init__(self, host, storage): |
161 log.debug("Parameters init") | 168 log.debug("Parameters init") |
162 self.host = host | 169 self.host = host |
163 self.storage = storage | 170 self.storage = storage |
172 @param component(unicode): entry point if profile is a component | 179 @param component(unicode): entry point if profile is a component |
173 @param callback: called when the profile actually exists in database and memory | 180 @param callback: called when the profile actually exists in database and memory |
174 @return: a Deferred instance | 181 @return: a Deferred instance |
175 """ | 182 """ |
176 if self.storage.hasProfile(profile): | 183 if self.storage.hasProfile(profile): |
177 log.info(_('The profile name already exists')) | 184 log.info(_("The profile name already exists")) |
178 return defer.fail(Failure(exceptions.ConflictError)) | 185 return defer.fail(Failure(exceptions.ConflictError)) |
179 if not self.host.trigger.point("ProfileCreation", profile): | 186 if not self.host.trigger.point("ProfileCreation", profile): |
180 return defer.fail(Failure(exceptions.CancelError)) | 187 return defer.fail(Failure(exceptions.CancelError)) |
181 return self.storage.createProfile(profile, component or None) | 188 return self.storage.createProfile(profile, component or None) |
182 | 189 |
187 @param force: force the deletion even if the profile is connected. | 194 @param force: force the deletion even if the profile is connected. |
188 To be used for direct calls only (not through the bridge). | 195 To be used for direct calls only (not through the bridge). |
189 @return: a Deferred instance | 196 @return: a Deferred instance |
190 """ | 197 """ |
191 if not self.storage.hasProfile(profile): | 198 if not self.storage.hasProfile(profile): |
192 log.info(_('Trying to delete an unknown profile')) | 199 log.info(_("Trying to delete an unknown profile")) |
193 return defer.fail(Failure(exceptions.ProfileUnknownError(profile))) | 200 return defer.fail(Failure(exceptions.ProfileUnknownError(profile))) |
194 if self.host.isConnected(profile): | 201 if self.host.isConnected(profile): |
195 if force: | 202 if force: |
196 self.host.disconnect(profile) | 203 self.host.disconnect(profile) |
197 else: | 204 else: |
208 @param return_profile_keys: if True, return unmanaged profile keys (like C.PROF_KEY_ALL). This keys must be managed by the caller | 215 @param return_profile_keys: if True, return unmanaged profile keys (like C.PROF_KEY_ALL). This keys must be managed by the caller |
209 @return: requested profile name | 216 @return: requested profile name |
210 @raise exceptions.ProfileUnknownError: profile doesn't exists | 217 @raise exceptions.ProfileUnknownError: profile doesn't exists |
211 @raise exceptions.ProfileNotSetError: if C.PROF_KEY_NONE is used | 218 @raise exceptions.ProfileNotSetError: if C.PROF_KEY_NONE is used |
212 """ | 219 """ |
213 if profile_key == '@DEFAULT@': | 220 if profile_key == "@DEFAULT@": |
214 default = self.host.memory.memory_data.get('Profile_default') | 221 default = self.host.memory.memory_data.get("Profile_default") |
215 if not default: | 222 if not default: |
216 log.info(_('No default profile, returning first one')) | 223 log.info(_("No default profile, returning first one")) |
217 try: | 224 try: |
218 default = self.host.memory.memory_data['Profile_default'] = self.storage.getProfilesList()[0] | 225 default = self.host.memory.memory_data[ |
226 "Profile_default" | |
227 ] = self.storage.getProfilesList()[0] | |
219 except IndexError: | 228 except IndexError: |
220 log.info(_('No profile exist yet')) | 229 log.info(_("No profile exist yet")) |
221 raise exceptions.ProfileUnknownError(profile_key) | 230 raise exceptions.ProfileUnknownError(profile_key) |
222 return default # FIXME: temporary, must use real default value, and fallback to first one if it doesn't exists | 231 return ( |
232 default | |
233 ) # FIXME: temporary, must use real default value, and fallback to first one if it doesn't exists | |
223 elif profile_key == C.PROF_KEY_NONE: | 234 elif profile_key == C.PROF_KEY_NONE: |
224 raise exceptions.ProfileNotSetError | 235 raise exceptions.ProfileNotSetError |
225 elif return_profile_keys and profile_key in [C.PROF_KEY_ALL]: | 236 elif return_profile_keys and profile_key in [C.PROF_KEY_ALL]: |
226 return profile_key # this value must be managed by the caller | 237 return profile_key # this value must be managed by the caller |
227 if not self.storage.hasProfile(profile_key): | 238 if not self.storage.hasProfile(profile_key): |
228 log.error(_(u'Trying to access an unknown profile (%s)') % profile_key) | 239 log.error(_(u"Trying to access an unknown profile (%s)") % profile_key) |
229 raise exceptions.ProfileUnknownError(profile_key) | 240 raise exceptions.ProfileUnknownError(profile_key) |
230 return profile_key | 241 return profile_key |
231 | 242 |
232 def __get_unique_node(self, parent, tag, name): | 243 def __get_unique_node(self, parent, tag, name): |
233 """return node with given tag | 244 """return node with given tag |
237 @param name: name to check (e.g. "JID") | 248 @param name: name to check (e.g. "JID") |
238 @return: node if it exist or None | 249 @return: node if it exist or None |
239 """ | 250 """ |
240 for node in parent.childNodes: | 251 for node in parent.childNodes: |
241 if node.nodeName == tag and node.getAttribute("name") == name: | 252 if node.nodeName == tag and node.getAttribute("name") == name: |
242 #the node already exists | 253 # the node already exists |
243 return node | 254 return node |
244 #the node is new | 255 # the node is new |
245 return None | 256 return None |
246 | 257 |
247 def updateParams(self, xml, security_limit=C.NO_SECURITY_LIMIT, app=''): | 258 def updateParams(self, xml, security_limit=C.NO_SECURITY_LIMIT, app=""): |
248 """import xml in parameters, update if the param already exists | 259 """import xml in parameters, update if the param already exists |
249 | 260 |
250 If security_limit is specified and greater than -1, the parameters | 261 If security_limit is specified and greater than -1, the parameters |
251 that have a security level greater than security_limit are skipped. | 262 that have a security level greater than security_limit are skipped. |
252 @param xml: parameters in xml form | 263 @param xml: parameters in xml form |
253 @param security_limit: -1 means no security, 0 is the maximum security then the higher the less secure | 264 @param security_limit: -1 means no security, 0 is the maximum security then the higher the less secure |
254 @param app: name of the frontend registering the parameters or empty value | 265 @param app: name of the frontend registering the parameters or empty value |
255 """ | 266 """ |
256 # TODO: should word with domish.Element | 267 # TODO: should word with domish.Element |
257 src_parent = minidom.parseString(xml.encode('utf-8')).documentElement | 268 src_parent = minidom.parseString(xml.encode("utf-8")).documentElement |
258 | 269 |
259 def pre_process_app_node(src_parent, security_limit, app): | 270 def pre_process_app_node(src_parent, security_limit, app): |
260 """Parameters that are registered from a frontend must be checked""" | 271 """Parameters that are registered from a frontend must be checked""" |
261 to_remove = [] | 272 to_remove = [] |
262 for type_node in src_parent.childNodes: | 273 for type_node in src_parent.childNodes: |
263 if type_node.nodeName != C.INDIVIDUAL: | 274 if type_node.nodeName != C.INDIVIDUAL: |
264 to_remove.append(type_node) # accept individual parameters only | 275 to_remove.append(type_node) # accept individual parameters only |
265 continue | 276 continue |
266 for cat_node in type_node.childNodes: | 277 for cat_node in type_node.childNodes: |
267 if cat_node.nodeName != 'category': | 278 if cat_node.nodeName != "category": |
268 to_remove.append(cat_node) | 279 to_remove.append(cat_node) |
269 continue | 280 continue |
270 to_remove_count = 0 # count the params to be removed from current category | 281 to_remove_count = ( |
282 0 | |
283 ) # count the params to be removed from current category | |
271 for node in cat_node.childNodes: | 284 for node in cat_node.childNodes: |
272 if node.nodeName != "param" or not self.checkSecurityLimit(node, security_limit): | 285 if node.nodeName != "param" or not self.checkSecurityLimit( |
286 node, security_limit | |
287 ): | |
273 to_remove.append(node) | 288 to_remove.append(node) |
274 to_remove_count += 1 | 289 to_remove_count += 1 |
275 continue | 290 continue |
276 node.setAttribute('app', app) | 291 node.setAttribute("app", app) |
277 if len(cat_node.childNodes) == to_remove_count: # remove empty category | 292 if ( |
293 len(cat_node.childNodes) == to_remove_count | |
294 ): # remove empty category | |
278 for dummy in xrange(0, to_remove_count): | 295 for dummy in xrange(0, to_remove_count): |
279 to_remove.pop() | 296 to_remove.pop() |
280 to_remove.append(cat_node) | 297 to_remove.append(cat_node) |
281 for node in to_remove: | 298 for node in to_remove: |
282 node.parentNode.removeChild(node) | 299 node.parentNode.removeChild(node) |
283 | 300 |
284 def import_node(tgt_parent, src_parent): | 301 def import_node(tgt_parent, src_parent): |
285 for child in src_parent.childNodes: | 302 for child in src_parent.childNodes: |
286 if child.nodeName == '#text': | 303 if child.nodeName == "#text": |
287 continue | 304 continue |
288 node = self.__get_unique_node(tgt_parent, child.nodeName, child.getAttribute("name")) | 305 node = self.__get_unique_node( |
306 tgt_parent, child.nodeName, child.getAttribute("name") | |
307 ) | |
289 if not node: # The node is new | 308 if not node: # The node is new |
290 tgt_parent.appendChild(child.cloneNode(True)) | 309 tgt_parent.appendChild(child.cloneNode(True)) |
291 else: | 310 else: |
292 if child.nodeName == "param": | 311 if child.nodeName == "param": |
293 # The child updates an existing parameter, we replace the node | 312 # The child updates an existing parameter, we replace the node |
308 @param xml: XML definition of the parameters to be added | 327 @param xml: XML definition of the parameters to be added |
309 @param security_limit: -1 means no security, 0 is the maximum security then the higher the less secure | 328 @param security_limit: -1 means no security, 0 is the maximum security then the higher the less secure |
310 @param app: name of the frontend registering the parameters | 329 @param app: name of the frontend registering the parameters |
311 """ | 330 """ |
312 if not app: | 331 if not app: |
313 log.warning(_(u"Trying to register frontends parameters with no specified app: aborted")) | 332 log.warning( |
333 _( | |
334 u"Trying to register frontends parameters with no specified app: aborted" | |
335 ) | |
336 ) | |
314 return | 337 return |
315 if not hasattr(self, "frontends_cache"): | 338 if not hasattr(self, "frontends_cache"): |
316 self.frontends_cache = [] | 339 self.frontends_cache = [] |
317 if app in self.frontends_cache: | 340 if app in self.frontends_cache: |
318 log.debug(_(u"Trying to register twice frontends parameters for %(app)s: aborted" % {"app": app})) | 341 log.debug( |
342 _( | |
343 u"Trying to register twice frontends parameters for %(app)s: aborted" | |
344 % {"app": app} | |
345 ) | |
346 ) | |
319 return | 347 return |
320 self.frontends_cache.append(app) | 348 self.frontends_cache.append(app) |
321 self.updateParams(xml, security_limit, app) | 349 self.updateParams(xml, security_limit, app) |
322 log.debug(u"Frontends parameters registered for %(app)s" % {'app': app}) | 350 log.debug(u"Frontends parameters registered for %(app)s" % {"app": app}) |
323 | 351 |
324 def __default_ok(self, value, name, category): | 352 def __default_ok(self, value, name, category): |
325 #FIXME: will not work with individual parameters | 353 # FIXME: will not work with individual parameters |
326 self.setParam(name, value, category) | 354 self.setParam(name, value, category) |
327 | 355 |
328 def __default_ko(self, failure, name, category): | 356 def __default_ko(self, failure, name, category): |
329 log.error(_(u"Can't determine default value for [%(category)s/%(name)s]: %(reason)s") % {'category': category, 'name': name, 'reason': str(failure.value)}) | 357 log.error( |
358 _(u"Can't determine default value for [%(category)s/%(name)s]: %(reason)s") | |
359 % {"category": category, "name": name, "reason": str(failure.value)} | |
360 ) | |
330 | 361 |
331 def setDefault(self, name, category, callback, errback=None): | 362 def setDefault(self, name, category, callback, errback=None): |
332 """Set default value of parameter | 363 """Set default value of parameter |
333 | 364 |
334 'default_cb' attibute of parameter must be set to 'yes' | 365 'default_cb' attibute of parameter must be set to 'yes' |
335 @param name: name of the parameter | 366 @param name: name of the parameter |
336 @param category: category of the parameter | 367 @param category: category of the parameter |
337 @param callback: must return a string with the value (use deferred if needed) | 368 @param callback: must return a string with the value (use deferred if needed) |
338 @param errback: must manage the error with args failure, name, category | 369 @param errback: must manage the error with args failure, name, category |
339 """ | 370 """ |
340 #TODO: send signal param update if value changed | 371 # TODO: send signal param update if value changed |
341 #TODO: manage individual paramaters | 372 # TODO: manage individual paramaters |
342 log.debug ("setDefault called for %(category)s/%(name)s" % {"category": category, "name": name}) | 373 log.debug( |
343 node = self._getParamNode(name, category, '@ALL@') | 374 "setDefault called for %(category)s/%(name)s" |
375 % {"category": category, "name": name} | |
376 ) | |
377 node = self._getParamNode(name, category, "@ALL@") | |
344 if not node: | 378 if not node: |
345 log.error(_(u"Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name': name, 'category': category}) | 379 log.error( |
380 _( | |
381 u"Requested param [%(name)s] in category [%(category)s] doesn't exist !" | |
382 ) | |
383 % {"name": name, "category": category} | |
384 ) | |
346 return | 385 return |
347 if node[1].getAttribute('default_cb') == 'yes': | 386 if node[1].getAttribute("default_cb") == "yes": |
348 # del node[1].attributes['default_cb'] # default_cb is not used anymore as a flag to know if we have to set the default value, | 387 # del node[1].attributes['default_cb'] # default_cb is not used anymore as a flag to know if we have to set the default value, |
349 # and we can still use it later e.g. to call a generic setDefault method | 388 # and we can still use it later e.g. to call a generic setDefault method |
350 value = self._getParam(category, name, C.GENERAL) | 389 value = self._getParam(category, name, C.GENERAL) |
351 if value is None: # no value set by the user: we have the default value | 390 if value is None: # no value set by the user: we have the default value |
352 log.debug ("Default value to set, using callback") | 391 log.debug("Default value to set, using callback") |
353 d = defer.maybeDeferred(callback) | 392 d = defer.maybeDeferred(callback) |
354 d.addCallback(self.__default_ok, name, category) | 393 d.addCallback(self.__default_ok, name, category) |
355 d.addErrback(errback or self.__default_ko, name, category) | 394 d.addErrback(errback or self.__default_ko, name, category) |
356 | 395 |
357 def _getAttr_internal(self, node, attr, value): | 396 def _getAttr_internal(self, node, attr, value): |
362 @param node: XML param node | 401 @param node: XML param node |
363 @param attr: name of the attribute to get (e.g.: 'value' or 'type') | 402 @param attr: name of the attribute to get (e.g.: 'value' or 'type') |
364 @param value: user defined value | 403 @param value: user defined value |
365 @return: value (can be str, bool, int, list, None) | 404 @return: value (can be str, bool, int, list, None) |
366 """ | 405 """ |
367 if attr == 'value': | 406 if attr == "value": |
368 value_to_use = value if value is not None else node.getAttribute(attr) # we use value (user defined) if it exist, else we use node's default value | 407 value_to_use = ( |
369 if node.getAttribute('type') == 'bool': | 408 value if value is not None else node.getAttribute(attr) |
409 ) # we use value (user defined) if it exist, else we use node's default value | |
410 if node.getAttribute("type") == "bool": | |
370 return C.bool(value_to_use) | 411 return C.bool(value_to_use) |
371 if node.getAttribute('type') == 'int': | 412 if node.getAttribute("type") == "int": |
372 return int(value_to_use) | 413 return int(value_to_use) |
373 elif node.getAttribute('type') == 'list': | 414 elif node.getAttribute("type") == "list": |
374 if not value_to_use: # no user defined value, take default value from the XML | 415 if ( |
375 options = [option for option in node.childNodes if option.nodeName == 'option'] | 416 not value_to_use |
376 selected = [option for option in options if option.getAttribute('selected') == 'true'] | 417 ): # no user defined value, take default value from the XML |
377 cat, param = node.parentNode.getAttribute('name'), node.getAttribute('name') | 418 options = [ |
419 option | |
420 for option in node.childNodes | |
421 if option.nodeName == "option" | |
422 ] | |
423 selected = [ | |
424 option | |
425 for option in options | |
426 if option.getAttribute("selected") == "true" | |
427 ] | |
428 cat, param = ( | |
429 node.parentNode.getAttribute("name"), | |
430 node.getAttribute("name"), | |
431 ) | |
378 if len(selected) == 1: | 432 if len(selected) == 1: |
379 value_to_use = selected[0].getAttribute('value') | 433 value_to_use = selected[0].getAttribute("value") |
380 log.info(_("Unset parameter (%(cat)s, %(param)s) of type list will use the default option '%(value)s'") % | 434 log.info( |
381 {'cat': cat, 'param': param, 'value': value_to_use}) | 435 _( |
436 "Unset parameter (%(cat)s, %(param)s) of type list will use the default option '%(value)s'" | |
437 ) | |
438 % {"cat": cat, "param": param, "value": value_to_use} | |
439 ) | |
382 return value_to_use | 440 return value_to_use |
383 if len(selected) == 0: | 441 if len(selected) == 0: |
384 log.error(_(u'Parameter (%(cat)s, %(param)s) of type list has no default option!') % {'cat': cat, 'param': param}) | 442 log.error( |
443 _( | |
444 u"Parameter (%(cat)s, %(param)s) of type list has no default option!" | |
445 ) | |
446 % {"cat": cat, "param": param} | |
447 ) | |
385 else: | 448 else: |
386 log.error(_(u'Parameter (%(cat)s, %(param)s) of type list has more than one default option!') % {'cat': cat, 'param': param}) | 449 log.error( |
450 _( | |
451 u"Parameter (%(cat)s, %(param)s) of type list has more than one default option!" | |
452 ) | |
453 % {"cat": cat, "param": param} | |
454 ) | |
387 raise exceptions.DataError | 455 raise exceptions.DataError |
388 elif node.getAttribute('type') == 'jids_list': | 456 elif node.getAttribute("type") == "jids_list": |
389 if value_to_use: | 457 if value_to_use: |
390 jids = value_to_use.split('\t') # FIXME: it's not good to use tabs as separator ! | 458 jids = value_to_use.split( |
459 "\t" | |
460 ) # FIXME: it's not good to use tabs as separator ! | |
391 else: # no user defined value, take default value from the XML | 461 else: # no user defined value, take default value from the XML |
392 jids = [getText(jid_) for jid_ in node.getElementsByTagName("jid")] | 462 jids = [getText(jid_) for jid_ in node.getElementsByTagName("jid")] |
393 to_delete = [] | 463 to_delete = [] |
394 for idx, value in enumerate(jids): | 464 for idx, value in enumerate(jids): |
395 try: | 465 try: |
396 jids[idx] = jid.JID(value) | 466 jids[idx] = jid.JID(value) |
397 except (RuntimeError, jid.InvalidFormat, AttributeError): | 467 except (RuntimeError, jid.InvalidFormat, AttributeError): |
398 log.warning(u"Incorrect jid value found in jids list: [{}]".format(value)) | 468 log.warning( |
469 u"Incorrect jid value found in jids list: [{}]".format(value) | |
470 ) | |
399 to_delete.append(value) | 471 to_delete.append(value) |
400 for value in to_delete: | 472 for value in to_delete: |
401 jids.remove(value) | 473 jids.remove(value) |
402 return jids | 474 return jids |
403 return value_to_use | 475 return value_to_use |
410 @param node: XML param node | 482 @param node: XML param node |
411 @param attr: name of the attribute to get (e.g.: 'value' or 'type') | 483 @param attr: name of the attribute to get (e.g.: 'value' or 'type') |
412 @param value: user defined value | 484 @param value: user defined value |
413 @return (unicode, bool, int, list): value to retrieve | 485 @return (unicode, bool, int, list): value to retrieve |
414 """ | 486 """ |
415 if attr == 'value' and node.getAttribute('type') == 'password': | 487 if attr == "value" and node.getAttribute("type") == "password": |
416 raise exceptions.InternalError('To retrieve password values, use _asyncGetAttr instead of _getAttr') | 488 raise exceptions.InternalError( |
489 "To retrieve password values, use _asyncGetAttr instead of _getAttr" | |
490 ) | |
417 return self._getAttr_internal(node, attr, value) | 491 return self._getAttr_internal(node, attr, value) |
418 | 492 |
419 def _asyncGetAttr(self, node, attr, value, profile=None): | 493 def _asyncGetAttr(self, node, attr, value, profile=None): |
420 """Get attribute value. | 494 """Get attribute value. |
421 | 495 |
426 @param value: user defined value | 500 @param value: user defined value |
427 @param profile: %(doc_profile)s | 501 @param profile: %(doc_profile)s |
428 @return (unicode, bool, int, list): Deferred value to retrieve | 502 @return (unicode, bool, int, list): Deferred value to retrieve |
429 """ | 503 """ |
430 value = self._getAttr_internal(node, attr, value) | 504 value = self._getAttr_internal(node, attr, value) |
431 if attr != 'value' or node.getAttribute('type') != 'password': | 505 if attr != "value" or node.getAttribute("type") != "password": |
432 return defer.succeed(value) | 506 return defer.succeed(value) |
433 param_cat = node.parentNode.getAttribute('name') | 507 param_cat = node.parentNode.getAttribute("name") |
434 param_name = node.getAttribute('name') | 508 param_name = node.getAttribute("name") |
435 if ((param_cat, param_name) == C.PROFILE_PASS_PATH) or not value: | 509 if ((param_cat, param_name) == C.PROFILE_PASS_PATH) or not value: |
436 return defer.succeed(value) # profile password and empty passwords are returned "as is" | 510 return defer.succeed( |
511 value | |
512 ) # profile password and empty passwords are returned "as is" | |
437 if not profile: | 513 if not profile: |
438 raise exceptions.ProfileNotSetError('The profile is needed to decrypt a password') | 514 raise exceptions.ProfileNotSetError( |
515 "The profile is needed to decrypt a password" | |
516 ) | |
439 d = self.host.memory.decryptValue(value, profile) | 517 d = self.host.memory.decryptValue(value, profile) |
440 | 518 |
441 def gotPlainPassword(password): | 519 def gotPlainPassword(password): |
442 if password is None: # empty value means empty password, None means decryption failure | 520 if ( |
443 raise exceptions.InternalError(_('The stored password could not be decrypted!')) | 521 password is None |
522 ): # empty value means empty password, None means decryption failure | |
523 raise exceptions.InternalError( | |
524 _("The stored password could not be decrypted!") | |
525 ) | |
444 return password | 526 return password |
445 | 527 |
446 return d.addCallback(gotPlainPassword) | 528 return d.addCallback(gotPlainPassword) |
447 | 529 |
448 def __type_to_string(self, result): | 530 def __type_to_string(self, result): |
453 return str(result) | 535 return str(result) |
454 return result | 536 return result |
455 | 537 |
456 def getStringParamA(self, name, category, attr="value", profile_key=C.PROF_KEY_NONE): | 538 def getStringParamA(self, name, category, attr="value", profile_key=C.PROF_KEY_NONE): |
457 """ Same as getParamA but for bridge: convert non string value to string """ | 539 """ Same as getParamA but for bridge: convert non string value to string """ |
458 return self.__type_to_string(self.getParamA(name, category, attr, profile_key=profile_key)) | 540 return self.__type_to_string( |
459 | 541 self.getParamA(name, category, attr, profile_key=profile_key) |
460 def getParamA(self, name, category, attr="value", use_default=True, profile_key=C.PROF_KEY_NONE): | 542 ) |
543 | |
544 def getParamA( | |
545 self, name, category, attr="value", use_default=True, profile_key=C.PROF_KEY_NONE | |
546 ): | |
461 """Helper method to get a specific attribute. | 547 """Helper method to get a specific attribute. |
462 | 548 |
463 /!\ This method would return encrypted password values, | 549 /!\ This method would return encrypted password values, |
464 to get the plain values you have to use _asyncGetParamA. | 550 to get the plain values you have to use _asyncGetParamA. |
465 @param name: name of the parameter | 551 @param name: name of the parameter |
472 """ | 558 """ |
473 # FIXME: looks really dirty and buggy, need to be reviewed/refactored | 559 # FIXME: looks really dirty and buggy, need to be reviewed/refactored |
474 # FIXME: security_limit is not managed here ! | 560 # FIXME: security_limit is not managed here ! |
475 node = self._getParamNode(name, category) | 561 node = self._getParamNode(name, category) |
476 if not node: | 562 if not node: |
477 log.error(_(u"Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name': name, 'category': category}) | 563 log.error( |
564 _( | |
565 u"Requested param [%(name)s] in category [%(category)s] doesn't exist !" | |
566 ) | |
567 % {"name": name, "category": category} | |
568 ) | |
478 raise exceptions.NotFound | 569 raise exceptions.NotFound |
479 | 570 |
480 if attr == 'value' and node[1].getAttribute('type') == 'password': | 571 if attr == "value" and node[1].getAttribute("type") == "password": |
481 raise exceptions.InternalError('To retrieve password values, use asyncGetParamA instead of getParamA') | 572 raise exceptions.InternalError( |
573 "To retrieve password values, use asyncGetParamA instead of getParamA" | |
574 ) | |
482 | 575 |
483 if node[0] == C.GENERAL: | 576 if node[0] == C.GENERAL: |
484 value = self._getParam(category, name, C.GENERAL) | 577 value = self._getParam(category, name, C.GENERAL) |
485 if value is None and attr=='value' and not use_default: | 578 if value is None and attr == "value" and not use_default: |
486 return value | 579 return value |
487 return self._getAttr(node[1], attr, value) | 580 return self._getAttr(node[1], attr, value) |
488 | 581 |
489 assert node[0] == C.INDIVIDUAL | 582 assert node[0] == C.INDIVIDUAL |
490 | 583 |
491 profile = self.getProfileName(profile_key) | 584 profile = self.getProfileName(profile_key) |
492 if not profile: | 585 if not profile: |
493 log.error(_('Requesting a param for an non-existant profile')) | 586 log.error(_("Requesting a param for an non-existant profile")) |
494 raise exceptions.ProfileUnknownError(profile_key) | 587 raise exceptions.ProfileUnknownError(profile_key) |
495 | 588 |
496 if profile not in self.params: | 589 if profile not in self.params: |
497 log.error(_('Requesting synchronous param for not connected profile')) | 590 log.error(_("Requesting synchronous param for not connected profile")) |
498 raise exceptions.ProfileNotConnected(profile) | 591 raise exceptions.ProfileNotConnected(profile) |
499 | 592 |
500 if attr == "value": | 593 if attr == "value": |
501 value = self._getParam(category, name, profile=profile) | 594 value = self._getParam(category, name, profile=profile) |
502 if value is None and attr=='value' and not use_default: | 595 if value is None and attr == "value" and not use_default: |
503 return value | 596 return value |
504 return self._getAttr(node[1], attr, value) | 597 return self._getAttr(node[1], attr, value) |
505 | 598 |
506 def asyncGetStringParamA(self, name, category, attr="value", security_limit=C.NO_SECURITY_LIMIT, profile_key=C.PROF_KEY_NONE): | 599 def asyncGetStringParamA( |
600 self, | |
601 name, | |
602 category, | |
603 attr="value", | |
604 security_limit=C.NO_SECURITY_LIMIT, | |
605 profile_key=C.PROF_KEY_NONE, | |
606 ): | |
507 d = self.asyncGetParamA(name, category, attr, security_limit, profile_key) | 607 d = self.asyncGetParamA(name, category, attr, security_limit, profile_key) |
508 d.addCallback(self.__type_to_string) | 608 d.addCallback(self.__type_to_string) |
509 return d | 609 return d |
510 | 610 |
511 def asyncGetParamA(self, name, category, attr="value", security_limit=C.NO_SECURITY_LIMIT, profile_key=C.PROF_KEY_NONE): | 611 def asyncGetParamA( |
612 self, | |
613 name, | |
614 category, | |
615 attr="value", | |
616 security_limit=C.NO_SECURITY_LIMIT, | |
617 profile_key=C.PROF_KEY_NONE, | |
618 ): | |
512 """Helper method to get a specific attribute. | 619 """Helper method to get a specific attribute. |
513 | 620 |
514 @param name: name of the parameter | 621 @param name: name of the parameter |
515 @param category: category of the parameter | 622 @param category: category of the parameter |
516 @param attr: name of the attribute (default: "value") | 623 @param attr: name of the attribute (default: "value") |
517 @param profile: owner of the param (@ALL@ for everyone) | 624 @param profile: owner of the param (@ALL@ for everyone) |
518 @return (defer.Deferred): parameter value, with corresponding type (bool, int, list, etc) | 625 @return (defer.Deferred): parameter value, with corresponding type (bool, int, list, etc) |
519 """ | 626 """ |
520 node = self._getParamNode(name, category) | 627 node = self._getParamNode(name, category) |
521 if not node: | 628 if not node: |
522 log.error(_(u"Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name': name, 'category': category}) | 629 log.error( |
630 _( | |
631 u"Requested param [%(name)s] in category [%(category)s] doesn't exist !" | |
632 ) | |
633 % {"name": name, "category": category} | |
634 ) | |
523 raise ValueError("Requested param doesn't exist") | 635 raise ValueError("Requested param doesn't exist") |
524 | 636 |
525 if not self.checkSecurityLimit(node[1], security_limit): | 637 if not self.checkSecurityLimit(node[1], security_limit): |
526 log.warning(_(u"Trying to get parameter '%(param)s' in category '%(cat)s' without authorization!!!" | 638 log.warning( |
527 % {'param': name, 'cat': category})) | 639 _( |
640 u"Trying to get parameter '%(param)s' in category '%(cat)s' without authorization!!!" | |
641 % {"param": name, "cat": category} | |
642 ) | |
643 ) | |
528 raise exceptions.PermissionError | 644 raise exceptions.PermissionError |
529 | 645 |
530 if node[0] == C.GENERAL: | 646 if node[0] == C.GENERAL: |
531 value = self._getParam(category, name, C.GENERAL) | 647 value = self._getParam(category, name, C.GENERAL) |
532 return self._asyncGetAttr(node[1], attr, value) | 648 return self._asyncGetAttr(node[1], attr, value) |
533 | 649 |
534 assert node[0] == C.INDIVIDUAL | 650 assert node[0] == C.INDIVIDUAL |
535 | 651 |
536 profile = self.getProfileName(profile_key) | 652 profile = self.getProfileName(profile_key) |
537 if not profile: | 653 if not profile: |
538 raise exceptions.InternalError(_('Requesting a param for a non-existant profile')) | 654 raise exceptions.InternalError( |
655 _("Requesting a param for a non-existant profile") | |
656 ) | |
539 | 657 |
540 if attr != "value": | 658 if attr != "value": |
541 return defer.succeed(node[1].getAttribute(attr)) | 659 return defer.succeed(node[1].getAttribute(attr)) |
542 try: | 660 try: |
543 value = self._getParam(category, name, profile=profile) | 661 value = self._getParam(category, name, profile=profile) |
544 return self._asyncGetAttr(node[1], attr, value, profile) | 662 return self._asyncGetAttr(node[1], attr, value, profile) |
545 except exceptions.ProfileNotInCacheError: | 663 except exceptions.ProfileNotInCacheError: |
546 #We have to ask data to the storage manager | 664 # We have to ask data to the storage manager |
547 d = self.storage.getIndParam(category, name, profile) | 665 d = self.storage.getIndParam(category, name, profile) |
548 return d.addCallback(lambda value: self._asyncGetAttr(node[1], attr, value, profile)) | 666 return d.addCallback( |
667 lambda value: self._asyncGetAttr(node[1], attr, value, profile) | |
668 ) | |
549 | 669 |
550 def asyncGetParamsValuesFromCategory(self, category, security_limit, profile_key): | 670 def asyncGetParamsValuesFromCategory(self, category, security_limit, profile_key): |
551 """Get all parameters "attribute" for a category | 671 """Get all parameters "attribute" for a category |
552 | 672 |
553 @param category(unicode): the desired category | 673 @param category(unicode): the desired category |
555 Otherwise sole the params which have a security level defined *and* | 675 Otherwise sole the params which have a security level defined *and* |
556 lower or equal to the specified value are returned. | 676 lower or equal to the specified value are returned. |
557 @param profile_key: %(doc_profile_key)s | 677 @param profile_key: %(doc_profile_key)s |
558 @return (dict): key: param name, value: param value (converted to string if needed) | 678 @return (dict): key: param name, value: param value (converted to string if needed) |
559 """ | 679 """ |
560 #TODO: manage category of general type (without existant profile) | 680 # TODO: manage category of general type (without existant profile) |
561 profile = self.getProfileName(profile_key) | 681 profile = self.getProfileName(profile_key) |
562 if not profile: | 682 if not profile: |
563 log.error(_("Asking params for inexistant profile")) | 683 log.error(_("Asking params for inexistant profile")) |
564 return "" | 684 return "" |
565 | 685 |
570 ret = {} | 690 ret = {} |
571 names_d_list = [] | 691 names_d_list = [] |
572 for category_node in prof_xml.getElementsByTagName("category"): | 692 for category_node in prof_xml.getElementsByTagName("category"): |
573 if category_node.getAttribute("name") == category: | 693 if category_node.getAttribute("name") == category: |
574 for param_node in category_node.getElementsByTagName("param"): | 694 for param_node in category_node.getElementsByTagName("param"): |
575 name = param_node.getAttribute('name') | 695 name = param_node.getAttribute("name") |
576 if not name: | 696 if not name: |
577 log.warning(u"ignoring attribute without name: {}".format(param_node.toxml())) | 697 log.warning( |
698 u"ignoring attribute without name: {}".format( | |
699 param_node.toxml() | |
700 ) | |
701 ) | |
578 continue | 702 continue |
579 d = self.asyncGetStringParamA(name, category, security_limit=security_limit, profile_key=profile) | 703 d = self.asyncGetStringParamA( |
704 name, | |
705 category, | |
706 security_limit=security_limit, | |
707 profile_key=profile, | |
708 ) | |
580 d.addCallback(setValue, ret, name) | 709 d.addCallback(setValue, ret, name) |
581 names_d_list.append(d) | 710 names_d_list.append(d) |
582 break | 711 break |
583 | 712 |
584 prof_xml.unlink() | 713 prof_xml.unlink() |
585 dlist = defer.gatherResults(names_d_list) | 714 dlist = defer.gatherResults(names_d_list) |
586 dlist.addCallback(lambda dummy: ret) | 715 dlist.addCallback(lambda dummy: ret) |
587 return ret | 716 return ret |
588 | 717 |
589 d = self._constructProfileXml(security_limit, '', profile) | 718 d = self._constructProfileXml(security_limit, "", profile) |
590 return d.addCallback(returnCategoryXml) | 719 return d.addCallback(returnCategoryXml) |
591 | 720 |
592 def _getParam(self, category, name, type_=C.INDIVIDUAL, cache=None, profile=C.PROF_KEY_NONE): | 721 def _getParam( |
722 self, category, name, type_=C.INDIVIDUAL, cache=None, profile=C.PROF_KEY_NONE | |
723 ): | |
593 """Return the param, or None if it doesn't exist | 724 """Return the param, or None if it doesn't exist |
594 | 725 |
595 @param category: param category | 726 @param category: param category |
596 @param name: param name | 727 @param name: param name |
597 @param type_: GENERAL or INDIVIDUAL | 728 @param type_: GENERAL or INDIVIDUAL |
606 assert type_ == C.INDIVIDUAL | 737 assert type_ == C.INDIVIDUAL |
607 if profile == C.PROF_KEY_NONE: | 738 if profile == C.PROF_KEY_NONE: |
608 raise exceptions.ProfileNotSetError | 739 raise exceptions.ProfileNotSetError |
609 if profile in self.params: | 740 if profile in self.params: |
610 cache = self.params[profile] # if profile is in main cache, we use it, | 741 cache = self.params[profile] # if profile is in main cache, we use it, |
611 # ignoring the temporary cache | 742 # ignoring the temporary cache |
612 elif cache is None: # else we use the temporary cache if it exists, or raise an exception | 743 elif ( |
744 cache is None | |
745 ): # else we use the temporary cache if it exists, or raise an exception | |
613 raise exceptions.ProfileNotInCacheError | 746 raise exceptions.ProfileNotInCacheError |
614 if (category, name) not in cache: | 747 if (category, name) not in cache: |
615 return None | 748 return None |
616 return cache[(category, name)] | 749 return cache[(category, name)] |
617 | 750 |
627 @return: a deferred that fire a minidom.Document of the profile xml (cf warning above) | 760 @return: a deferred that fire a minidom.Document of the profile xml (cf warning above) |
628 """ | 761 """ |
629 | 762 |
630 def checkNode(node): | 763 def checkNode(node): |
631 """Check the node against security_limit and app""" | 764 """Check the node against security_limit and app""" |
632 return self.checkSecurityLimit(node, security_limit) and self.checkApp(node, app) | 765 return self.checkSecurityLimit(node, security_limit) and self.checkApp( |
766 node, app | |
767 ) | |
633 | 768 |
634 def constructProfile(ignore, profile_cache): | 769 def constructProfile(ignore, profile_cache): |
635 # init the result document | 770 # init the result document |
636 prof_xml = minidom.parseString('<params/>') | 771 prof_xml = minidom.parseString("<params/>") |
637 cache = {} | 772 cache = {} |
638 | 773 |
639 for type_node in self.dom.documentElement.childNodes: | 774 for type_node in self.dom.documentElement.childNodes: |
640 if type_node.nodeName != C.GENERAL and type_node.nodeName != C.INDIVIDUAL: | 775 if type_node.nodeName != C.GENERAL and type_node.nodeName != C.INDIVIDUAL: |
641 continue | 776 continue |
642 # we use all params, general and individual | 777 # we use all params, general and individual |
643 for cat_node in type_node.childNodes: | 778 for cat_node in type_node.childNodes: |
644 if cat_node.nodeName != 'category': | 779 if cat_node.nodeName != "category": |
645 continue | 780 continue |
646 category = cat_node.getAttribute('name') | 781 category = cat_node.getAttribute("name") |
647 dest_params = {} # result (merged) params for category | 782 dest_params = {} # result (merged) params for category |
648 if category not in cache: | 783 if category not in cache: |
649 # we make a copy for the new xml | 784 # we make a copy for the new xml |
650 cache[category] = dest_cat = cat_node.cloneNode(True) | 785 cache[category] = dest_cat = cat_node.cloneNode(True) |
651 to_remove = [] | 786 to_remove = [] |
653 if node.nodeName != "param": | 788 if node.nodeName != "param": |
654 continue | 789 continue |
655 if not checkNode(node): | 790 if not checkNode(node): |
656 to_remove.append(node) | 791 to_remove.append(node) |
657 continue | 792 continue |
658 dest_params[node.getAttribute('name')] = node | 793 dest_params[node.getAttribute("name")] = node |
659 for node in to_remove: | 794 for node in to_remove: |
660 dest_cat.removeChild(node) | 795 dest_cat.removeChild(node) |
661 new_node = True | 796 new_node = True |
662 else: | 797 else: |
663 # It's not a new node, we use the previously cloned one | 798 # It's not a new node, we use the previously cloned one |
666 params = cat_node.getElementsByTagName("param") | 801 params = cat_node.getElementsByTagName("param") |
667 | 802 |
668 for param_node in params: | 803 for param_node in params: |
669 # we have to merge new params (we are parsing individual parameters, we have to add them | 804 # we have to merge new params (we are parsing individual parameters, we have to add them |
670 # to the previously parsed general ones) | 805 # to the previously parsed general ones) |
671 name = param_node.getAttribute('name') | 806 name = param_node.getAttribute("name") |
672 if not checkNode(param_node): | 807 if not checkNode(param_node): |
673 continue | 808 continue |
674 if name not in dest_params: | 809 if name not in dest_params: |
675 # this is reached when a previous category exists | 810 # this is reached when a previous category exists |
676 dest_params[name] = param_node.cloneNode(True) | 811 dest_params[name] = param_node.cloneNode(True) |
677 dest_cat.appendChild(dest_params[name]) | 812 dest_cat.appendChild(dest_params[name]) |
678 | 813 |
679 profile_value = self._getParam(category, | 814 profile_value = self._getParam( |
680 name, type_node.nodeName, | 815 category, |
681 cache=profile_cache, profile=profile) | 816 name, |
817 type_node.nodeName, | |
818 cache=profile_cache, | |
819 profile=profile, | |
820 ) | |
682 if profile_value is not None: | 821 if profile_value is not None: |
683 # there is a value for this profile, we must change the default | 822 # there is a value for this profile, we must change the default |
684 if dest_params[name].getAttribute('type') == 'list': | 823 if dest_params[name].getAttribute("type") == "list": |
685 for option in dest_params[name].getElementsByTagName("option"): | 824 for option in dest_params[name].getElementsByTagName( |
686 if option.getAttribute('value') == profile_value: | 825 "option" |
687 option.setAttribute('selected', 'true') | 826 ): |
827 if option.getAttribute("value") == profile_value: | |
828 option.setAttribute("selected", "true") | |
688 else: | 829 else: |
689 try: | 830 try: |
690 option.removeAttribute('selected') | 831 option.removeAttribute("selected") |
691 except NotFoundErr: | 832 except NotFoundErr: |
692 pass | 833 pass |
693 elif dest_params[name].getAttribute('type') == 'jids_list': | 834 elif dest_params[name].getAttribute("type") == "jids_list": |
694 jids = profile_value.split('\t') | 835 jids = profile_value.split("\t") |
695 for jid_elt in dest_params[name].getElementsByTagName("jid"): | 836 for jid_elt in dest_params[name].getElementsByTagName( |
696 dest_params[name].removeChild(jid_elt) # remove all default | 837 "jid" |
838 ): | |
839 dest_params[name].removeChild( | |
840 jid_elt | |
841 ) # remove all default | |
697 for jid_ in jids: # rebuilt the children with use values | 842 for jid_ in jids: # rebuilt the children with use values |
698 try: | 843 try: |
699 jid.JID(jid_) | 844 jid.JID(jid_) |
700 except (RuntimeError, jid.InvalidFormat, AttributeError): | 845 except ( |
701 log.warning(u"Incorrect jid value found in jids list: [{}]".format(jid_)) | 846 RuntimeError, |
847 jid.InvalidFormat, | |
848 AttributeError, | |
849 ): | |
850 log.warning( | |
851 u"Incorrect jid value found in jids list: [{}]".format( | |
852 jid_ | |
853 ) | |
854 ) | |
702 else: | 855 else: |
703 jid_elt = prof_xml.createElement('jid') | 856 jid_elt = prof_xml.createElement("jid") |
704 jid_elt.appendChild(prof_xml.createTextNode(jid_)) | 857 jid_elt.appendChild(prof_xml.createTextNode(jid_)) |
705 dest_params[name].appendChild(jid_elt) | 858 dest_params[name].appendChild(jid_elt) |
706 else: | 859 else: |
707 dest_params[name].setAttribute('value', profile_value) | 860 dest_params[name].setAttribute("value", profile_value) |
708 if new_node: | 861 if new_node: |
709 prof_xml.documentElement.appendChild(dest_cat) | 862 prof_xml.documentElement.appendChild(dest_cat) |
710 | 863 |
711 to_remove = [] | 864 to_remove = [] |
712 for cat_node in prof_xml.documentElement.childNodes: | 865 for cat_node in prof_xml.documentElement.childNodes: |
719 | 872 |
720 if profile in self.params: | 873 if profile in self.params: |
721 d = defer.succeed(None) | 874 d = defer.succeed(None) |
722 profile_cache = self.params[profile] | 875 profile_cache = self.params[profile] |
723 else: | 876 else: |
724 #profile is not in cache, we load values in a short time cache | 877 # profile is not in cache, we load values in a short time cache |
725 profile_cache = {} | 878 profile_cache = {} |
726 d = self.loadIndParams(profile, profile_cache) | 879 d = self.loadIndParams(profile, profile_cache) |
727 | 880 |
728 return d.addCallback(constructProfile, profile_cache) | 881 return d.addCallback(constructProfile, profile_cache) |
729 | 882 |
759 return defer.succeed("") | 912 return defer.succeed("") |
760 | 913 |
761 def returnXML(prof_xml): | 914 def returnXML(prof_xml): |
762 return_xml = prof_xml.toxml() | 915 return_xml = prof_xml.toxml() |
763 prof_xml.unlink() | 916 prof_xml.unlink() |
764 return '\n'.join((line for line in return_xml.split('\n') if line)) | 917 return "\n".join((line for line in return_xml.split("\n") if line)) |
765 | 918 |
766 return self._constructProfileXml(security_limit, app, profile).addCallback(returnXML) | 919 return self._constructProfileXml(security_limit, app, profile).addCallback( |
920 returnXML | |
921 ) | |
767 | 922 |
768 def _getParamNode(self, name, category, type_="@ALL@"): # FIXME: is type_ useful ? | 923 def _getParamNode(self, name, category, type_="@ALL@"): # FIXME: is type_ useful ? |
769 """Return a node from the param_xml | 924 """Return a node from the param_xml |
770 @param name: name of the node | 925 @param name: name of the node |
771 @param category: category of the node | 926 @param category: category of the node |
774 @GENERAL@ only search in general type | 929 @GENERAL@ only search in general type |
775 @INDIVIDUAL@ only search in individual type | 930 @INDIVIDUAL@ only search in individual type |
776 @return: a tuple (node type, node) or None if not found""" | 931 @return: a tuple (node type, node) or None if not found""" |
777 | 932 |
778 for type_node in self.dom.documentElement.childNodes: | 933 for type_node in self.dom.documentElement.childNodes: |
779 if (((type_ == "@ALL@" or type_ == "@GENERAL@") and type_node.nodeName == C.GENERAL) | 934 if ( |
780 or ((type_ == "@ALL@" or type_ == "@INDIVIDUAL@") and type_node.nodeName == C.INDIVIDUAL)): | 935 (type_ == "@ALL@" or type_ == "@GENERAL@") |
781 for node in type_node.getElementsByTagName('category'): | 936 and type_node.nodeName == C.GENERAL |
937 ) or ( | |
938 (type_ == "@ALL@" or type_ == "@INDIVIDUAL@") | |
939 and type_node.nodeName == C.INDIVIDUAL | |
940 ): | |
941 for node in type_node.getElementsByTagName("category"): | |
782 if node.getAttribute("name") == category: | 942 if node.getAttribute("name") == category: |
783 params = node.getElementsByTagName("param") | 943 params = node.getElementsByTagName("param") |
784 for param in params: | 944 for param in params: |
785 if param.getAttribute("name") == name: | 945 if param.getAttribute("name") == name: |
786 return (type_node.nodeName, param) | 946 return (type_node.nodeName, param) |
793 name = cat.getAttribute("name") | 953 name = cat.getAttribute("name") |
794 if name not in categories: | 954 if name not in categories: |
795 categories.append(cat.getAttribute("name")) | 955 categories.append(cat.getAttribute("name")) |
796 return categories | 956 return categories |
797 | 957 |
798 def setParam(self, name, value, category, security_limit=C.NO_SECURITY_LIMIT, profile_key=C.PROF_KEY_NONE): | 958 def setParam( |
959 self, | |
960 name, | |
961 value, | |
962 category, | |
963 security_limit=C.NO_SECURITY_LIMIT, | |
964 profile_key=C.PROF_KEY_NONE, | |
965 ): | |
799 """Set a parameter, return None if the parameter is not in param xml. | 966 """Set a parameter, return None if the parameter is not in param xml. |
800 | 967 |
801 Parameter of type 'password' that are not the SàT profile password are | 968 Parameter of type 'password' that are not the SàT profile password are |
802 stored encrypted (if not empty). The profile password is stored hashed | 969 stored encrypted (if not empty). The profile password is stored hashed |
803 (if not empty). | 970 (if not empty). |
811 """ | 978 """ |
812 # FIXME: setParam should accept the right type for value, not only str ! | 979 # FIXME: setParam should accept the right type for value, not only str ! |
813 if profile_key != C.PROF_KEY_NONE: | 980 if profile_key != C.PROF_KEY_NONE: |
814 profile = self.getProfileName(profile_key) | 981 profile = self.getProfileName(profile_key) |
815 if not profile: | 982 if not profile: |
816 log.error(_(u'Trying to set parameter for an unknown profile')) | 983 log.error(_(u"Trying to set parameter for an unknown profile")) |
817 raise exceptions.ProfileUnknownError(profile_key) | 984 raise exceptions.ProfileUnknownError(profile_key) |
818 | 985 |
819 node = self._getParamNode(name, category, '@ALL@') | 986 node = self._getParamNode(name, category, "@ALL@") |
820 if not node: | 987 if not node: |
821 log.error(_(u'Requesting an unknown parameter (%(category)s/%(name)s)') | 988 log.error( |
822 % {'category': category, 'name': name}) | 989 _(u"Requesting an unknown parameter (%(category)s/%(name)s)") |
990 % {"category": category, "name": name} | |
991 ) | |
823 return defer.succeed(None) | 992 return defer.succeed(None) |
824 | 993 |
825 if not self.checkSecurityLimit(node[1], security_limit): | 994 if not self.checkSecurityLimit(node[1], security_limit): |
826 log.warning(_(u"Trying to set parameter '%(param)s' in category '%(cat)s' without authorization!!!" | 995 log.warning( |
827 % {'param': name, 'cat': category})) | 996 _( |
997 u"Trying to set parameter '%(param)s' in category '%(cat)s' without authorization!!!" | |
998 % {"param": name, "cat": category} | |
999 ) | |
1000 ) | |
828 return defer.succeed(None) | 1001 return defer.succeed(None) |
829 | 1002 |
830 type_ = node[1].getAttribute("type") | 1003 type_ = node[1].getAttribute("type") |
831 if type_ == 'int': | 1004 if type_ == "int": |
832 if not value: # replace with the default value (which might also be '') | 1005 if not value: # replace with the default value (which might also be '') |
833 value = node[1].getAttribute("value") | 1006 value = node[1].getAttribute("value") |
834 else: | 1007 else: |
835 try: | 1008 try: |
836 int(value) | 1009 int(value) |
837 except ValueError: | 1010 except ValueError: |
838 log.debug(_(u"Trying to set parameter '%(param)s' in category '%(cat)s' with an non-integer value" | 1011 log.debug( |
839 % {'param': name, 'cat': category})) | 1012 _( |
1013 u"Trying to set parameter '%(param)s' in category '%(cat)s' with an non-integer value" | |
1014 % {"param": name, "cat": category} | |
1015 ) | |
1016 ) | |
840 return defer.succeed(None) | 1017 return defer.succeed(None) |
841 if node[1].hasAttribute("constraint"): | 1018 if node[1].hasAttribute("constraint"): |
842 constraint = node[1].getAttribute("constraint") | 1019 constraint = node[1].getAttribute("constraint") |
843 try: | 1020 try: |
844 min_, max_ = [int(limit) for limit in constraint.split(";")] | 1021 min_, max_ = [int(limit) for limit in constraint.split(";")] |
845 except ValueError: | 1022 except ValueError: |
846 raise exceptions.InternalError("Invalid integer parameter constraint: %s" % constraint) | 1023 raise exceptions.InternalError( |
1024 "Invalid integer parameter constraint: %s" % constraint | |
1025 ) | |
847 value = str(min(max(int(value), min_), max_)) | 1026 value = str(min(max(int(value), min_), max_)) |
848 | 1027 |
849 | 1028 log.info( |
850 log.info(_("Setting parameter (%(category)s, %(name)s) = %(value)s") % | 1029 _("Setting parameter (%(category)s, %(name)s) = %(value)s") |
851 {'category': category, 'name': name, 'value': value if type_ != 'password' else '********'}) | 1030 % { |
1031 "category": category, | |
1032 "name": name, | |
1033 "value": value if type_ != "password" else "********", | |
1034 } | |
1035 ) | |
852 | 1036 |
853 if node[0] == C.GENERAL: | 1037 if node[0] == C.GENERAL: |
854 self.params_gen[(category, name)] = value | 1038 self.params_gen[(category, name)] = value |
855 self.storage.setGenParam(category, name, value) | 1039 self.storage.setGenParam(category, name, value) |
856 for profile in self.storage.getProfilesList(): | 1040 for profile in self.storage.getProfilesList(): |
857 if self.host.memory.isSessionStarted(profile): | 1041 if self.host.memory.isSessionStarted(profile): |
858 self.host.bridge.paramUpdate(name, value, category, profile) | 1042 self.host.bridge.paramUpdate(name, value, category, profile) |
859 self.host.trigger.point("paramUpdateTrigger", name, value, category, node[0], profile) | 1043 self.host.trigger.point( |
1044 "paramUpdateTrigger", name, value, category, node[0], profile | |
1045 ) | |
860 return defer.succeed(None) | 1046 return defer.succeed(None) |
861 | 1047 |
862 assert node[0] == C.INDIVIDUAL | 1048 assert node[0] == C.INDIVIDUAL |
863 assert profile_key != C.PROF_KEY_NONE | 1049 assert profile_key != C.PROF_KEY_NONE |
864 | 1050 |
865 if type_ == "button": | 1051 if type_ == "button": |
866 log.debug(u"Clicked param button %s" % node.toxml()) | 1052 log.debug(u"Clicked param button %s" % node.toxml()) |
867 return defer.succeed(None) | 1053 return defer.succeed(None) |
868 elif type_ == "password": | 1054 elif type_ == "password": |
869 try: | 1055 try: |
870 personal_key = self.host.memory.auth_sessions.profileGetUnique(profile)[C.MEMORY_CRYPTO_KEY] | 1056 personal_key = self.host.memory.auth_sessions.profileGetUnique(profile)[ |
1057 C.MEMORY_CRYPTO_KEY | |
1058 ] | |
871 except TypeError: | 1059 except TypeError: |
872 raise exceptions.InternalError(_('Trying to encrypt a password while the personal key is undefined!')) | 1060 raise exceptions.InternalError( |
1061 _("Trying to encrypt a password while the personal key is undefined!") | |
1062 ) | |
873 if (category, name) == C.PROFILE_PASS_PATH: | 1063 if (category, name) == C.PROFILE_PASS_PATH: |
874 # using 'value' as the encryption key to encrypt another encryption key... could be confusing! | 1064 # using 'value' as the encryption key to encrypt another encryption key... could be confusing! |
875 d = self.host.memory.encryptPersonalData(data_key=C.MEMORY_CRYPTO_KEY, | 1065 d = self.host.memory.encryptPersonalData( |
876 data_value=personal_key, | 1066 data_key=C.MEMORY_CRYPTO_KEY, |
877 crypto_key=value, | 1067 data_value=personal_key, |
878 profile=profile) | 1068 crypto_key=value, |
879 d.addCallback(lambda dummy: PasswordHasher.hash(value)) # profile password is hashed (empty value stays empty) | 1069 profile=profile, |
1070 ) | |
1071 d.addCallback( | |
1072 lambda dummy: PasswordHasher.hash(value) | |
1073 ) # profile password is hashed (empty value stays empty) | |
880 elif value: # other non empty passwords are encrypted with the personal key | 1074 elif value: # other non empty passwords are encrypted with the personal key |
881 d = BlockCipher.encrypt(personal_key, value) | 1075 d = BlockCipher.encrypt(personal_key, value) |
882 else: | 1076 else: |
883 d = defer.succeed(value) | 1077 d = defer.succeed(value) |
884 else: | 1078 else: |
886 | 1080 |
887 def gotFinalValue(value): | 1081 def gotFinalValue(value): |
888 if self.host.memory.isSessionStarted(profile): | 1082 if self.host.memory.isSessionStarted(profile): |
889 self.params[profile][(category, name)] = value | 1083 self.params[profile][(category, name)] = value |
890 self.host.bridge.paramUpdate(name, value, category, profile) | 1084 self.host.bridge.paramUpdate(name, value, category, profile) |
891 self.host.trigger.point("paramUpdateTrigger", name, value, category, node[0], profile) | 1085 self.host.trigger.point( |
1086 "paramUpdateTrigger", name, value, category, node[0], profile | |
1087 ) | |
892 return self.storage.setIndParam(category, name, value, profile) | 1088 return self.storage.setIndParam(category, name, value, profile) |
893 else: | 1089 else: |
894 raise exceptions.ProfileNotConnected | 1090 raise exceptions.ProfileNotConnected |
895 | 1091 |
896 d.addCallback(gotFinalValue) | 1092 d.addCallback(gotFinalValue) |
910 - key is a couple (attribute category, attribute name) | 1106 - key is a couple (attribute category, attribute name) |
911 - value is a node | 1107 - value is a node |
912 """ | 1108 """ |
913 ret = {} | 1109 ret = {} |
914 for type_node in self.dom.documentElement.childNodes: | 1110 for type_node in self.dom.documentElement.childNodes: |
915 if (((node_type == "@ALL@" or node_type == "@GENERAL@") and type_node.nodeName == C.GENERAL) or | 1111 if ( |
916 ((node_type == "@ALL@" or node_type == "@INDIVIDUAL@") and type_node.nodeName == C.INDIVIDUAL)): | 1112 (node_type == "@ALL@" or node_type == "@GENERAL@") |
917 for cat_node in type_node.getElementsByTagName('category'): | 1113 and type_node.nodeName == C.GENERAL |
918 cat = cat_node.getAttribute('name') | 1114 ) or ( |
1115 (node_type == "@ALL@" or node_type == "@INDIVIDUAL@") | |
1116 and type_node.nodeName == C.INDIVIDUAL | |
1117 ): | |
1118 for cat_node in type_node.getElementsByTagName("category"): | |
1119 cat = cat_node.getAttribute("name") | |
919 params = cat_node.getElementsByTagName("param") | 1120 params = cat_node.getElementsByTagName("param") |
920 for param in params: | 1121 for param in params: |
921 if param.getAttribute("type") == attr_type: | 1122 if param.getAttribute("type") == attr_type: |
922 ret[(cat, param.getAttribute("name"))] = param | 1123 ret[(cat, param.getAttribute("name"))] = param |
923 return ret | 1124 return ret |