diff options
23 files changed, 331 insertions, 454 deletions
diff --git a/service/pixelated/application.py b/service/pixelated/application.py index 65e974b6..178726ef 100644 --- a/service/pixelated/application.py +++ b/service/pixelated/application.py @@ -144,10 +144,9 @@ def _start_in_multi_user_mode(args, root_resource, services_factory): def _setup_multi_user(args, root_resource, services_factory): if args.provider is None: raise ValueError('Multi-user mode: provider name is required') - init_monkeypatches() events_server.ensure_server() - config, provider = initialize_leap_provider(args.provider, args.leap_provider_cert, args.leap_provider_cert_fingerprint, args.leap_home) + provider = initialize_leap_provider(args.provider, args.leap_provider_cert, args.leap_provider_cert_fingerprint, args.leap_home) protected_resource = set_up_protected_resources(root_resource, provider, services_factory, banner=args.banner) return protected_resource diff --git a/service/pixelated/bitmask_libraries/certs.py b/service/pixelated/bitmask_libraries/certs.py index 9d543672..e3466d05 100644 --- a/service/pixelated/bitmask_libraries/certs.py +++ b/service/pixelated/bitmask_libraries/certs.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see <http://www.gnu.org/licenses/>. import os +from pixelated.config import leap_config class LeapCertificate(object): @@ -22,7 +23,6 @@ class LeapCertificate(object): LEAP_FINGERPRINT = None def __init__(self, provider): - self._config = provider.config self._server_name = provider.server_name self._provider = provider @@ -41,10 +41,10 @@ class LeapCertificate(object): @property def provider_api_cert(self): - return str(os.path.join(self._provider.config.leap_home, 'providers', self._server_name, 'keys', 'client', 'api.pem')) + return str(os.path.join(leap_config.leap_home, 'providers', self._server_name, 'keys', 'client', 'api.pem')) def setup_ca_bundle(self): - path = os.path.join(self._provider.config.leap_home, 'providers', self._server_name, 'keys', 'client') + path = os.path.join(leap_config.leap_home, 'providers', self._server_name, 'keys', 'client') if not os.path.isdir(path): os.makedirs(path, 0700) self._download_cert(self.provider_api_cert) diff --git a/service/pixelated/bitmask_libraries/nicknym.py b/service/pixelated/bitmask_libraries/keymanager.py index aeedab2c..78d6e935 100644 --- a/service/pixelated/bitmask_libraries/nicknym.py +++ b/service/pixelated/bitmask_libraries/keymanager.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see <http://www.gnu.org/licenses/>. from leap.keymanager import KeyManager, KeyNotFound +from pixelated.config import leap_config from .certs import LeapCertificate from twisted.internet import defer import logging @@ -21,15 +22,15 @@ import logging logger = logging.getLogger(__name__) -class NickNym(object): - def __init__(self, provider, config, soledad, email_address, token, uuid): - nicknym_url = _discover_nicknym_server(provider) +class Keymanager(object): + def __init__(self, provider, soledad, email_address, token, uuid): + nicknym_url = provider._discover_nicknym_server() self._email = email_address self.keymanager = KeyManager(self._email, nicknym_url, soledad, token=token, ca_cert_path=LeapCertificate(provider).provider_api_cert, api_uri=provider.api_uri, api_version=provider.api_version, - uid=uuid, gpgbinary=config.gpg_binary) + uid=uuid, gpgbinary=leap_config.gpg_binary) @defer.inlineCallbacks def generate_openpgp_key(self): @@ -55,7 +56,3 @@ class NickNym(object): def _send_key_to_leap(self): return self.keymanager.send_key() - - -def _discover_nicknym_server(provider): - return 'https://nicknym.%s:6425/' % provider.domain diff --git a/service/pixelated/bitmask_libraries/provider.py b/service/pixelated/bitmask_libraries/provider.py index 9c889287..07791624 100644 --- a/service/pixelated/bitmask_libraries/provider.py +++ b/service/pixelated/bitmask_libraries/provider.py @@ -19,16 +19,18 @@ import os from leap.common.certs import get_digest import requests from .certs import LeapCertificate +from pixelated.config import leap_config from pixelated.support.tls_adapter import EnforceTLSv1Adapter -from pixelated.bitmask_libraries.soledad import SoledadDiscoverException + +REQUESTS_TIMEOUT = 15 class LeapProvider(object): - def __init__(self, server_name, config): + def __init__(self, server_name): self.server_name = server_name - self.config = config - self.local_ca_crt = '%s/ca.crt' % self.config.leap_home + self.local_ca_crt = '%s/ca.crt' % leap_config.leap_home self.provider_json = self.fetch_provider_json() + self.soledad_json = self.fetch_soledad_json() @property def api_uri(self): @@ -119,7 +121,7 @@ class LeapProvider(object): session = requests.session() try: session.mount('https://', EnforceTLSv1Adapter(assert_fingerprint=LeapCertificate.LEAP_FINGERPRINT)) - response = session.get(url, verify=LeapCertificate(self).provider_web_cert, timeout=self.config.timeout_in_s) + response = session.get(url, verify=LeapCertificate(self).provider_web_cert, timeout=REQUESTS_TIMEOUT) response.raise_for_status() return response finally: @@ -134,14 +136,14 @@ class LeapProvider(object): def fetch_soledad_json(self): service_url = "%s/%s/config/soledad-service.json" % ( self.api_uri, self.api_version) - response = requests.get(service_url, verify=LeapCertificate(self).provider_api_cert, timeout=self.config.timeout_in_s) + response = requests.get(service_url, verify=LeapCertificate(self).provider_api_cert, timeout=REQUESTS_TIMEOUT) response.raise_for_status() return json.loads(response.content) def fetch_smtp_json(self): service_url = '%s/%s/config/smtp-service.json' % ( self.api_uri, self.api_version) - response = requests.get(service_url, verify=LeapCertificate(self).provider_api_cert, timeout=self.config.timeout_in_s) + response = requests.get(service_url, verify=LeapCertificate(self).provider_api_cert, timeout=REQUESTS_TIMEOUT) response.raise_for_status() return json.loads(response.content) @@ -152,14 +154,11 @@ class LeapProvider(object): return '%s@%s' % (username, self.domain) def discover_soledad_server(self, user_uuid): - try: - json_data = self.fetch_soledad_json() - - hosts = json_data['hosts'] - host = hosts.keys()[0] - server_url = 'https://%s:%d/user-%s' % \ - (hosts[host]['hostname'], hosts[host]['port'], - user_uuid) - return server_url - except Exception, e: - raise SoledadDiscoverException(e) + hosts = self.soledad_json['hosts'] + host = hosts.keys()[0] + server_url = 'https://%s:%d/user-%s' % \ + (hosts[host]['hostname'], hosts[host]['port'], user_uuid) + return server_url + + def _discover_nicknym_server(self): + return 'https://nicknym.%s:6425/' % self.domain diff --git a/service/pixelated/bitmask_libraries/soledad.py b/service/pixelated/bitmask_libraries/soledad.py deleted file mode 100644 index 406e9fc1..00000000 --- a/service/pixelated/bitmask_libraries/soledad.py +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -from leap.soledad.client import Soledad -from leap.soledad.common.crypto import WrongMacError, UnknownMacMethodError - - -class SoledadDiscoverException(Exception): - def __init__(self, *args, **kwargs): - super(SoledadDiscoverException, self).__init__(*args, **kwargs) - - -class SoledadWrongPassphraseException(Exception): - def __init__(self, *args, **kwargs): - super(SoledadWrongPassphraseException, self).__init__(*args, **kwargs) - - -class SoledadFactory(object): - - @classmethod - def create(cls, user_token, user_uuid, encryption_passphrase, secrets, local_db, server_url, api_cert): - try: - return Soledad(user_uuid, - passphrase=unicode(encryption_passphrase), - secrets_path=secrets, - local_db_path=local_db, - server_url=server_url, - cert_file=api_cert, - shared_db=None, - auth_token=user_token, - defer_encryption=False) - - except (WrongMacError, UnknownMacMethodError), e: - raise SoledadWrongPassphraseException(e) diff --git a/service/pixelated/config/leap.py b/service/pixelated/config/leap.py index 9d0a35c4..b14aacc7 100644 --- a/service/pixelated/config/leap.py +++ b/service/pixelated/config/leap.py @@ -6,10 +6,10 @@ from leap.soledad.common.errors import InvalidAuthTokenError from leap.auth import SRPAuth from pixelated.config import credentials -from pixelated.bitmask_libraries.config import LeapConfig +from pixelated.config import leap_config from pixelated.bitmask_libraries.certs import LeapCertificate from pixelated.bitmask_libraries.provider import LeapProvider -from pixelated.bitmask_libraries.session import LeapSessionFactory +from pixelated.config.sessions import LeapSessionFactory log = logging.getLogger(__name__) @@ -17,13 +17,12 @@ log = logging.getLogger(__name__) def initialize_leap_provider(provider_hostname, provider_cert, provider_fingerprint, leap_home): LeapCertificate.set_cert_and_fingerprint(provider_cert, provider_fingerprint) - - config = LeapConfig(leap_home=leap_home, start_background_jobs=True) - provider = LeapProvider(provider_hostname, config) + leap_config.set_leap_home(leap_home) + provider = LeapProvider(provider_hostname) provider.download_certificate() LeapCertificate(provider).setup_ca_bundle() - return config, provider + return provider @defer.inlineCallbacks @@ -40,16 +39,16 @@ def initialize_leap_multi_user(provider_hostname, @defer.inlineCallbacks def create_leap_session(provider, username, password, auth=None): - leap_session = LeapSessionFactory(provider).create(username, password, auth) + leap_session = yield LeapSessionFactory(provider).create(username, password, auth) try: - yield leap_session.initial_sync() + yield leap_session.first_required_sync() except InvalidAuthTokenError: try: leap_session.close() except Exception, e: log.error(e) leap_session = LeapSessionFactory(provider).create(username, password, auth) - yield leap_session.initial_sync() + yield leap_session.first_required_sync() defer.returnValue(leap_session) diff --git a/service/pixelated/bitmask_libraries/config.py b/service/pixelated/config/leap_config.py index c521a093..324edc5e 100644 --- a/service/pixelated/bitmask_libraries/config.py +++ b/service/pixelated/config/leap_config.py @@ -30,17 +30,13 @@ def discover_gpg_binary(): SYSTEM_CA_BUNDLE = True +leap_home = '~/.leap/' +gpg_binary = discover_gpg_binary() -class LeapConfig(object): +def set_leap_home(new_home): + leap_home = new_home - def __init__(self, - leap_home=None, - timeout_in_s=15, - start_background_jobs=False, - gpg_binary=discover_gpg_binary()): - self.leap_home = leap_home - self.timeout_in_s = timeout_in_s - self.start_background_jobs = start_background_jobs - self.gpg_binary = gpg_binary +def set_gpg_binary(new_binary): + gpg_binary = binary diff --git a/service/pixelated/config/services.py b/service/pixelated/config/services.py index a49e1df9..494be703 100644 --- a/service/pixelated/config/services.py +++ b/service/pixelated/config/services.py @@ -12,14 +12,14 @@ from pixelated.adapter.listeners.mailbox_indexer_listener import listen_all_mail from twisted.internet import defer, reactor from pixelated.adapter.search.index_storage_key import SearchIndexStorageKey from pixelated.adapter.services.feedback_service import FeedbackService - +from pixelated.config import leap_config logger = logging.getLogger(__name__) class Services(object): def __init__(self, leap_session): - self._leap_home = leap_session.config.leap_home + self._leap_home = leap_config.leap_home self._leap_session = leap_session @defer.inlineCallbacks @@ -33,7 +33,7 @@ class Services(object): self.mail_service = self._setup_mail_service(self.search_engine) - self.keymanager = self._leap_session.nicknym + self.keymanager = self._leap_session.keymanager self.draft_service = self._setup_draft_service(self._leap_session.mail_store) self.feedback_service = self._setup_feedback_service() @@ -61,7 +61,7 @@ class Services(object): self.search_engine = search_engine def _setup_mail_service(self, search_engine): - pixelated_mail_sender = MailSender(self._leap_session.smtp_config, self._leap_session.nicknym.keymanager) + pixelated_mail_sender = MailSender(self._leap_session.smtp_config, self._leap_session.keymanager.keymanager) return MailService( pixelated_mail_sender, diff --git a/service/pixelated/bitmask_libraries/session.py b/service/pixelated/config/sessions.py index 72ad8520..ed492ea9 100644 --- a/service/pixelated/bitmask_libraries/session.py +++ b/service/pixelated/config/sessions.py @@ -1,81 +1,160 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -import errno -import traceback -import sys +from __future__ import absolute_import + import os +import errno import requests import logging - -from twisted.internet import reactor, defer -from pixelated.bitmask_libraries.certs import LeapCertificate -from pixelated.adapter.mailstore import LeapMailStore +from twisted.internet import defer, threads, reactor +from leap.soledad.common.crypto import WrongMacError, UnknownMacMethodError +from leap.soledad.client import Soledad +from pixelated.bitmask_libraries.keymanager import Keymanager from leap.mail.incoming.service import IncomingMail from leap.mail.mail import Account -from leap.auth import SRPAuth -from .nicknym import NickNym -from .smtp import LeapSMTPConfig -from .soledad import SoledadFactory import leap.common.certs as leap_certs - from leap.common.events import ( register, unregister, catalog as events ) +from pixelated.adapter.mailstore import LeapMailStore +from pixelated.config import leap_config +from pixelated.bitmask_libraries.certs import LeapCertificate +from pixelated.bitmask_libraries.smtp import LeapSMTPConfig + +logger = logging.getLogger(__name__) + + +class LeapSessionFactory(object): + def __init__(self, provider): + self._provider = provider + + @defer.inlineCallbacks + def create(self, username, password, auth): + key = SessionCache.session_key(self._provider, username) + session = SessionCache.lookup_session(key) + if not session: + session = yield self._create_new_session(username, password, auth) + SessionCache.remember_session(key, session) + defer.returnValue(session) + + @defer.inlineCallbacks + def _create_new_session(self, username, password, auth): + account_email = self._provider.address_for(username) + + self._create_database_dir(auth.uuid) + + api_cert = LeapCertificate(self._provider).provider_api_cert + + soledad = yield self.setup_soledad(auth.token, auth.uuid, password, api_cert) + + mail_store = LeapMailStore(soledad) + + keymanager = yield self.setup_keymanager(self._provider, soledad, account_email, auth.token, auth.uuid) + + smtp_client_cert = self._download_smtp_cert(auth) + smtp_host, smtp_port = self._provider.smtp_info() + smtp_config = LeapSMTPConfig(account_email, smtp_client_cert, smtp_host, smtp_port) + + leap_session = LeapSession(self._provider, auth, mail_store, soledad, keymanager, smtp_config) + + defer.returnValue(leap_session) + + @defer.inlineCallbacks + def setup_soledad(self, + user_token, + user_uuid, + password, + api_cert): + secrets = self._secrets_path(user_uuid) + local_db = self._local_db_path(user_uuid) + server_url = self._provider.discover_soledad_server(user_uuid) + try: + soledad = yield threads.deferToThread(Soledad, + user_uuid, + passphrase=unicode(password), + secrets_path=secrets, + local_db_path=local_db, + server_url=server_url, + cert_file=api_cert, + shared_db=None, + auth_token=user_token, + defer_encryption=False) + defer.returnValue(soledad) + except (WrongMacError, UnknownMacMethodError), e: + raise SoledadWrongPassphraseException(e) + + @defer.inlineCallbacks + def setup_keymanager(self, provider, soledad, account_email, token, uuid): + keymanager = yield threads.deferToThread(Keymanager, + provider, + soledad, + account_email, + token, + uuid) + defer.returnValue(keymanager) + + def _download_smtp_cert(self, auth): + cert = SmtpClientCertificate(self._provider, auth, self._user_path(auth.uuid)) + return cert.cert_path() + + def _create_dir(self, path): + try: + os.makedirs(path) + except OSError as exc: + if exc.errno == errno.EEXIST and os.path.isdir(path): + pass + else: + raise + + def _user_path(self, user_uuid): + return os.path.join(leap_config.leap_home, user_uuid) + + def _soledad_path(self, user_uuid): + return os.path.join(leap_config.leap_home, user_uuid, 'soledad') + + def _secrets_path(self, user_uuid): + return os.path.join(self._soledad_path(user_uuid), 'secrets') + + def _local_db_path(self, user_uuid): + return os.path.join(self._soledad_path(user_uuid), 'soledad.db') -log = logging.getLogger(__name__) + def _create_database_dir(self, user_uuid): + try: + os.makedirs(self._soledad_path(user_uuid)) + except OSError as exc: + if exc.errno == errno.EEXIST and os.path.isdir(self._soledad_path(user_uuid)): + pass + else: + raise class LeapSession(object): - def __init__(self, provider, user_auth, mail_store, soledad, nicknym, smtp_config): + def __init__(self, provider, user_auth, mail_store, soledad, keymanager, smtp_config): self.smtp_config = smtp_config - self.config = provider.config self.provider = provider self.user_auth = user_auth self.mail_store = mail_store self.soledad = soledad - self.nicknym = nicknym + self.keymanager = keymanager self.fresh_account = False self.incoming_mail_fetcher = None self.account = None 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: - yield self.sync() - if not self._has_been_initially_synced: - yield self.after_first_sync() - self._has_been_initially_synced = True - finally: - yield self._sem_intial_sync.release() - defer.returnValue(self) + def first_required_sync(self): + yield self.sync() + yield self.finish_bootstrap() @defer.inlineCallbacks - def after_first_sync(self): - yield self.nicknym.generate_openpgp_key() + def finish_bootstrap(self): + yield self.keymanager.generate_openpgp_key() yield self._create_account(self.soledad, self.user_auth.uuid) self.incoming_mail_fetcher = yield self._create_incoming_mail_fetcher( - self.nicknym, + self.keymanager, self.soledad, self.account, self.account_email()) @@ -86,7 +165,7 @@ class LeapSession(object): return self.account.deferred_initialization def _set_fresh_account(self, event, email_address): - log.debug('Key for email %s has been generated' % email_address) + logger.debug('Key for email %s has been generated' % email_address) if email_address == self.account_email(): self.fresh_account = True @@ -115,9 +194,9 @@ class LeapSession(object): SessionCache.remove_session(key) @defer.inlineCallbacks - def _create_incoming_mail_fetcher(self, nicknym, soledad, account, user_mail): + def _create_incoming_mail_fetcher(self, keymanager, soledad, account, user_mail): inbox = yield account.callWhenReady(lambda _: account.get_collection_by_mailbox('INBOX')) - defer.returnValue(IncomingMail(nicknym.keymanager, + defer.returnValue(IncomingMail(keymanager.keymanager, soledad, inbox, user_mail)) @@ -135,6 +214,33 @@ class LeapSession(object): raise +class SessionCache(object): + + sessions = {} + + @staticmethod + def lookup_session(key): + 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): + SessionCache.sessions[key] = session + + @staticmethod + def remove_session(key): + if key in SessionCache.sessions: + del SessionCache.sessions[key] + + @staticmethod + def session_key(provider, username): + return hash((provider, username)) + + class SmtpClientCertificate(object): def __init__(self, provider, auth, user_path): self._provider = provider @@ -159,7 +265,7 @@ class SmtpClientCertificate(object): if not os.path.exists(os.path.dirname(cert_path)): os.makedirs(os.path.dirname(cert_path)) - SmtpCertDownloader(self._provider, self._auth).download_to(cert_path) + self.download_to(cert_path) def _smtp_client_cert_path(self): return os.path.join( @@ -168,13 +274,6 @@ class SmtpClientCertificate(object): self._provider.domain, "keys", "client", "smtp.pem") - -class SmtpCertDownloader(object): - - def __init__(self, provider, auth): - self._provider = provider - self._auth = auth - def download(self): cert_url = '%s/%s/smtp_cert' % (self._provider.api_uri, self._provider.api_version) headers = {} @@ -185,7 +284,7 @@ class SmtpCertDownloader(object): params=params, data=params, verify=LeapCertificate(self._provider).provider_api_cert, - timeout=self._provider.config.timeout_in_s, + timeout=15, headers=headers) response.raise_for_status() @@ -200,102 +299,6 @@ class SmtpCertDownloader(object): f.write(client_cert) -class LeapSessionFactory(object): - def __init__(self, provider): - self._provider = provider - self._config = provider.config - - def create(self, username, password, auth): - key = SessionCache.session_key(self._provider, username) - session = SessionCache.lookup_session(key) - if not session: - session = self._create_new_session(username, password, auth) - SessionCache.remember_session(key, session) - - return session - - def _create_new_session(self, username, password, auth): - account_email = self._provider.address_for(username) - - self._create_database_dir(auth.uuid) - - soledad = SoledadFactory.create(auth.token, - auth.uuid, - password, - self._secrets_path(auth.uuid), - self._local_db_path(auth.uuid), - self._provider.discover_soledad_server(auth.uuid), - LeapCertificate(self._provider).provider_api_cert) - - mail_store = LeapMailStore(soledad) - nicknym = self._create_nicknym(account_email, auth.token, auth.uuid, soledad) - - smtp_client_cert = self._download_smtp_cert(auth) - smtp_host, smtp_port = self._provider.smtp_info() - smtp_config = LeapSMTPConfig(account_email, smtp_client_cert, smtp_host, smtp_port) - - return LeapSession(self._provider, auth, mail_store, soledad, nicknym, smtp_config) - - def _download_smtp_cert(self, auth): - cert = SmtpClientCertificate(self._provider, auth, self._user_path(auth.uuid)) - return cert.cert_path() - - def _create_dir(self, path): - try: - os.makedirs(path) - except OSError as exc: - if exc.errno == errno.EEXIST and os.path.isdir(path): - pass - else: - raise - - def _create_nicknym(self, email_address, token, uuid, soledad): - return NickNym(self._provider, self._config, soledad, email_address, token, uuid) - - def _user_path(self, user_uuid): - return os.path.join(self._config.leap_home, user_uuid) - - def _soledad_path(self, user_uuid): - return os.path.join(self._config.leap_home, user_uuid, 'soledad') - - def _secrets_path(self, user_uuid): - return os.path.join(self._soledad_path(user_uuid), 'secrets') - - def _local_db_path(self, user_uuid): - return os.path.join(self._soledad_path(user_uuid), 'soledad.db') - - def _create_database_dir(self, user_uuid): - try: - os.makedirs(self._soledad_path(user_uuid)) - except OSError as exc: - if exc.errno == errno.EEXIST and os.path.isdir(self._soledad_path(user_uuid)): - pass - else: - raise - - -class SessionCache(object): - - sessions = {} - - @staticmethod - def lookup_session(key): - 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): - SessionCache.sessions[key] = session - - @staticmethod - def remove_session(key): - if key in SessionCache.sessions: - del SessionCache.sessions[key] - - @staticmethod - def session_key(provider, username): - return hash((provider, username)) +class SoledadWrongPassphraseException(Exception): + def __init__(self, *args, **kwargs): + super(SoledadWrongPassphraseException, self).__init__(*args, **kwargs) diff --git a/service/pixelated/register.py b/service/pixelated/register.py index 2bdbb27b..93b55872 100644 --- a/service/pixelated/register.py +++ b/service/pixelated/register.py @@ -21,9 +21,8 @@ import sys from pixelated.config import arguments from pixelated.config import logger as logger_config from pixelated.bitmask_libraries.certs import LeapCertificate -from pixelated.bitmask_libraries.config import LeapConfig from pixelated.bitmask_libraries.provider import LeapProvider -from pixelated.bitmask_libraries.session import LeapSessionFactory +from pixelated.config.sessions import LeapSessionFactory from leap.auth import SRPAuth from leap.common.events import server as events_server import pixelated.extensions.shared_db @@ -53,7 +52,7 @@ def register( events_server.ensure_server() LeapCertificate.set_cert_and_fingerprint(provider_cert, provider_cert_fingerprint) config = LeapConfig(leap_home=leap_home) - provider = LeapProvider(server_name, config) + provider = LeapProvider(server_name) LeapCertificate(provider).setup_ca_bundle() srp_auth = SRPAuth(provider.api_uri, LeapCertificate(provider).provider_api_cert) diff --git a/service/test/support/integration/app_test_client.py b/service/test/support/integration/app_test_client.py index c2bf22cb..5d1e760a 100644 --- a/service/test/support/integration/app_test_client.py +++ b/service/test/support/integration/app_test_client.py @@ -37,8 +37,7 @@ from twisted.cred import checkers, credentials from pixelated.adapter.mailstore.leap_attachment_store import LeapAttachmentStore from pixelated.adapter.services.feedback_service import FeedbackService from pixelated.application import ServicesFactory, UserAgentMode, SingleUserServicesFactory, set_up_protected_resources -from pixelated.bitmask_libraries.config import LeapConfig -from pixelated.bitmask_libraries.session import LeapSession +from pixelated.config.sessions import LeapSession from pixelated.config.services import Services, ServicesFactory, SingleUserServicesFactory from pixelated.config.site import PixelatedSite @@ -197,7 +196,6 @@ class AppTestClient(object): else: self.service_factory = StubServicesFactory(self.accounts, mode) provider = mock() - provider.config = LeapConfig(self._tmp_dir.name) self.resource = set_up_protected_resources(RootResource(self.service_factory), provider, self.service_factory, checker=StubSRPChecker(provider)) diff --git a/service/test/support/integration/multi_user_client.py b/service/test/support/integration/multi_user_client.py index d6133e64..4b2cb832 100644 --- a/service/test/support/integration/multi_user_client.py +++ b/service/test/support/integration/multi_user_client.py @@ -22,7 +22,7 @@ from leap.auth import SRPAuth from pixelated.application import UserAgentMode, set_up_protected_resources from pixelated.config.services import ServicesFactory -from pixelated.bitmask_libraries.session import LeapSession, LeapSessionFactory +from pixelated.config.sessions import LeapSessionFactory, LeapSession import pixelated.config.services from pixelated.resources.root_resource import RootResource from test.support.integration import AppTestClient diff --git a/service/test/unit/bitmask_libraries/test_abstract_leap.py b/service/test/unit/bitmask_libraries/test_abstract_leap.py index 6f2351cd..237a1152 100644 --- a/service/test/unit/bitmask_libraries/test_abstract_leap.py +++ b/service/test/unit/bitmask_libraries/test_abstract_leap.py @@ -40,7 +40,7 @@ class AbstractLeapTest(unittest.TestCase): uuid=self._uuid, token=self._token) - self.nicknym = MagicMock() + self.keymanager = MagicMock() self.soledad_account = MagicMock() diff --git a/service/test/unit/bitmask_libraries/test_certs.py b/service/test/unit/bitmask_libraries/test_certs.py index 5d447537..bd9b32d3 100644 --- a/service/test/unit/bitmask_libraries/test_certs.py +++ b/service/test/unit/bitmask_libraries/test_certs.py @@ -1,14 +1,16 @@ import unittest from pixelated.bitmask_libraries.certs import LeapCertificate +from pixelated.config import leap_config from mock import MagicMock class CertsTest(unittest.TestCase): def setUp(self): - config = MagicMock(leap_home='/some/leap/home') - self.provider = MagicMock(server_name=u'test.leap.net', config=config) + leap_config.leap_home = '/some/leap/home' + + self.provider = MagicMock(server_name=u'test.leap.net') def test_set_cert_and_fingerprint_sets_cert(self): LeapCertificate.set_cert_and_fingerprint('some cert', None) diff --git a/service/test/unit/bitmask_libraries/test_nicknym.py b/service/test/unit/bitmask_libraries/test_keymanager.py index d15f1a75..1a1038b8 100644 --- a/service/test/unit/bitmask_libraries/test_nicknym.py +++ b/service/test/unit/bitmask_libraries/test_keymanager.py @@ -14,28 +14,28 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see <http://www.gnu.org/licenses/>. from mock import patch +from mockito import when from test_abstract_leap import AbstractLeapTest from leap.keymanager import openpgp, KeyNotFound -from pixelated.bitmask_libraries.nicknym import NickNym +from pixelated.bitmask_libraries.keymanager import Keymanager from pixelated.bitmask_libraries.certs import LeapCertificate +from pixelated.config import leap_config -class NickNymTest(AbstractLeapTest): - # @patch('pixelated.bitmask_libraries.nicknym.KeyManager.__init__', return_value=None) - @patch('pixelated.bitmask_libraries.nicknym.KeyManager') +class KeymanagerTest(AbstractLeapTest): + @patch('pixelated.bitmask_libraries.keymanager.KeyManager') def test_that_keymanager_is_created(self, keymanager_mock): - # given LeapCertificate.provider_api_cert = '/some/path/to/provider_ca_cert' - # when - NickNym(self.provider, - self.config, - self.soledad, - 'test_user@some-server.test', - self.auth.token, - self.auth.uuid) + when(self.provider)._discover_nicknym_server().thenReturn('https://nicknym.some-server.test:6425/') + leap_config.gpg_binary = '/path/to/gpg' + + Keymanager(self.provider, + self.soledad, + 'test_user@some-server.test', + self.auth.token, + self.auth.uuid) - # then keymanager_mock.assert_called_with( 'test_user@some-server.test', 'https://nicknym.some-server.test:6425/', @@ -47,20 +47,19 @@ class NickNymTest(AbstractLeapTest): uid=self.auth.uuid, gpgbinary='/path/to/gpg') - @patch('pixelated.bitmask_libraries.nicknym.KeyManager') + @patch('pixelated.bitmask_libraries.keymanager.KeyManager') def test_gen_key(self, keymanager_mock): # given keyman = keymanager_mock.return_value keyman.get_key.side_effect = KeyNotFound - nicknym = NickNym(self.provider, - self.config, - self.soledad, - 'test_user@some-server.test', - self.auth.token, - self.auth.uuid) + keymanager = Keymanager(self.provider, + self.soledad, + 'test_user@some-server.test', + self.auth.token, + self.auth.uuid) # when/then - nicknym.generate_openpgp_key() + keymanager.generate_openpgp_key() keyman.get_key.assert_called_with('test_user@some-server.test', private=True, fetch_remote=False) keyman.gen_key.assert_called() diff --git a/service/test/unit/bitmask_libraries/test_provider.py b/service/test/unit/bitmask_libraries/test_provider.py index df851203..1284698f 100644 --- a/service/test/unit/bitmask_libraries/test_provider.py +++ b/service/test/unit/bitmask_libraries/test_provider.py @@ -18,9 +18,9 @@ import json from mock import patch, MagicMock, ANY from httmock import all_requests, HTTMock, urlmatch from requests import HTTPError -from pixelated.bitmask_libraries.config import LeapConfig from pixelated.bitmask_libraries.provider import LeapProvider from pixelated.bitmask_libraries.certs import LeapCertificate +from pixelated.config import leap_config from test_abstract_leap import AbstractLeapTest import requests @@ -139,12 +139,12 @@ PROVIDER_WEB_CERT = '/tmp/bootstrap-ca.crt' class LeapProviderTest(AbstractLeapTest): def setUp(self): - self.config = LeapConfig(leap_home='/tmp/foobar') + leap_config.set_leap_home('/tmp/foobar') LeapCertificate.set_cert_and_fingerprint(PROVIDER_WEB_CERT, None) def test_provider_fetches_provider_json(self): - with HTTMock(provider_json_mock): - provider = LeapProvider('some-provider.test', self.config) + with HTTMock(provider_json_mock, soledad_json_mock): + provider = LeapProvider('some-provider.test') self.assertEqual("1", provider.api_version) self.assertEqual("some-provider.test", provider.domain) @@ -156,42 +156,36 @@ class LeapProviderTest(AbstractLeapTest): def test_provider_json_throws_exception_on_status_code(self): with HTTMock(not_found_mock): - self.assertRaises(HTTPError, LeapProvider, 'some-provider.test', self.config) + self.assertRaises(HTTPError, LeapProvider, 'some-provider.test') def test_fetch_soledad_json(self): with HTTMock(provider_json_mock, soledad_json_mock, not_found_mock): - provider = LeapProvider('some-provider.test', self.config) + provider = LeapProvider('some-provider.test') soledad = provider.fetch_soledad_json() self.assertEqual("some value", soledad.get('some key')) - def test_throw_exception_for_fetch_soledad_status_code(self): - with HTTMock(provider_json_mock, not_found_mock): - provider = LeapProvider('some-provider.test', self.config) - - self.assertRaises(HTTPError, provider.fetch_soledad_json) - def test_fetch_smtp_json(self): - with HTTMock(provider_json_mock, smtp_json_mock, not_found_mock): - provider = LeapProvider('some-provider.test', self.config) + with HTTMock(provider_json_mock, soledad_json_mock, smtp_json_mock, not_found_mock): + provider = LeapProvider('some-provider.test') smtp = provider.fetch_smtp_json() self.assertEqual('mx.some-provider.test', smtp.get('hosts').get('leap-mx').get('hostname')) def test_throw_exception_for_fetch_smtp_status_code(self): - with HTTMock(provider_json_mock, not_found_mock): - provider = LeapProvider('some-provider.test', self.config) + with HTTMock(provider_json_mock, soledad_json_mock, not_found_mock): + provider = LeapProvider('some-provider.test') self.assertRaises(HTTPError, provider.fetch_smtp_json) def test_fetch_valid_certificate(self): - with HTTMock(provider_json_mock, ca_cert_mock, not_found_mock): - provider = LeapProvider('some-provider.test', self.config) + with HTTMock(provider_json_mock, soledad_json_mock, ca_cert_mock, not_found_mock): + provider = LeapProvider('some-provider.test') provider.fetch_valid_certificate() def test_throw_exception_for_invalid_certificate(self): expected_exception_message = 'Certificate fingerprints don\'t match! Expected [0123456789012345678901234567890123456789012345678901234567890123] but got [06e2300bdbc118c290eda0dc977c24080718f4eeca68c8b0ad431872a2baa22d]' - with HTTMock(provider_json_invalid_fingerprint_mock, ca_cert_mock, not_found_mock): - provider = LeapProvider('some-provider.test', self.config) + with HTTMock(provider_json_invalid_fingerprint_mock, soledad_json_mock, ca_cert_mock, not_found_mock): + provider = LeapProvider('some-provider.test') with self.assertRaises(Exception) as cm: provider.fetch_valid_certificate() self.assertEqual(expected_exception_message, cm.exception.message) @@ -204,8 +198,8 @@ class LeapProviderTest(AbstractLeapTest): with patch('pixelated.bitmask_libraries.provider.requests.session', new=session_func): with patch('pixelated.bitmask_libraries.provider.requests.get', new=get_func): - with HTTMock(provider_json_mock, ca_cert_mock, not_found_mock): - provider = LeapProvider('some-provider.test', self.config) + with HTTMock(provider_json_mock, ca_cert_mock, soledad_json_mock, not_found_mock): + provider = LeapProvider('some-provider.test') provider.fetch_valid_certificate() session.get.assert_any_call('https://some-provider.test/ca.crt', verify=PROVIDER_WEB_CERT, timeout=15) @@ -217,7 +211,7 @@ class LeapProviderTest(AbstractLeapTest): with patch('pixelated.bitmask_libraries.provider.requests.get', new=get_func): with HTTMock(provider_json_mock, soledad_json_mock, not_found_mock): - provider = LeapProvider('some-provider.test', self.config) + provider = LeapProvider('some-provider.test') provider.fetch_soledad_json() get_func.assert_called_with('https://api.some-provider.test:4430/1/config/soledad-service.json', verify=PROVIDER_API_CERT, timeout=15) @@ -227,8 +221,8 @@ class LeapProviderTest(AbstractLeapTest): LeapCertificate.set_cert_and_fingerprint(None, 'some fingerprint') with patch('pixelated.bitmask_libraries.provider.requests.session', new=session_func): - with HTTMock(provider_json_mock, ca_cert_mock, not_found_mock): - provider = LeapProvider('some-provider.test', self.config) + with HTTMock(provider_json_mock, ca_cert_mock, soledad_json_mock, not_found_mock): + provider = LeapProvider('some-provider.test') provider.fetch_valid_certificate() session.get.assert_any_call('https://some-provider.test/ca.crt', verify=False, timeout=15) diff --git a/service/test/unit/bitmask_libraries/test_smtp_cert_downloader.py b/service/test/unit/bitmask_libraries/test_smtp_cert_downloader.py deleted file mode 100644 index 2a4afa40..00000000 --- a/service/test/unit/bitmask_libraries/test_smtp_cert_downloader.py +++ /dev/null @@ -1,84 +0,0 @@ -# -# Copyright (c) 2015 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. -import unittest -from mockito import mock, unstub -from requests import HTTPError -from pixelated.bitmask_libraries.session import SmtpCertDownloader -from tempfile import NamedTemporaryFile -from httmock import all_requests, HTTMock, urlmatch - -CERTIFICATE_DATA = 'some cert data' -USERNAME = 'some_user_name' - - -@all_requests -def not_found_mock(url, request): - return {'status_code': 404, - 'content': 'foobar'} - - -@urlmatch(netloc='api.some-server.test:4430', path='/1/smtp_cert', method='POST') -def smtp_cert_mock(url, request): - if request.body == 'address=%s' % USERNAME: - return { - "status_code": 200, - "content": CERTIFICATE_DATA - } - else: - return { - 'status_code': 401 - } - - -class TestSmtpCertDownloader(unittest.TestCase): - - def setUp(self): - self._provider = mock() - self._config = mock() - self._config.leap_home = '/tmp' - self._auth = mock() - - self._provider.config = self._config - self._provider.api_uri = 'https://api.some-server.test:4430' - self._provider.api_version = '1' - self._provider.server_name = 'some.host.tld' - - self._auth.username = USERNAME - self._auth.token = 'some token' - - def tearDown(self): - unstub() - - def test_download_certificate(self): - with HTTMock(smtp_cert_mock, not_found_mock): - cert_data = SmtpCertDownloader(self._provider, self._auth).download() - - self.assertEqual(CERTIFICATE_DATA, cert_data) - - def test_error_if_not_found(self): - downloader = SmtpCertDownloader(self._provider, self._auth) - with HTTMock(not_found_mock): - self.assertRaises(HTTPError, downloader.download) - - def test_download_to(self): - downloader = SmtpCertDownloader(self._provider, self._auth) - - with NamedTemporaryFile() as tmp_file: - with HTTMock(smtp_cert_mock, not_found_mock): - downloader.download_to(tmp_file.name) - - file_content = open(tmp_file.name).read() - self.assertEqual(CERTIFICATE_DATA, file_content) diff --git a/service/test/unit/bitmask_libraries/test_smtp_client_certificate.py b/service/test/unit/bitmask_libraries/test_smtp_client_certificate.py index e938d6f5..050f2d94 100644 --- a/service/test/unit/bitmask_libraries/test_smtp_client_certificate.py +++ b/service/test/unit/bitmask_libraries/test_smtp_client_certificate.py @@ -16,12 +16,36 @@ import os import unittest import tempdir -from pixelated.bitmask_libraries import session from leap.srp_session import SRPSession import leap.common.certs as certs from mockito import mock, unstub, when, verify, never, any as ANY -from pixelated.bitmask_libraries.session import SmtpClientCertificate +from pixelated.config.sessions import SmtpClientCertificate + +from tempfile import NamedTemporaryFile +from httmock import all_requests, HTTMock, urlmatch + +CERTIFICATE_DATA = 'some cert data' +USERNAME = 'some_user_name' + + +@all_requests +def not_found_mock(url, request): + return {'status_code': 404, + 'content': 'foobar'} + + +@urlmatch(netloc='api.some-server.test:4430', path='/1/smtp_cert', method='POST') +def smtp_cert_mock(url, request): + if request.body == 'address=%s' % USERNAME: + return { + "status_code": 200, + "content": CERTIFICATE_DATA + } + else: + return { + 'status_code': 401 + } class TestSmtpClientCertificate(unittest.TestCase): @@ -29,11 +53,12 @@ class TestSmtpClientCertificate(unittest.TestCase): def setUp(self): self.tmp_dir = tempdir.TempDir() self.provider = mock() + self.provider.api_uri = 'https://api.some-server.test:4430' + self.provider.api_version = '1' + self.provider.server_name = 'some.host.tld' self.provider.domain = 'some-provider.tld' - self.auth = SRPSession('username', 'token', 'uuid', 'session_id', {}) + self.auth = SRPSession(USERNAME, 'token', 'uuid', 'session_id', {}) self.pem_path = os.path.join(self.tmp_dir.name, 'providers', 'some-provider.tld', 'keys', 'client', 'smtp.pem') - self.downloader = mock() - when(session).SmtpCertDownloader(self.provider, self.auth).thenReturn(self.downloader) def tearDown(self): self.tmp_dir.dissolve() @@ -41,20 +66,20 @@ class TestSmtpClientCertificate(unittest.TestCase): def test_download_certificate(self): cert = SmtpClientCertificate(self.provider, self.auth, self.tmp_dir.name) + when(cert).download_to(ANY()).thenReturn(None) result = cert.cert_path() self.assertEqual(self.pem_path, result) - verify(self.downloader).download_to(self.pem_path) def test_download_certificate_if_redownload_necessary_e_g_certificate_expired(self): self.pretend_all_paths_exist() when(certs).should_redownload(self.pem_path).thenReturn(True) cert = SmtpClientCertificate(self.provider, self.auth, self.tmp_dir.name) + when(cert).download_to(ANY()).thenReturn(None) result = cert.cert_path() self.assertEqual(self.pem_path, result) - verify(self.downloader).download_to(self.pem_path) def pretend_all_paths_exist(self): when(os.path).exists(ANY()).thenReturn(True) @@ -66,4 +91,13 @@ class TestSmtpClientCertificate(unittest.TestCase): result = cert.cert_path() self.assertEqual(self.pem_path, result) - verify(self.downloader, never).download_to(ANY()) + + def test_download_to(self): + cert = SmtpClientCertificate(self.provider, self.auth, self.tmp_dir.name) + + with NamedTemporaryFile() as tmp_file: + with HTTMock(smtp_cert_mock, not_found_mock): + cert.download_to(tmp_file.name) + + file_content = open(tmp_file.name).read() + self.assertEqual(CERTIFICATE_DATA, file_content) diff --git a/service/test/unit/config/test_leap.py b/service/test/unit/config/test_leap.py index 5576cca8..b87065d2 100644 --- a/service/test/unit/config/test_leap.py +++ b/service/test/unit/config/test_leap.py @@ -9,7 +9,7 @@ class TestAuth(unittest.TestCase): @patch('pixelated.config.leap.LeapSessionFactory') @defer.inlineCallbacks - def test_create_leap_session_calls_initinal_sync(self, session_factory__ctor_mock): + def test_create_leap_session_calls_initial_sync(self, session_factory__ctor_mock): session_factory_mock = session_factory__ctor_mock.return_value provider_mock = MagicMock() auth_mock = MagicMock() @@ -19,7 +19,7 @@ class TestAuth(unittest.TestCase): yield create_leap_session(provider_mock, 'username', 'password', auth=auth_mock) - session.initial_sync.assert_called_with() + session.first_required_sync.assert_called_with() @patch('pixelated.config.leap.LeapSessionFactory') @defer.inlineCallbacks @@ -29,10 +29,10 @@ class TestAuth(unittest.TestCase): auth_mock = MagicMock() session = MagicMock() - session.initial_sync.side_effect = [InvalidAuthTokenError, defer.succeed(None)] + session.first_required_sync.side_effect = [InvalidAuthTokenError, defer.succeed(None)] session_factory_mock.create.return_value = session yield create_leap_session(provider_mock, 'username', 'password', auth=auth_mock) session.close.assert_called_with() - self.assertEqual(2, session.initial_sync.call_count) + self.assertEqual(2, session.first_required_sync.call_count) diff --git a/service/test/unit/bitmask_libraries/test_session.py b/service/test/unit/config/test_sessions.py index 84f9f023..be418a73 100644 --- a/service/test/unit/bitmask_libraries/test_session.py +++ b/service/test/unit/config/test_sessions.py @@ -17,8 +17,9 @@ from mock import patch from mock import MagicMock from twisted.internet import defer -from pixelated.bitmask_libraries.session import LeapSession, SessionCache -from test_abstract_leap import AbstractLeapTest +from pixelated.config.sessions import LeapSession, SessionCache + +from test.unit.bitmask_libraries.test_abstract_leap import AbstractLeapTest from leap.common.events.catalog import KEYMANAGER_FINISHED_KEY_GENERATION @@ -28,32 +29,32 @@ class SessionTest(AbstractLeapTest): super(SessionTest, self).setUp() self.smtp_mock = MagicMock() - @patch('pixelated.bitmask_libraries.session.register') - @patch('pixelated.bitmask_libraries.session.Account') + @patch('pixelated.config.sessions.register') + @patch('pixelated.config.sessions.Account') @defer.inlineCallbacks def test_background_jobs_are_started_during_initial_sync(self, *unused): mailFetcherMock = MagicMock() - with patch('pixelated.bitmask_libraries.session.reactor.callFromThread', new=_execute_func) as _: + with patch('pixelated.config.sessions.reactor.callFromThread', new=_execute_func) as _: with patch.object(LeapSession, '_create_incoming_mail_fetcher', return_value=mailFetcherMock) as _: session = self._create_session() - yield session.initial_sync() + yield session.first_required_sync() mailFetcherMock.startService.assert_called_once() - @patch('pixelated.bitmask_libraries.session.register') - @patch('pixelated.bitmask_libraries.session.unregister') - @patch('pixelated.bitmask_libraries.session.Account') + @patch('pixelated.config.sessions.register') + @patch('pixelated.config.sessions.unregister') + @patch('pixelated.config.sessions.Account') @defer.inlineCallbacks def test_that_close_stops_background_jobs(self, *unused): - with patch('pixelated.bitmask_libraries.session.reactor.callFromThread', new=_execute_func) as _: - with patch('pixelated.bitmask_libraries.session.LeapSession._create_incoming_mail_fetcher') as mail_fetcher_mock: + with patch('pixelated.config.sessions.reactor.callFromThread', new=_execute_func) as _: + with patch('pixelated.config.sessions.LeapSession._create_incoming_mail_fetcher') as mail_fetcher_mock: session = self._create_session() - yield session.initial_sync() + yield session.first_required_sync() session.close() mail_fetcher_mock.stopService.assert_called_once() - def test_that_sync_deferes_to_soledad(self): - with patch('pixelated.bitmask_libraries.session.reactor.callFromThread', new=_execute_func) as _: - with patch('pixelated.bitmask_libraries.session.LeapSession._create_incoming_mail_fetcher') as mail_fetcher_mock: + def test_that_sync_defers_to_soledad(self): + with patch('pixelated.config.sessions.reactor.callFromThread', new=_execute_func) as _: + with patch('pixelated.config.sessions.LeapSession._create_incoming_mail_fetcher') as mail_fetcher_mock: session = self._create_session() yield session.sync() self.soledad_session.sync.assert_called_once() @@ -61,34 +62,34 @@ class SessionTest(AbstractLeapTest): def test_session_registers_to_generated_keys(self): email = 'someone@somedomain.tld' self.provider.address_for.return_value = email - with patch('pixelated.bitmask_libraries.session.register') as register_mock: + with patch('pixelated.config.sessions.register') as register_mock: session = self._create_session() register_mock.assert_called_once_with(KEYMANAGER_FINISHED_KEY_GENERATION, session._set_fresh_account, uid=email) - @patch('pixelated.bitmask_libraries.session.register') + @patch('pixelated.config.sessions.register') def test_close_unregisters_from_generate_keys_events(self, _): email = 'someone@somedomain.tld' self.provider.address_for.return_value = email session = self._create_session() - with patch('pixelated.bitmask_libraries.session.unregister') as unregister_mock: + with patch('pixelated.config.sessions.unregister') as unregister_mock: session.close() unregister_mock.assert_called_once_with(KEYMANAGER_FINISHED_KEY_GENERATION, uid=email) - @patch('pixelated.bitmask_libraries.session.register') + @patch('pixelated.config.sessions.register') def test_close_stops_soledad(self, _): email = 'someone@somedomain.tld' self.provider.address_for.return_value = email session = self._create_session() - with patch('pixelated.bitmask_libraries.session.unregister') as unregister_mock: + with patch('pixelated.config.sessions.unregister') as unregister_mock: session.close() self.soledad_session.close.assert_called_once_with() - @patch('pixelated.bitmask_libraries.session.register') + @patch('pixelated.config.sessions.register') def test_close_removes_session_from_cache(self, _): email = 'someone@somedomain.tld' self.provider.address_for.return_value = email @@ -99,12 +100,12 @@ class SessionTest(AbstractLeapTest): self.assertEqual(session, SessionCache.lookup_session(key)) - with patch('pixelated.bitmask_libraries.session.unregister') as unregister_mock: + with patch('pixelated.config.sessions.unregister') as unregister_mock: session.close() self.assertIsNone(SessionCache.lookup_session(key)) - @patch('pixelated.bitmask_libraries.session.register') + @patch('pixelated.config.sessions.register') def test_close_ends_account_session(self, _): account_mock = MagicMock() email = 'someone@somedomain.tld' @@ -112,18 +113,18 @@ class SessionTest(AbstractLeapTest): session = self._create_session() session.account = account_mock - with patch('pixelated.bitmask_libraries.session.unregister') as unregister_mock: + with patch('pixelated.config.sessions.unregister') as unregister_mock: session.close() account_mock.end_session.assert_called_once_with() - @patch('pixelated.bitmask_libraries.session.register') + @patch('pixelated.config.sessions.register') def test_session_fresh_is_initially_false(self, _): session = self._create_session() self.assertFalse(session.fresh_account) - @patch('pixelated.bitmask_libraries.session.register') + @patch('pixelated.config.sessions.register') def test_session_sets_status_to_fresh_on_key_generation_event(self, _): session = self._create_session() self.provider.address_for.return_value = 'someone@somedomain.tld' @@ -132,7 +133,7 @@ class SessionTest(AbstractLeapTest): self.assertTrue(session.fresh_account) - @patch('pixelated.bitmask_libraries.session.register') + @patch('pixelated.config.sessions.register') def test_closed_session_not_reused(self, _): session = self._create_session() SessionCache.remember_session('somekey', session) @@ -142,7 +143,7 @@ class SessionTest(AbstractLeapTest): self.assertIsNone(result) - @patch('pixelated.bitmask_libraries.session.register') + @patch('pixelated.config.sessions.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' @@ -151,21 +152,8 @@ class SessionTest(AbstractLeapTest): self.assertFalse(session.fresh_account) - @patch('pixelated.bitmask_libraries.session.register') - @patch('pixelated.bitmask_libraries.session.unregister') - @patch('pixelated.bitmask_libraries.session.Account') - @defer.inlineCallbacks - def test_session_initial_sync_only_triggered_once(self, *unused): - mailFetcherMock = MagicMock() - 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_initially_synced = True - yield session.initial_sync() - self.assertFalse(mailFetcherMock.startService.called) - def _create_session(self): - return LeapSession(self.provider, self.auth, self.mail_store, self.soledad_session, self.nicknym, self.smtp_mock) + return LeapSession(self.provider, self.auth, self.mail_store, self.soledad_session, self.keymanager, self.smtp_mock) def _execute_func(func): diff --git a/service/test/unit/maintenance/test_commands.py b/service/test/unit/maintenance/test_commands.py index a0fc58d6..812c1bc2 100644 --- a/service/test/unit/maintenance/test_commands.py +++ b/service/test/unit/maintenance/test_commands.py @@ -17,7 +17,7 @@ import unittest import email from pixelated.maintenance import delete_all_mails, load_mails -from pixelated.bitmask_libraries.session import LeapSession +from pixelated.config.sessions import LeapSession from pixelated.adapter.mailstore import MailStore from leap.soledad.client import Soledad from leap.soledad.common.document import SoledadDocument diff --git a/service/test/unit/resources/test_login_resource.py b/service/test/unit/resources/test_login_resource.py index 2fba72fd..d006e934 100644 --- a/service/test/unit/resources/test_login_resource.py +++ b/service/test/unit/resources/test_login_resource.py @@ -9,7 +9,7 @@ from twisted.trial import unittest from twisted.web.resource import IResource from twisted.web.test.requesthelper import DummyRequest -from pixelated.bitmask_libraries.session import LeapSession, LeapSessionFactory +from pixelated.config.sessions import LeapSessionFactory, LeapSession from pixelated.resources.login_resource import LoginResource from test.unit.resources import DummySite @@ -220,7 +220,7 @@ class TestLoginPOST(unittest.TestCase): d.addCallback(assert_login_setup_service_for_user) return d - @patch('pixelated.bitmask_libraries.session.LeapSessionFactory.create') + @patch('pixelated.config.sessions.LeapSessionFactory.create') @patch('leap.auth.SRPAuth.authenticate') @patch('pixelated.config.services.Services.setup') def test_leap_session_is_not_created_when_leap_auth_fails(self, mock_service_setup, mock_leap_srp_auth, mock_leap_session_create): diff --git a/service/test/unit/resources/test_users_resource.py b/service/test/unit/resources/test_users_resource.py index bfd61022..9862209d 100644 --- a/service/test/unit/resources/test_users_resource.py +++ b/service/test/unit/resources/test_users_resource.py @@ -9,7 +9,7 @@ from twisted.trial import unittest from twisted.web.resource import IResource from twisted.web.test.requesthelper import DummyRequest -from pixelated.bitmask_libraries.session import LeapSession, LeapSessionFactory +from pixelated.config.sessions import LeapSessionFactory, LeapSession from pixelated.config.services import Services, ServicesFactory from pixelated.resources.login_resource import LoginResource from pixelated.resources.users import UsersResource |