Mercurial > libervia-backend
diff 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 |
line wrap: on
line diff
--- a/src/memory/memory.py Sat Nov 14 19:18:10 2015 +0100 +++ b/src/memory/memory.py Sat Nov 14 19:18:10 2015 +0100 @@ -37,6 +37,7 @@ from sat.memory.params import Params from sat.memory.disco import Discovery from sat.memory.crypto import BlockCipher +from sat.memory.crypto import PasswordHasher from sat.tools import config as tools_config @@ -316,11 +317,80 @@ ## Profiles/Sessions management ## - def startProfileSession(self, profile): + def _startSession(self, password, profile_key): + profile = self.getProfileName(profile_key) + return self.startSession(password, profile) + + def startSession(self, password, profile): """"Iniatialise session for a profile - @param profile: %(doc_profile)s""" - log.info(_("[%s] Profile session started" % profile)) - self._entities_cache[profile] = {} + + @param password(unicode): profile session password + or empty string is no password is set + @param profile: %(doc_profile)s + """ + def createSession(dummy): + """Called once params are loaded.""" + self._entities_cache[profile] = {} + log.info(u"[{}] Profile session started".format(profile)) + return False + + def backendInitialised(dummy): + def doStartSession(dummy=None): + if self.isSessionStarted(profile): + log.info("Session already started!") + return True + try: + # if there is a value at this point in self._entities_cache, + # it is the loadIndividualParams Deferred, the session is starting + session_d = self._entities_cache[profile] + except KeyError: + # else we do request the params + session_d = self._entities_cache[profile] = self.loadIndividualParams(profile) + session_d.addCallback(createSession) + finally: + return session_d + + auth_d = self.profileAuthenticate(password, profile) + auth_d.addCallback(doStartSession) + return auth_d + + return self.host.initialised.addCallback(backendInitialised) + + def _isSessionStarted(self, profile_key): + return self.isSessionStarted(self.getProfileName(profile_key)) + + def isSessionStarted(self, profile): + try: + # XXX: if the value in self._entities_cache is a Deferred, + # the session is starting but not started yet + return not isinstance(self._entities_cache[profile], defer.Deferred) + except KeyError: + return False + + def profileAuthenticate(self, password, profile): + """Authenticate the profile. + + @param password (unicode): the SàT profile password + @param profile: %(doc_profile)s + @return (D): a deferred None in case of success, a failure otherwise. + """ + session_data = self.auth_sessions.profileGetUnique(profile) + if not password and session_data: + # XXX: this allows any frontend to connect with the empty password as soon as + # the profile has been authenticated at least once before. It is OK as long as + # submitting a form with empty passwords is restricted to local frontends. + return defer.succeed(None) + + def check_result(result): + if not result: + log.warning(u'Authentication failure of profile {}'.format(profile)) + raise exceptions.PasswordError(u"The provided profile password doesn't match.") + if not session_data: # avoid to create two profile sessions when password if specified + return self.newAuthSession(password, profile) + + d = self.asyncGetParamA(C.PROFILE_PASS_PATH[1], C.PROFILE_PASS_PATH[0], profile_key=profile) + d.addCallback(lambda sat_cipher: PasswordHasher.verify(password, sat_cipher)) + return d.addCallback(check_result) def newAuthSession(self, key, profile): """Start a new session for the authenticated profile.