From e7f77052f0aba1b84febf0ab1382c9602bbf7f93 Mon Sep 17 00:00:00 2001 From: NavaL Date: Wed, 3 Feb 2016 17:23:42 +0100 Subject: closing the services closes leap session, which stops background tasks, close soldedad and remove it from cache Issue #586 --- service/pixelated/application.py | 7 ++-- service/pixelated/assets/index.html | 9 +++++ service/pixelated/bitmask_libraries/session.py | 51 +++++++++++++++++--------- service/pixelated/config/services.py | 10 ++--- service/pixelated/resources/__init__.py | 2 +- service/pixelated/resources/auth.py | 11 +++--- service/pixelated/resources/login_resource.py | 4 +- service/pixelated/resources/logout_resource.py | 2 + 8 files changed, 61 insertions(+), 35 deletions(-) create mode 100644 service/pixelated/assets/index.html (limited to 'service/pixelated') diff --git a/service/pixelated/application.py b/service/pixelated/application.py index dafab0b1..b0f2d3fc 100644 --- a/service/pixelated/application.py +++ b/service/pixelated/application.py @@ -53,8 +53,8 @@ class ServicesFactory(object): def log_out_user(self, user_id): if self.is_logged_in(user_id): - services = self._services_by_user[user_id] - services.close() + _services = self._services_by_user[user_id] + _services.close() del self._services_by_user[user_id] def add_session(self, user_id, services): @@ -64,7 +64,6 @@ class ServicesFactory(object): def create_services_from(self, leap_session): _services = services.Services(leap_session) yield _services.setup() - self._services_by_user[leap_session.user_auth.uuid] = _services @@ -176,7 +175,7 @@ def _start_in_multi_user_mode(args, root_resource, services_factory): def set_up_protected_resources(root_resource, provider, services_factory, checker=None): if not checker: checker = LeapPasswordChecker(provider) - session_checker = SessionChecker() + session_checker = SessionChecker(services_factory) anonymous_resource = LoginResource(services_factory) realm = PixelatedRealm(root_resource, anonymous_resource) diff --git a/service/pixelated/assets/index.html b/service/pixelated/assets/index.html new file mode 100644 index 00000000..c095577e --- /dev/null +++ b/service/pixelated/assets/index.html @@ -0,0 +1,9 @@ + + + + + + click here + + + diff --git a/service/pixelated/bitmask_libraries/session.py b/service/pixelated/bitmask_libraries/session.py index 4276c0c3..8b9118ce 100644 --- a/service/pixelated/bitmask_libraries/session.py +++ b/service/pixelated/bitmask_libraries/session.py @@ -39,7 +39,7 @@ from leap.common.events import ( log = logging.getLogger(__name__) -SESSIONS = {} +SESSIONS = {} # TODO replace with redis or memCached in prod class LeapSession(object): @@ -90,6 +90,12 @@ class LeapSession(object): def close(self): self.stop_background_jobs() unregister(events.KEYMANAGER_FINISHED_KEY_GENERATION, uid=self.account_email()) + self.soledad.close() + self.remove_from_cache() + + def remove_from_cache(self): + key = SessionCache.session_key(self.provider, self.user_auth.username) + SessionCache.remove_session(key) @defer.inlineCallbacks def _create_incoming_mail_fetcher(self, nicknym, soledad, account, user_mail): @@ -148,11 +154,11 @@ class LeapSessionFactory(object): self._config = provider.config def create(self, username, password, auth=None): - key = self._session_key(username) - session = self._lookup_session(key) + key = SessionCache.session_key(self._provider, username) + session = SessionCache.lookup_session(key) if not session: session = self._create_new_session(username, password, auth) - self._remember_session(key, session) + SessionCache.remember_session(key, session) return session @@ -201,20 +207,6 @@ class LeapSessionFactory(object): self._provider.domain, "keys", "client", "smtp.pem") - def _lookup_session(self, key): - global SESSIONS - if key in SESSIONS: - return SESSIONS[key] - else: - return None - - def _remember_session(self, key, session): - global SESSIONS - SESSIONS[key] = session - - def _session_key(self, username): - return hash((self._provider, username)) - def _create_dir(self, path): try: os.makedirs(path) @@ -244,3 +236,26 @@ class LeapSessionFactory(object): pass else: raise + + +class SessionCache(object): # should be replaced with redis or memcached in prod + + @staticmethod + def lookup_session(key): + global SESSIONS + return SESSIONS.get(key, None) + + @staticmethod + def remember_session(key, session): + global SESSIONS + SESSIONS[key] = session + + @staticmethod + def remove_session(key): + global SESSIONS + if key in SESSIONS: + del SESSIONS[key] + + @staticmethod + def session_key(provider, username): + return hash((provider, username)) diff --git a/service/pixelated/config/services.py b/service/pixelated/config/services.py index 3f254571..de0e2537 100644 --- a/service/pixelated/config/services.py +++ b/service/pixelated/config/services.py @@ -25,16 +25,13 @@ class Services(object): @defer.inlineCallbacks def setup(self): search_index_storage_key = self._setup_search_index_storage_key(self._leap_session.soledad) - yield self._setup_search_engine( - self._leap_session.user_auth.uuid, - search_index_storage_key) + yield self._setup_search_engine(self._leap_session.user_auth.uuid, search_index_storage_key) self._wrap_mail_store_with_indexing_mail_store(self._leap_session) yield listen_all_mailboxes(self._leap_session.account, self.search_engine, self._leap_session.mail_store) - self.mail_service = self._setup_mail_service( - self.search_engine) + self.mail_service = self._setup_mail_service(self.search_engine) self.keymanager = self._leap_session.nicknym self.draft_service = self._setup_draft_service(self._leap_session.mail_store) @@ -42,6 +39,9 @@ class Services(object): yield self._index_all_mails() + def close(self): + self._leap_session.close() + def _wrap_mail_store_with_indexing_mail_store(self, leap_session): leap_session.mail_store = SearchableMailStore(leap_session.mail_store, self.search_engine) diff --git a/service/pixelated/resources/__init__.py b/service/pixelated/resources/__init__.py index 2e451a69..14ecac86 100644 --- a/service/pixelated/resources/__init__.py +++ b/service/pixelated/resources/__init__.py @@ -63,7 +63,7 @@ class BaseResource(Resource): def is_logged_in(self, request): session = self.get_session(request) - return session.is_logged_in() + return session.is_logged_in() and self._services_factory.is_logged_in(session.user_uuid) def get_session(self, request): return IPixelatedSession(request.getSession()) diff --git a/service/pixelated/resources/auth.py b/service/pixelated/resources/auth.py index 92efaa27..e2e7ec97 100644 --- a/service/pixelated/resources/auth.py +++ b/service/pixelated/resources/auth.py @@ -78,12 +78,14 @@ class SessionCredential(object): class SessionChecker(object): credentialInterfaces = (ISessionCredential,) + def __init__(self, services_factory): + self._services_factory = services_factory + def requestAvatarId(self, credentials): session = self.get_session(credentials.request) - if session.is_logged_in(): - return defer.succeed(session.user_uuid) - else: - return defer.succeed(ANONYMOUS) + if session.is_logged_in() and self._services_factory.is_logged_in(session.user_uuid): + return defer.succeed(session.user_uuid) + return defer.succeed(ANONYMOUS) def get_session(self, request): return IPixelatedSession(request.getSession()) @@ -131,7 +133,6 @@ class PixelatedAuthSessionWrapper(object): def _loginSucceeded(self, args): interface, avatar, logout = args - if avatar == checkers.ANONYMOUS: return self._anonymous_resource else: diff --git a/service/pixelated/resources/login_resource.py b/service/pixelated/resources/login_resource.py index ca8f0b11..1e1beb48 100644 --- a/service/pixelated/resources/login_resource.py +++ b/service/pixelated/resources/login_resource.py @@ -99,11 +99,11 @@ class LoginResource(BaseResource): if self.is_logged_in(request): return util.redirectTo("/", request) - def render_response(leap_user): + def render_response(leap_session): request.setResponseCode(OK) request.write(open(os.path.join(self._startup_folder, 'Interstitial.html')).read()) request.finish() - self._setup_user_services(leap_user, request) + self._setup_user_services(leap_session, request) def render_error(error): log.info('Login Error for %s' % request.args['username'][0]) diff --git a/service/pixelated/resources/logout_resource.py b/service/pixelated/resources/logout_resource.py index 9fd16451..fe80316e 100644 --- a/service/pixelated/resources/logout_resource.py +++ b/service/pixelated/resources/logout_resource.py @@ -10,5 +10,7 @@ class LogoutResource(BaseResource): def render_GET(self, request): session = self.get_session(request) + self._services_factory.log_out_user(session.user_uuid) session.expire() + return util.redirectTo("/%s" % LoginResource.BASE_URL, request) -- cgit v1.2.3