diff options
Diffstat (limited to 'service')
| -rw-r--r-- | service/pixelated/bitmask_libraries/session.py | 21 | ||||
| -rw-r--r-- | service/pixelated/config/leap.py | 31 | ||||
| -rw-r--r-- | service/pixelated/resources/auth.py | 1 | ||||
| -rw-r--r-- | service/test/unit/bitmask_libraries/test_session.py | 12 | ||||
| -rw-r--r-- | service/test/unit/config/test_leap.py | 38 | 
5 files changed, 89 insertions, 14 deletions
| diff --git a/service/pixelated/bitmask_libraries/session.py b/service/pixelated/bitmask_libraries/session.py index f28d9f59..5d8b13af 100644 --- a/service/pixelated/bitmask_libraries/session.py +++ b/service/pixelated/bitmask_libraries/session.py @@ -53,18 +53,19 @@ class LeapSession(object):          self.fresh_account = False          self.incoming_mail_fetcher = None          self.account = None -        self._has_been_synced = False +        self._has_been_initially_synced = False          self._sem_intial_sync = defer.DeferredLock() +        self._is_closed = False          register(events.KEYMANAGER_FINISHED_KEY_GENERATION, self._set_fresh_account, uid=self.account_email())      @defer.inlineCallbacks      def initial_sync(self):          yield self._sem_intial_sync.acquire()          try: -            if not self._has_been_synced: -                yield self.sync() +            yield self.sync() +            if not self._has_been_initially_synced:                  yield self.after_first_sync() -                self._has_been_synced = True +                self._has_been_initially_synced = True          finally:              yield self._sem_intial_sync.release()          defer.returnValue(self) @@ -94,12 +95,17 @@ class LeapSession(object):          return self.provider.address_for(name)      def close(self): +        self._is_closed = True          self.stop_background_jobs()          unregister(events.KEYMANAGER_FINISHED_KEY_GENERATION, uid=self.account_email())          self.soledad.close()          self.remove_from_cache()          self._close_account() +    @property +    def is_closed(self): +        return self._is_closed +      def _close_account(self):          if self.account:              self.account.end_session() @@ -284,7 +290,12 @@ class SessionCache(object):      @staticmethod      def lookup_session(key): -        return SessionCache.sessions.get(key, None) +        session = SessionCache.sessions.get(key, None) +        if session is not None and session.is_closed: +            SessionCache.remove_session(key) +            return None +        else: +            return session      @staticmethod      def remember_session(key, session): diff --git a/service/pixelated/config/leap.py b/service/pixelated/config/leap.py index a8666086..17a69406 100644 --- a/service/pixelated/config/leap.py +++ b/service/pixelated/config/leap.py @@ -1,14 +1,13 @@  from __future__ import absolute_import -from leap.common.events import (server as events_server, -                                register, catalog as events) +from leap.common.events import (server as events_server) +from leap.soledad.common.errors import InvalidAuthTokenError +  from pixelated.config import credentials  from pixelated.bitmask_libraries.config import LeapConfig  from pixelated.bitmask_libraries.certs import LeapCertificate  from pixelated.bitmask_libraries.provider import LeapProvider  from pixelated.bitmask_libraries.session import LeapSessionFactory  from twisted.internet import defer -import os -import logging  import logging  log = logging.getLogger(__name__) @@ -39,11 +38,29 @@ def initialize_leap_multi_user(provider_hostname,      defer.returnValue((config, provider)) +def _create_session(provider, username, password, auth): +    return LeapSessionFactory(provider).create(username, password, auth) + + +def _force_close_session(session): +    try: +        session.close() +    except Exception, e: +        log.error(e) + +  @defer.inlineCallbacks  def authenticate_user(provider, username, password, initial_sync=True, auth=None): -    leap_session = LeapSessionFactory(provider).create(username, password, auth) -    if initial_sync: -        yield leap_session.initial_sync() +    leap_session = _create_session(provider, username, password, auth) +    try: +        if initial_sync: +            yield leap_session.initial_sync() +    except InvalidAuthTokenError: +        _force_close_session(leap_session) + +        leap_session = _create_session(provider, username, password, auth) +        if initial_sync: +            yield leap_session.initial_sync()      defer.returnValue(leap_session) diff --git a/service/pixelated/resources/auth.py b/service/pixelated/resources/auth.py index 02729a01..a6ab5396 100644 --- a/service/pixelated/resources/auth.py +++ b/service/pixelated/resources/auth.py @@ -41,7 +41,6 @@ log = logging.getLogger(__name__)  class LeapPasswordChecker(object):      credentialInterfaces = (          credentials.IUsernamePassword, -        credentials.IUsernameHashedPassword      )      def __init__(self, leap_provider): diff --git a/service/test/unit/bitmask_libraries/test_session.py b/service/test/unit/bitmask_libraries/test_session.py index a41cb805..aad2cac2 100644 --- a/service/test/unit/bitmask_libraries/test_session.py +++ b/service/test/unit/bitmask_libraries/test_session.py @@ -133,6 +133,16 @@ class SessionTest(AbstractLeapTest):          self.assertTrue(session.fresh_account)      @patch('pixelated.bitmask_libraries.session.register') +    def test_closed_session_not_reused(self, _): +        session = self._create_session() +        SessionCache.remember_session('somekey', session) +        session._is_closed = True + +        result = SessionCache.lookup_session('somekey') + +        self.assertIsNone(result) + +    @patch('pixelated.bitmask_libraries.session.register')      def test_session_does_not_set_status_fresh_for_unkown_emails(self, _):          session = self._create_session()          self.provider.address_for.return_value = 'someone@somedomain.tld' @@ -150,7 +160,7 @@ class SessionTest(AbstractLeapTest):          with patch('pixelated.bitmask_libraries.session.reactor.callFromThread', new=_execute_func) as _:              with patch.object(LeapSession, '_create_incoming_mail_fetcher', return_value=mailFetcherMock) as _:                  session = self._create_session() -                session._has_been_synced = True +                session._has_been_initially_synced = True                  yield session.initial_sync()                  self.assertFalse(mailFetcherMock.startService.called) diff --git a/service/test/unit/config/test_leap.py b/service/test/unit/config/test_leap.py new file mode 100644 index 00000000..6b34d717 --- /dev/null +++ b/service/test/unit/config/test_leap.py @@ -0,0 +1,38 @@ +from leap.soledad.common.errors import InvalidAuthTokenError +from mock import MagicMock, patch +from twisted.trial import unittest +from twisted.internet import defer +from pixelated.config.leap import authenticate_user + + +class TestAuth(unittest.TestCase): + +    @patch('pixelated.config.leap.LeapSessionFactory') +    @defer.inlineCallbacks +    def test_authenticate_user_calls_initinal_sync(self, session_factory__ctor_mock): +        session_factory_mock = session_factory__ctor_mock.return_value +        provider_mock = MagicMock() +        auth_mock = MagicMock() +        session = MagicMock() + +        session_factory_mock.create.return_value = session + +        yield authenticate_user(provider_mock, 'username', 'password', auth=auth_mock) + +        session.initial_sync.assert_called_with() + +    @patch('pixelated.config.leap.LeapSessionFactory') +    @defer.inlineCallbacks +    def test_authenticate_user_calls_initial_sync_a_second_time_if_invalid_auth_exception_is_raised(self, session_factory__ctor_mock): +        session_factory_mock = session_factory__ctor_mock.return_value +        provider_mock = MagicMock() +        auth_mock = MagicMock() +        session = MagicMock() + +        session.initial_sync.side_effect = [InvalidAuthTokenError, defer.succeed(None)] +        session_factory_mock.create.return_value = session + +        yield authenticate_user(provider_mock, 'username', 'password', auth=auth_mock) + +        session.close.assert_called_with() +        self.assertEqual(2, session.initial_sync.call_count) | 
