From 7f87384ed8c6e3d1b8c53d75e52a8bbfb4aaec52 Mon Sep 17 00:00:00 2001 From: irregulator Date: Sun, 27 Jul 2014 22:56:07 +0300 Subject: [PATCH] feature/5785, downloads configs.json from provider configs.json lists service definition files by version --- src/leap/bitmask/backend/api.py | 2 + src/leap/bitmask/backend/components.py | 14 +++++ src/leap/bitmask/backend/leapbackend.py | 6 ++ src/leap/bitmask/backend/leapsignaler.py | 1 + src/leap/bitmask/config/configs_spec.py | 18 ++++++ src/leap/bitmask/gui/mainwindow.py | 10 ++++ .../bitmask/provider/providerbootstrapper.py | 55 +++++++++++++++++++ src/leap/bitmask/services/__init__.py | 14 +++++ 8 files changed, 120 insertions(+) create mode 100644 src/leap/bitmask/config/configs_spec.py diff --git a/src/leap/bitmask/backend/api.py b/src/leap/bitmask/backend/api.py index 4f52e4702..7e969cdee 100644 --- a/src/leap/bitmask/backend/api.py +++ b/src/leap/bitmask/backend/api.py @@ -47,6 +47,7 @@ "provider_get_pinned_providers", "provider_get_supported_services", "provider_setup", + "provider_get_version_configs", "settings_set_selected_gateway", "smtp_start_service", "smtp_stop_service", @@ -123,6 +124,7 @@ "prov_problem_with_provider", "prov_unsupported_api", "prov_unsupported_client", + "prov_get_version_configs", "soledad_bootstrap_failed", "soledad_bootstrap_finished", "soledad_cancelled_bootstrap", diff --git a/src/leap/bitmask/backend/components.py b/src/leap/bitmask/backend/components.py index b372db890..cfb765cbd 100644 --- a/src/leap/bitmask/backend/components.py +++ b/src/leap/bitmask/backend/components.py @@ -56,6 +56,7 @@ from leap.bitmask.util import force_eval from leap.common import certs as leap_certs +from leap.common.check import leap_assert from leap.keymanager import openpgp from leap.keymanager.errors import KeyAddressMismatch, KeyFingerprintMismatch @@ -283,6 +284,19 @@ def get_pinned_providers(self): self._signaler.prov_get_pinned_providers, PinnedProviders.domains()) + def get_version_configs(self, domain): + """ + Downloads configs.json + """ + provider_config = ProviderConfig.get_provider_config(domain) + leap_assert(provider_config, "We need a provider configuration!") + logger.debug("Downloading configs.json for %s" % domain) + + self._signaler.signal( + self._signaler.prov_get_version_configs, + self._provider_bootstrapper.download_version_configs( + provider_config)) + class Register(object): """ diff --git a/src/leap/bitmask/backend/leapbackend.py b/src/leap/bitmask/backend/leapbackend.py index 6b0328ca3..b971d83a4 100644 --- a/src/leap/bitmask/backend/leapbackend.py +++ b/src/leap/bitmask/backend/leapbackend.py @@ -159,6 +159,12 @@ def provider_get_pinned_providers(self): """ self._provider.get_pinned_providers() + def provider_get_version_configs(self, domain): + """ + Get configs.json from provider + """ + self._provider.get_version_configs(domain) + def user_register(self, provider, username, password): """ Register a user using the domain and password given as parameters. diff --git a/src/leap/bitmask/backend/leapsignaler.py b/src/leap/bitmask/backend/leapsignaler.py index a36e6fdc7..389100ddd 100644 --- a/src/leap/bitmask/backend/leapsignaler.py +++ b/src/leap/bitmask/backend/leapsignaler.py @@ -87,6 +87,7 @@ class LeapSignaler(SignalerQt): prov_problem_with_provider = QtCore.Signal() prov_unsupported_api = QtCore.Signal() prov_unsupported_client = QtCore.Signal() + prov_get_version_configs = QtCore.Signal() soledad_bootstrap_failed = QtCore.Signal() soledad_bootstrap_finished = QtCore.Signal() diff --git a/src/leap/bitmask/config/configs_spec.py b/src/leap/bitmask/config/configs_spec.py new file mode 100644 index 000000000..879c8773d --- /dev/null +++ b/src/leap/bitmask/config/configs_spec.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# configs_spec.py + +version_configs_spec = { + 'description': 'version configs', + 'type': 'object', + 'properties': { + 'eip': { + 'type': dict, + }, + 'smtp': { + 'type': dict, + }, + 'soledad': { + 'type': dict, + } + } +} diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 2f78fd147..ae122b80a 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1317,6 +1317,7 @@ def _authentication_finished(self): domain = self._login_widget.get_selected_provider() full_user_id = make_address(user, domain) self._mail_conductor.userid = full_user_id + self._download_version_configs() self._start_eip_bootstrap() self.ui.action_create_new_account.setEnabled(True) @@ -1331,6 +1332,15 @@ def _authentication_finished(self): if MX_SERVICE not in self._provider_details['services']: self._set_mx_visible(False) + def _download_version_configs(self): + """ + Downloads configs.json, containing versions + of services' definitions + """ + self._login_widget.logged_in() + domain = self._login_widget.get_selected_provider() + self._backend.provider_get_version_configs(domain=domain) + def _start_eip_bootstrap(self): """ Changes the stackedWidget index to the EIP status one and diff --git a/src/leap/bitmask/provider/providerbootstrapper.py b/src/leap/bitmask/provider/providerbootstrapper.py index 71edbb875..de96cd096 100644 --- a/src/leap/bitmask/provider/providerbootstrapper.py +++ b/src/leap/bitmask/provider/providerbootstrapper.py @@ -30,6 +30,7 @@ from leap.bitmask.config.providerconfig import ProviderConfig, MissingCACert from leap.bitmask.provider import get_provider_path from leap.bitmask.provider.pinned import PinnedProviders +from leap.bitmask.services import VersionConfig from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper from leap.bitmask.util.constants import REQUEST_TIMEOUT from leap.bitmask.util.request_helpers import get_content @@ -409,3 +410,57 @@ def run_provider_setup_checks(self, ] return self.addCallbackChain(cb_chain) + + def download_version_configs(self, provider_config): + """ + Downloads the json containing versions for + provider's service definition file. + + :param provider_config: Provider configuration + :type provider_config: ProviderConfig + """ + leap_assert(provider_config, "We need a provider config!") + leap_assert_type(provider_config, ProviderConfig) + + configs_json = "configs.json" + version_config = VersionConfig() + download_if_needed = True + headers = {} + mtime = get_mtime(os.path.join(util.get_path_prefix(), + "leap", "providers", + provider_config.get_domain(), + configs_json)) + + if download_if_needed and mtime: + headers['if-modified-since'] = mtime + + api_version = provider_config.get_api_version() + version_config.set_api_version(api_version) + + configs_uri = "%s/%s/config/configs.json" % ( + provider_config.get_api_uri(), + api_version) + + logger.debug('Downloading configs.json from: %s' % (configs_uri)) + + cookies = None + res = self._session.get(configs_uri, + verify=self.verify, + headers=headers, + timeout=REQUEST_TIMEOUT, + cookies=cookies) + + res.raise_for_status() + + configs_path = ("leap", "providers", provider_config.get_domain(), + configs_json) + + if res.status_code == 304: + logger.debug("configs.json has not been modified") + version_config.load(os.path.join(*configs_path)) + else: + logger.debug("modified") + configs_content, mtime = get_content(res) + version_config.load(os.path.join(*configs_path), + data=configs_content, mtime=mtime) + version_config.save(configs_path) diff --git a/src/leap/bitmask/services/__init__.py b/src/leap/bitmask/services/__init__.py index ba12ba4e9..4a54933d2 100644 --- a/src/leap/bitmask/services/__init__.py +++ b/src/leap/bitmask/services/__init__.py @@ -24,6 +24,7 @@ from PySide import QtCore from leap.bitmask.config import flags +from leap.bitmask.config.configs_spec import version_configs_spec from leap.bitmask.crypto.srpauth import SRPAuth from leap.bitmask.util.constants import REQUEST_TIMEOUT from leap.bitmask.util.privilege_policies import is_missing_policy_permissions @@ -180,3 +181,16 @@ def name(self): """ leap_assert(self._service_name is not None) return self._service_name + + +class VersionConfig(BaseConfig): + """ + Base class for configs.json + """ + def _get_schema(self): + """ + Returns the schema corresponding to the version given. + + :rtype: dict or None if the version is not supported. + """ + return version_configs_spec