summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorBruno Wagner <bwagner@riseup.net>2016-08-19 21:37:34 -0300
committerBruno Wagner <bwagner@riseup.net>2016-08-19 21:37:34 -0300
commit9cdd52be577fff75830c854bd7738ee1649e7083 (patch)
treeef560dd628bda40832503250e1325283c49ede83 /service
parent9c5811c6b760415372c6cc67a9d34680c990cdd8 (diff)
Started deferring leap session creation #759
Started adapting get_leap_session to deferreds Soledad and keymanager setup calls will now happen in deferreds and leap session creation itself is a deferred with callbacks This is a start in breaking the big blocking calls we were doing on the main thread, this was done without changing code inside the leap libraries yet so things can be further optimized This breaks the ~4 seconds get_leap_session piece into smaller 1 seconds one, that can be further optimized and deferred to even smaller calls There are requests calls happening on the main thread that should get this number even further down Also moved some pieces from bitmask libraries to our bootstrap, because they are not bitmask libraries anymore and that was causing confusion
Diffstat (limited to 'service')
-rw-r--r--service/pixelated/application.py3
-rw-r--r--service/pixelated/bitmask_libraries/certs.py6
-rw-r--r--service/pixelated/bitmask_libraries/keymanager.py (renamed from service/pixelated/bitmask_libraries/nicknym.py)13
-rw-r--r--service/pixelated/bitmask_libraries/provider.py35
-rw-r--r--service/pixelated/bitmask_libraries/soledad.py46
-rw-r--r--service/pixelated/config/leap.py17
-rw-r--r--service/pixelated/config/leap_config.py (renamed from service/pixelated/bitmask_libraries/config.py)16
-rw-r--r--service/pixelated/config/services.py8
-rw-r--r--service/pixelated/config/sessions.py (renamed from service/pixelated/bitmask_libraries/session.py)315
-rw-r--r--service/pixelated/register.py5
-rw-r--r--service/test/support/integration/app_test_client.py4
-rw-r--r--service/test/support/integration/multi_user_client.py2
-rw-r--r--service/test/unit/bitmask_libraries/test_abstract_leap.py2
-rw-r--r--service/test/unit/bitmask_libraries/test_certs.py6
-rw-r--r--service/test/unit/bitmask_libraries/test_keymanager.py (renamed from service/test/unit/bitmask_libraries/test_nicknym.py)41
-rw-r--r--service/test/unit/bitmask_libraries/test_provider.py44
-rw-r--r--service/test/unit/bitmask_libraries/test_smtp_cert_downloader.py84
-rw-r--r--service/test/unit/bitmask_libraries/test_smtp_client_certificate.py50
-rw-r--r--service/test/unit/config/test_leap.py8
-rw-r--r--service/test/unit/config/test_sessions.py (renamed from service/test/unit/bitmask_libraries/test_session.py)72
-rw-r--r--service/test/unit/maintenance/test_commands.py2
-rw-r--r--service/test/unit/resources/test_login_resource.py4
-rw-r--r--service/test/unit/resources/test_users_resource.py2
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