Mercurial > libervia-backend
comparison src/memory/memory.py @ 1591:0df9c6247474
core: profile session starting and connection are now separated. Moved profile session starting/authentication to memory module
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 14 Nov 2015 19:18:10 +0100 |
parents | 698d6755d62a |
children | a3d0cfa5b7a6 |
comparison
equal
deleted
inserted
replaced
1590:ab54af2a9ab2 | 1591:0df9c6247474 |
---|---|
35 from sat.memory.sqlite import SqliteStorage | 35 from sat.memory.sqlite import SqliteStorage |
36 from sat.memory.persistent import PersistentDict | 36 from sat.memory.persistent import PersistentDict |
37 from sat.memory.params import Params | 37 from sat.memory.params import Params |
38 from sat.memory.disco import Discovery | 38 from sat.memory.disco import Discovery |
39 from sat.memory.crypto import BlockCipher | 39 from sat.memory.crypto import BlockCipher |
40 from sat.memory.crypto import PasswordHasher | |
40 from sat.tools import config as tools_config | 41 from sat.tools import config as tools_config |
41 | 42 |
42 | 43 |
43 PresenceTuple = namedtuple("PresenceTuple", ('show', 'priority', 'statuses')) | 44 PresenceTuple = namedtuple("PresenceTuple", ('show', 'priority', 'statuses')) |
44 MSG_NO_SESSION = "Session id doesn't exist or is finished" | 45 MSG_NO_SESSION = "Session id doesn't exist or is finished" |
314 @param profile: %(doc_profile)s""" | 315 @param profile: %(doc_profile)s""" |
315 return self.params.loadIndParams(profile) | 316 return self.params.loadIndParams(profile) |
316 | 317 |
317 ## Profiles/Sessions management ## | 318 ## Profiles/Sessions management ## |
318 | 319 |
319 def startProfileSession(self, profile): | 320 def _startSession(self, password, profile_key): |
321 profile = self.getProfileName(profile_key) | |
322 return self.startSession(password, profile) | |
323 | |
324 def startSession(self, password, profile): | |
320 """"Iniatialise session for a profile | 325 """"Iniatialise session for a profile |
321 @param profile: %(doc_profile)s""" | 326 |
322 log.info(_("[%s] Profile session started" % profile)) | 327 @param password(unicode): profile session password |
323 self._entities_cache[profile] = {} | 328 or empty string is no password is set |
329 @param profile: %(doc_profile)s | |
330 """ | |
331 def createSession(dummy): | |
332 """Called once params are loaded.""" | |
333 self._entities_cache[profile] = {} | |
334 log.info(u"[{}] Profile session started".format(profile)) | |
335 return False | |
336 | |
337 def backendInitialised(dummy): | |
338 def doStartSession(dummy=None): | |
339 if self.isSessionStarted(profile): | |
340 log.info("Session already started!") | |
341 return True | |
342 try: | |
343 # if there is a value at this point in self._entities_cache, | |
344 # it is the loadIndividualParams Deferred, the session is starting | |
345 session_d = self._entities_cache[profile] | |
346 except KeyError: | |
347 # else we do request the params | |
348 session_d = self._entities_cache[profile] = self.loadIndividualParams(profile) | |
349 session_d.addCallback(createSession) | |
350 finally: | |
351 return session_d | |
352 | |
353 auth_d = self.profileAuthenticate(password, profile) | |
354 auth_d.addCallback(doStartSession) | |
355 return auth_d | |
356 | |
357 return self.host.initialised.addCallback(backendInitialised) | |
358 | |
359 def _isSessionStarted(self, profile_key): | |
360 return self.isSessionStarted(self.getProfileName(profile_key)) | |
361 | |
362 def isSessionStarted(self, profile): | |
363 try: | |
364 # XXX: if the value in self._entities_cache is a Deferred, | |
365 # the session is starting but not started yet | |
366 return not isinstance(self._entities_cache[profile], defer.Deferred) | |
367 except KeyError: | |
368 return False | |
369 | |
370 def profileAuthenticate(self, password, profile): | |
371 """Authenticate the profile. | |
372 | |
373 @param password (unicode): the SàT profile password | |
374 @param profile: %(doc_profile)s | |
375 @return (D): a deferred None in case of success, a failure otherwise. | |
376 """ | |
377 session_data = self.auth_sessions.profileGetUnique(profile) | |
378 if not password and session_data: | |
379 # XXX: this allows any frontend to connect with the empty password as soon as | |
380 # the profile has been authenticated at least once before. It is OK as long as | |
381 # submitting a form with empty passwords is restricted to local frontends. | |
382 return defer.succeed(None) | |
383 | |
384 def check_result(result): | |
385 if not result: | |
386 log.warning(u'Authentication failure of profile {}'.format(profile)) | |
387 raise exceptions.PasswordError(u"The provided profile password doesn't match.") | |
388 if not session_data: # avoid to create two profile sessions when password if specified | |
389 return self.newAuthSession(password, profile) | |
390 | |
391 d = self.asyncGetParamA(C.PROFILE_PASS_PATH[1], C.PROFILE_PASS_PATH[0], profile_key=profile) | |
392 d.addCallback(lambda sat_cipher: PasswordHasher.verify(password, sat_cipher)) | |
393 return d.addCallback(check_result) | |
324 | 394 |
325 def newAuthSession(self, key, profile): | 395 def newAuthSession(self, key, profile): |
326 """Start a new session for the authenticated profile. | 396 """Start a new session for the authenticated profile. |
327 | 397 |
328 The personal key is loaded encrypted from a PersistentDict before being decrypted. | 398 The personal key is loaded encrypted from a PersistentDict before being decrypted. |