diff options
| -rw-r--r-- | src/leap/bitmask/backend.py | 161 | ||||
| -rw-r--r-- | src/leap/bitmask/config/providerconfig.py | 64 | ||||
| -rw-r--r-- | src/leap/bitmask/gui/mainwindow.py | 207 | ||||
| -rw-r--r-- | src/leap/bitmask/gui/preferenceswindow.py | 114 | ||||
| -rw-r--r-- | src/leap/bitmask/gui/wizard.py | 73 | ||||
| -rw-r--r-- | src/leap/bitmask/services/soledad/soledadbootstrapper.py | 3 | 
6 files changed, 360 insertions, 262 deletions
| diff --git a/src/leap/bitmask/backend.py b/src/leap/bitmask/backend.py index d6d5004f..e8bf0482 100644 --- a/src/leap/bitmask/backend.py +++ b/src/leap/bitmask/backend.py @@ -37,8 +37,8 @@ from leap.bitmask.config.providerconfig import ProviderConfig  from leap.bitmask.crypto.srpauth import SRPAuth  from leap.bitmask.crypto.srpregister import SRPRegister  from leap.bitmask.platform_init import IS_LINUX -from leap.bitmask.provider import get_provider_path  from leap.bitmask.provider.providerbootstrapper import ProviderBootstrapper +from leap.bitmask.services import get_supported  from leap.bitmask.services.eip import eipconfig  from leap.bitmask.services.eip import get_openvpn_management  from leap.bitmask.services.eip.eipbootstrapper import EIPBootstrapper @@ -64,26 +64,6 @@ from PySide import QtCore  logger = logging.getLogger(__name__) -def get_provider_config(config, domain): -    """ -    Return the ProviderConfig object for the given domain. -    If it is already loaded in `config`, then don't reload. - -    :param config: a ProviderConfig object -    :type conig: ProviderConfig -    :param domain: the domain which config is required. -    :type domain: unicode - -    :returns: True if the config was loaded successfully, False otherwise. -    :rtype: bool -    """ -    # TODO: see ProviderConfig.get_provider_config -    if (not config.loaded() or config.get_domain() != domain): -        config.load(get_provider_path(domain)) - -    return config.loaded() - -  class ILEAPComponent(zope.interface.Interface):      """      Interface that every component for the backend should comply to @@ -167,6 +147,7 @@ class Provider(object):          :type bypass_checks: bool          """          self.key = "provider" +        self._signaler = signaler          self._provider_bootstrapper = ProviderBootstrapper(signaler,                                                             bypass_checks)          self._download_provider_defer = None @@ -208,13 +189,9 @@ class Provider(object):          """          d = None -        # TODO: use this commented code when we don't need the provider config -        # in the maiwindow. -        # config = ProviderConfig.get_provider_config(provider) -        # self._provider_config = config -        # if config is not None: -        config = self._provider_config -        if get_provider_config(config, provider): +        config = ProviderConfig.get_provider_config(provider) +        self._provider_config = config +        if config is not None:              d = self._provider_bootstrapper.run_provider_setup_checks(                  config, download_if_needed=True)          else: @@ -228,6 +205,73 @@ class Provider(object):              d = defer.Deferred()          return d +    def _get_services(self, domain): +        """ +        Returns a list of services provided by the given provider. + +        :param domain: the provider to get the services from. +        :type domain: str + +        :rtype: list of str +        """ +        services = [] +        provider_config = ProviderConfig.get_provider_config(domain) +        if provider_config is not None: +            services = provider_config.get_services() + +        return services + +    def get_supported_services(self, domain): +        """ +        Signal a list of supported services provided by the given provider. + +        :param domain: the provider to get the services from. +        :type domain: str + +        Signals: +            prov_get_supported_services -> list of unicode +        """ +        services = get_supported(self._get_services(domain)) + +        self._signaler.signal( +            self._signaler.PROV_GET_SUPPORTED_SERVICES, services) + +    def get_all_services(self, providers): +        """ +        Signal a list of services provided by all the configured providers. + +        :param providers: the list of providers to get the services. +        :type providers: list + +        Signals: +            prov_get_all_services -> list of unicode +        """ +        services_all = set() + +        for domain in providers: +            services = self._get_services(domain) +            services_all = services_all.union(set(services)) + +        self._signaler.signal( +            self._signaler.PROV_GET_ALL_SERVICES, services_all) + +    def get_details(self, domain, lang=None): +        """ +        Signal a ProviderConfigLight object with the current ProviderConfig +        settings. + +        :param domain: the domain name of the provider. +        :type domain: str +        :param lang: the language to use for localized strings. +        :type lang: str + +        Signals: +            prov_get_details -> ProviderConfigLight +        """ +        self._signaler.signal( +            self._signaler.PROV_GET_DETAILS, +            self._provider_config.get_light_config(domain, lang)) +  class Register(object):      """ @@ -926,6 +970,10 @@ class Signaler(QtCore.QObject):      prov_unsupported_client = QtCore.Signal(object)      prov_unsupported_api = QtCore.Signal(object) +    prov_get_all_services = QtCore.Signal(object) +    prov_get_supported_services = QtCore.Signal(object) +    prov_get_details = QtCore.Signal(object) +      prov_cancelled_setup = QtCore.Signal(object)      # Signals for SRPRegister @@ -1021,6 +1069,9 @@ class Signaler(QtCore.QObject):      PROV_UNSUPPORTED_CLIENT = "prov_unsupported_client"      PROV_UNSUPPORTED_API = "prov_unsupported_api"      PROV_CANCELLED_SETUP = "prov_cancelled_setup" +    PROV_GET_ALL_SERVICES = "prov_get_all_services" +    PROV_GET_SUPPORTED_SERVICES = "prov_get_supported_services" +    PROV_GET_DETAILS = "prov_get_details"      SRP_REGISTRATION_FINISHED = "srp_registration_finished"      SRP_REGISTRATION_FAILED = "srp_registration_failed" @@ -1106,6 +1157,9 @@ class Signaler(QtCore.QObject):              self.PROV_UNSUPPORTED_CLIENT,              self.PROV_UNSUPPORTED_API,              self.PROV_CANCELLED_SETUP, +            self.PROV_GET_ALL_SERVICES, +            self.PROV_GET_SUPPORTED_SERVICES, +            self.PROV_GET_DETAILS,              self.SRP_REGISTRATION_FINISHED,              self.SRP_REGISTRATION_FAILED, @@ -1393,6 +1447,47 @@ class Backend(object):          """          self._call_queue.put(("provider", "bootstrap", None, provider)) +    def provider_get_supported_services(self, domain): +        """ +        Signal a list of supported services provided by the given provider. + +        :param domain: the provider to get the services from. +        :type domain: str + +        Signals: +            prov_get_supported_services -> list of unicode +        """ +        self._call_queue.put(("provider", "get_supported_services", None, +                              domain)) + +    def provider_get_all_services(self, providers): +        """ +        Signal a list of services provided by all the configured providers. + +        :param providers: the list of providers to get the services. +        :type providers: list + +        Signals: +            prov_get_all_services -> list of unicode +        """ +        self._call_queue.put(("provider", "get_all_services", None, +                              providers)) + +    def provider_get_details(self, domain, lang): +        """ +        Signal a ProviderConfigLight object with the current ProviderConfig +        settings. + +        :param domain: the domain name of the provider. +        :type domain: str +        :param lang: the language to use for localized strings. +        :type lang: str + +        Signals: +            prov_get_details -> ProviderConfigLight +        """ +        self._call_queue.put(("provider", "get_details", None, domain, lang)) +      def user_register(self, provider, username, password):          """          Register a user using the domain and password given as parameters. @@ -1698,16 +1793,6 @@ class Backend(object):      # XXX HACK: this section is meant to be a place to hold methods and      # variables needed in the meantime while we migrate all to the backend. -    def get_provider_config(self): -        # TODO: refactor the provider config into a singleton/global loading it -        # every time from the file. -        provider_config = self._components["provider"]._provider_config -        return provider_config - -    def get_soledad(self): -        soledad = self._components["soledad"]._soledad_bootstrapper._soledad -        return soledad -      def get_keymanager(self):          km = self._components["soledad"]._soledad_bootstrapper._keymanager          return km diff --git a/src/leap/bitmask/config/providerconfig.py b/src/leap/bitmask/config/providerconfig.py index b411c6f3..cf31b3b2 100644 --- a/src/leap/bitmask/config/providerconfig.py +++ b/src/leap/bitmask/config/providerconfig.py @@ -38,6 +38,35 @@ class MissingCACert(Exception):      pass +class ProviderConfigLight(object): +    """ +    A light config object to hold some provider settings needed by the GUI. +    """ +    def __init__(self): +        """ +        Define the public attributes. +        """ +        self.domain = "" +        self.name = "" +        self.description = "" +        self.enrollment_policy = "" +        self.services = [] + +    @property +    def services_string(self): +        """ +        Return a comma separated list of serices provided by this provider. + +        :rtype: str +        """ +        services = [] +        for service in self.services: +            services.append(get_service_display_name(service)) + +        services_str = ", ".join(services) +        return services_str + +  class ProviderConfig(BaseConfig):      """      Provider configuration abstraction class @@ -45,6 +74,29 @@ class ProviderConfig(BaseConfig):      def __init__(self):          BaseConfig.__init__(self) +    def get_light_config(self, domain, lang=None): +        """ +        Return a ProviderConfigLight object with the data for the loaded +        object. + +        :param domain: the domain name of the provider. +        :type domain: str +        :param lang: the language to use for localized strings. +        :type lang: str + +        :rtype: ProviderConfigLight or None if the ProviderConfig isn't loaded. +        """ +        config = self.get_provider_config(domain) +        details = ProviderConfigLight() + +        details.domain = config.get_domain() +        details.name = config.get_name(lang=lang) +        details.description = config.get_description(lang=lang) +        details.enrollment_policy = config.get_enrollment_policy() +        details.services = config.get_services() + +        return details +      @classmethod      def get_provider_config(self, domain):          """ @@ -144,18 +196,6 @@ class ProviderConfig(BaseConfig):          services = self._safe_get_value("services")          return services -    def get_services_string(self): -        """ -        Returns a string with the available services in the current -        provider, ready to be shown to the user. -        """ -        services = [] -        for service in self.get_services(): -            services.append(get_service_display_name(service)) - -        services_str = ", ".join(services) -        return services_str -      def get_ca_cert_path(self, about_to_download=False):          """          Returns the path to the certificate for the current provider. diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 201a24ec..4d79305e 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -30,7 +30,6 @@ from leap.bitmask import __version__ as VERSION  from leap.bitmask import __version_hash__ as VERSION_HASH  from leap.bitmask.config import flags  from leap.bitmask.config.leapsettings import LeapSettings -from leap.bitmask.config.providerconfig import ProviderConfig  from leap.bitmask.gui import statemachines  from leap.bitmask.gui.advanced_key_management import AdvancedKeyManagement @@ -43,7 +42,6 @@ from leap.bitmask.gui.preferenceswindow import PreferencesWindow  from leap.bitmask.gui.systray import SysTray  from leap.bitmask.gui.wizard import Wizard -from leap.bitmask import provider  from leap.bitmask.platform_init import IS_WIN, IS_MAC, IS_LINUX  from leap.bitmask.platform_init.initializers import init_platform @@ -64,7 +62,6 @@ if IS_WIN:      from leap.bitmask.platform_init.locks import WindowsLock      from leap.bitmask.platform_init.locks import raise_window_ack -from leap.common.check import leap_assert  from leap.common.events import register  from leap.common.events import events_pb2 as proto @@ -178,15 +175,6 @@ class MainWindow(QtGui.QMainWindow):          self._trying_to_start_eip = False -        # This is loaded only once, there's a bug when doing that more -        # than once -        # XXX HACK!! But we need it as long as we are using -        # provider_config in here -        self._provider_config = self._backend.get_provider_config() - -        # Used for automatic start of EIP -        self._provisional_provider_config = ProviderConfig() -          self._already_started_eip = False          self._soledad_started = False @@ -247,6 +235,8 @@ class MainWindow(QtGui.QMainWindow):          self._ui_mx_visible = True          self._ui_eip_visible = True +        self._provider_details = None +          # last minute UI manipulations          self._center_window() @@ -383,6 +373,9 @@ class MainWindow(QtGui.QMainWindow):          self._connect_and_track(sig.prov_cancelled_setup,                                  self._set_login_cancelled) +        self._connect_and_track(sig.prov_get_details, +                                self._provider_get_details) +          # Login signals          self._connect_and_track(sig.srp_auth_ok, self._authentication_finished) @@ -430,9 +423,14 @@ class MainWindow(QtGui.QMainWindow):          sig.backend_bad_call.connect(self._backend_bad_call) +        sig.prov_check_api_certificate.connect(self._get_provider_details) +          sig.prov_unsupported_client.connect(self._needs_update)          sig.prov_unsupported_api.connect(self._incompatible_api) +        sig.prov_get_all_services.connect( +            self._provider_get_all_services) +          # EIP start signals          sig.eip_openvpn_already_running.connect(              self._on_eip_openvpn_already_running) @@ -597,12 +595,13 @@ class MainWindow(QtGui.QMainWindow):          domain = self._login_widget.get_selected_provider()          logged_user = "{0}@{1}".format(self._logged_user, domain) -        has_mx = True -        if self._logged_user is not None: -            provider_config = self._get_best_provider_config() -            has_mx = provider_config.provides_mx() +        details = self._provider_details +        mx_provided = False +        if details is not None: +            mx_provided = MX_SERVICE in details -        akm = AdvancedKeyManagement(self, has_mx, logged_user, +        # XXX: handle differently not logged in user? +        akm = AdvancedKeyManagement(self, mx_provided, logged_user,                                      self._keymanager, self._soledad_started)          akm.show() @@ -618,8 +617,7 @@ class MainWindow(QtGui.QMainWindow):          user = self._login_widget.get_user()          prov = self._login_widget.get_selected_provider()          preferences = PreferencesWindow( -            self, self._backend, self._provider_config, -            self._soledad_started, user, prov) +            self, self._backend, self._soledad_started, user, prov)          self.soledad_ready.connect(preferences.set_soledad_ready)          preferences.show() @@ -857,16 +855,9 @@ class MainWindow(QtGui.QMainWindow):          """          providers = self._settings.get_configured_providers() -        services = set() - -        for prov in providers: -            provider_config = ProviderConfig() -            loaded = provider_config.load( -                provider.get_provider_path(prov)) -            if loaded: -                for service in provider_config.get_services(): -                    services.add(service) +        self._backend.provider_get_all_services(providers) +    def _provider_get_all_services(self, services):          self._set_eip_visible(EIP_SERVICE in services)          self._set_mx_visible(MX_SERVICE in services) @@ -904,14 +895,11 @@ class MainWindow(QtGui.QMainWindow):          """          Set the login label to reflect offline status.          """ -        if self._logged_in_offline: -            provider = "" -        else: +        provider = "" +        if not self._logged_in_offline:              provider = self.ui.lblLoginProvider.text() -        self.ui.lblLoginProvider.setText( -            provider + -            self.tr(" (offline mode)")) +        self.ui.lblLoginProvider.setText(provider + self.tr(" (offline mode)"))      #      # systray @@ -1165,9 +1153,8 @@ class MainWindow(QtGui.QMainWindow):          provider configuration if it's not present, otherwise will          emit the corresponding signals inmediately          """ -        # XXX should rename this provider, name clash. -        provider = self._login_widget.get_selected_provider() -        self._backend.provider_setup(provider) +        domain = self._login_widget.get_selected_provider() +        self._backend.provider_setup(domain)      @QtCore.Slot(dict)      def _load_provider_config(self, data): @@ -1175,12 +1162,11 @@ class MainWindow(QtGui.QMainWindow):          TRIGGERS:              self._backend.signaler.prov_download_provider_info -        Once the provider config has been downloaded, this loads the -        self._provider_config instance with it and starts the second -        part of the bootstrapping sequence +        Once the provider config has been downloaded, start the second +        part of the bootstrapping sequence.          :param data: result from the last stage of the -                     run_provider_select_checks +                     backend.provider_setup()          :type data: dict          """          if data[self._backend.PASSED_KEY]: @@ -1222,7 +1208,6 @@ class MainWindow(QtGui.QMainWindow):              self._set_label_offline()              self.offline_mode_bypass_login.emit()          else: -            leap_assert(self._provider_config, "We need a provider config")              self.ui.action_create_new_account.setEnabled(False)              if self._login_widget.start_login():                  self._download_provider_config() @@ -1290,15 +1275,13 @@ class MainWindow(QtGui.QMainWindow):          Once the provider configuration is loaded, this starts the SRP          authentication          """ -        leap_assert(self._provider_config, "We need a provider config!") -          if data[self._backend.PASSED_KEY]:              username = self._login_widget.get_user()              password = self._login_widget.get_password()              self._show_hide_unsupported_services() -            domain = self._provider_config.get_domain() +            domain = self._login_widget.get_selected_provider()              self._backend.user_login(domain, username, password)          else:              logger.error(data[self._backend.ERROR_KEY]) @@ -1317,7 +1300,7 @@ class MainWindow(QtGui.QMainWindow):          self._logged_user = self._login_widget.get_user()          user = self._logged_user -        domain = self._provider_config.get_domain() +        domain = self._login_widget.get_selected_provider()          full_user_id = make_address(user, domain)          self._mail_conductor.userid = full_user_id          self._start_eip_bootstrap() @@ -1331,7 +1314,7 @@ class MainWindow(QtGui.QMainWindow):              sig.soledad_bootstrap_failed.connect(lambda: btn_enabled(True))              sig.soledad_bootstrap_finished.connect(lambda: btn_enabled(True)) -        if not self._get_best_provider_config().provides_mx(): +        if not MX_SERVICE in self._provider_details.services:              self._set_mx_visible(False)      def _start_eip_bootstrap(self): @@ -1341,11 +1324,10 @@ class MainWindow(QtGui.QMainWindow):          """          self._login_widget.logged_in() -        provider = self._provider_config.get_domain() -        self.ui.lblLoginProvider.setText(provider) +        domain = self._login_widget.get_selected_provider() +        self.ui.lblLoginProvider.setText(domain) -        self._enabled_services = self._settings.get_enabled_services( -            self._provider_config.get_domain()) +        self._enabled_services = self._settings.get_enabled_services(domain)          # TODO separate UI from logic.          if self._provides_mx_and_enabled(): @@ -1355,6 +1337,30 @@ class MainWindow(QtGui.QMainWindow):          self._maybe_start_eip() +    @QtCore.Slot() +    def _get_provider_details(self): +        """ +        TRIGGERS: +            prov_check_api_certificate + +        Set the attributes to know if the EIP and MX services are supported +        and enabled. +        This is triggered right after the provider has been set up. +        """ +        domain = self._login_widget.get_selected_provider() +        lang = QtCore.QLocale.system().name() +        self._backend.provider_get_details(domain, lang) + +    @QtCore.Slot() +    def _provider_get_details(self, details): +        """ +        Set the details for the just downloaded provider. + +        :param details: the details of the provider. +        :type details: ProviderConfigLight +        """ +        self._provider_details = details +      def _provides_mx_and_enabled(self):          """          Defines if the current provider provides mx and if we have it enabled. @@ -1362,9 +1368,15 @@ class MainWindow(QtGui.QMainWindow):          :returns: True if provides and is enabled, False otherwise          :rtype: bool          """ -        provider_config = self._get_best_provider_config() -        return (provider_config.provides_mx() and -                MX_SERVICE in self._enabled_services) +        domain = self._login_widget.get_selected_provider() +        enabled_services = self._settings.get_enabled_services(domain) + +        mx_enabled = MX_SERVICE in enabled_services +        mx_provided = False +        if self._provider_details is not None: +            mx_provided = MX_SERVICE in self._provider_details.services + +        return mx_enabled and mx_provided      def _provides_eip_and_enabled(self):          """ @@ -1373,16 +1385,23 @@ class MainWindow(QtGui.QMainWindow):          :returns: True if provides and is enabled, False otherwise          :rtype: bool          """ -        provider_config = self._get_best_provider_config() -        return (provider_config.provides_eip() and -                EIP_SERVICE in self._enabled_services) +        domain = self._login_widget.get_selected_provider() +        enabled_services = self._settings.get_enabled_services(domain) + +        eip_enabled = EIP_SERVICE in enabled_services +        eip_provided = False +        if self._provider_details is not None: +            eip_provided = EIP_SERVICE in self._provider_details.services + +        return eip_enabled and eip_provided      def _maybe_run_soledad_setup_checks(self):          """          Conditionally start Soledad.          """          # TODO split. -        if not self._provides_mx_and_enabled(): +        if not self._provides_mx_and_enabled() and not flags.OFFLINE: +            logger.debug("Does not provides and enabled MX")              return          username = self._login_widget.get_user() @@ -1390,9 +1409,6 @@ class MainWindow(QtGui.QMainWindow):          provider_domain = self._login_widget.get_selected_provider()          if flags.OFFLINE: -            self._provisional_provider_config.load( -                provider.get_provider_path(provider_domain)) -              full_user_id = make_address(username, provider_domain)              uuid = self._settings.get_uuid(full_user_id)              self._mail_conductor.userid = full_user_id @@ -1405,7 +1421,7 @@ class MainWindow(QtGui.QMainWindow):              self._backend.soledad_load_offline(full_user_id, password, uuid)          else:              if self._logged_user is not None: -                domain = self._provider_config.get_domain() +                domain = self._login_widget.get_selected_provider()                  self._backend.soledad_bootstrap(username, domain, password)      ################################################################### @@ -1457,19 +1473,8 @@ class MainWindow(QtGui.QMainWindow):          # TODO in the OFFLINE mode we should also modify the  rules          # in the mail state machine so it shows that imap is active          # (but not smtp since it's not yet ready for offline use) -        start_fun = self._mail_conductor.start_imap_service -        if flags.OFFLINE: -            provider_domain = self._login_widget.get_selected_provider() -            self._provider_config.load( -                provider.get_provider_path(provider_domain)) -        provides_mx = self._provider_config.provides_mx() - -        if flags.OFFLINE and provides_mx: -            start_fun() -            return - -        if self._provides_mx_and_enabled(): -            start_fun() +        if self._provides_mx_and_enabled() or flags.OFFLINE: +            self._mail_conductor.start_imap_service()      # end service control methods (imap) @@ -1519,9 +1524,7 @@ class MainWindow(QtGui.QMainWindow):          """          self._eip_connection.qtsigs.connected_signal.emit() -        provider_config = self._get_best_provider_config() -        domain = provider_config.get_domain() - +        domain = self._login_widget.get_selected_provider()          self._eip_status.set_provider(domain)          self._settings.set_defaultprovider(domain)          self._already_started_eip = True @@ -1582,19 +1585,8 @@ class MainWindow(QtGui.QMainWindow):          self._enabled_services = settings.get_enabled_services(              default_provider) -        loaded = self._provisional_provider_config.load( -            provider.get_provider_path(default_provider)) -        if loaded and settings.get_autostart_eip(): -            # XXX I think we should not try to re-download config every time, -            # it adds some delay. -            # Maybe if it's the first run in a session, -            # or we can try only if it fails. +        if settings.get_autostart_eip():              self._maybe_start_eip() -        elif settings.get_autostart_eip(): -            # XXX: Display a proper message to the user -            self.eip_needs_login.emit() -            logger.error("Unable to load %s config, cannot autostart." % -                         (default_provider,))      @QtCore.Slot()      def _start_EIP(self): @@ -1700,11 +1692,12 @@ class MainWindow(QtGui.QMainWindow):          logger.debug('Setting autostart to: False')          self._settings.set_autostart_eip(False) -        if self._logged_user: -            self._eip_status.set_provider( -                make_address( -                    self._logged_user, -                    self._get_best_provider_config().get_domain())) +        user = self._logged_user +        if user: +            domain = self._login_widget.get_selected_provider() +            full_user_id = make_address(user, domain) +            self._eip_status.set_provider(full_user_id) +          self._eip_status.eip_stopped()      @QtCore.Slot() @@ -1874,30 +1867,6 @@ class MainWindow(QtGui.QMainWindow):      # end of EIP methods --------------------------------------------- -    def _get_best_provider_config(self): -        """ -        Returns the best ProviderConfig to use at a moment. We may -        have to use self._provider_config or -        self._provisional_provider_config depending on the start -        status. - -        :rtype: ProviderConfig -        """ -        # TODO move this out of gui. -        leap_assert(self._provider_config is not None or -                    self._provisional_provider_config is not None, -                    "We need a provider config") - -        provider_config = None -        if self._provider_config.loaded(): -            provider_config = self._provider_config -        elif self._provisional_provider_config.loaded(): -            provider_config = self._provisional_provider_config -        else: -            leap_assert(False, "We could not find any usable ProviderConfig.") - -        return provider_config -      @QtCore.Slot()      def _logout(self):          """ diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py index 0a4c7f56..c67052f3 100644 --- a/src/leap/bitmask/gui/preferenceswindow.py +++ b/src/leap/bitmask/gui/preferenceswindow.py @@ -24,12 +24,9 @@ from functools import partial  from PySide import QtCore, QtGui -from leap.bitmask.provider import get_provider_path  from leap.bitmask.config.leapsettings import LeapSettings  from leap.bitmask.gui.ui_preferences import Ui_Preferences  from leap.bitmask.util.credentials import password_checks -from leap.bitmask.services import get_supported -from leap.bitmask.config.providerconfig import ProviderConfig  from leap.bitmask.services import get_service_display_name, MX_SERVICE  logger = logging.getLogger(__name__) @@ -41,15 +38,12 @@ class PreferencesWindow(QtGui.QDialog):      """      preferences_saved = QtCore.Signal() -    def __init__(self, parent, backend, provider_config, soledad_started, -                 username, domain): +    def __init__(self, parent, backend, soledad_started, username, domain):          """          :param parent: parent object of the PreferencesWindow.          :parent type: QWidget          :param backend: Backend being used          :type backend: Backend -        :param provider_config: ProviderConfig object. -        :type provider_config: ProviderConfig          :param soledad_started: whether soledad has started or not          :type soledad_started: bool          :param username: the user set in the login widget @@ -62,7 +56,6 @@ class PreferencesWindow(QtGui.QDialog):          self._backend = backend          self._settings = LeapSettings() -        self._provider_config = provider_config          self._soledad_started = soledad_started          self._username = username          self._domain = domain @@ -99,31 +92,7 @@ class PreferencesWindow(QtGui.QDialog):          Actions to perform is the user is logged in.          """ -        settings = self._settings -        pw_enabled = True - -        # check if provider has 'mx' ... -        # TODO: we should move this to the backend. -        if self._provider_config.provides_mx(): -            enabled_services = settings.get_enabled_services(self._domain) -            mx_name = get_service_display_name(MX_SERVICE) - -            # ... and if the user have it enabled -            if MX_SERVICE not in enabled_services: -                msg = self.tr("You need to enable {0} in order to change " -                              "the password.".format(mx_name)) -                self._set_password_change_status(msg, error=True) -                pw_enabled = False -            else: -                # check if Soledad is bootstrapped -                if not self._soledad_started: -                    msg = self.tr( -                        "You need to wait until {0} is ready in " -                        "order to change the password.".format(mx_name)) -                    self._set_password_change_status(msg) -                    pw_enabled = False - -        self.ui.gbPasswordChange.setEnabled(pw_enabled) +        self._backend.provider_provides_mx()      @QtCore.Slot()      def _not_logged_in(self): @@ -139,6 +108,44 @@ class PreferencesWindow(QtGui.QDialog):          self.ui.gbPasswordChange.setEnabled(False)      @QtCore.Slot() +    def _provides_mx(self): +        """ +        TRIGGERS: +            Signaler.prov_provides_mx + +        Actions to perform if the provider provides MX. +        """ +        pw_enabled = True +        enabled_services = self._settings.get_enabled_services(self._domain) +        mx_name = get_service_display_name(MX_SERVICE) + +        if MX_SERVICE not in enabled_services: +            msg = self.tr("You need to enable {0} in order to change " +                          "the password.".format(mx_name)) +            self._set_password_change_status(msg, error=True) +            pw_enabled = False +        else: +            # check if Soledad is bootstrapped +            if not self._soledad_started: +                msg = self.tr( +                    "You need to wait until {0} is ready in " +                    "order to change the password.".format(mx_name)) +                self._set_password_change_status(msg) +                pw_enabled = False + +        self.ui.gbPasswordChange.setEnabled(pw_enabled) + +    @QtCore.Slot() +    def _not_provides_mx(self): +        """ +        TRIGGERS: +            Signaler.prov_not_provides_mx + +        Actions to perform if the provider does not provides MX. +        """ +        self.ui.gbPasswordChange.setEnabled(False) + +    @QtCore.Slot()      def set_soledad_ready(self):          """          TRIGGERS: @@ -339,8 +346,7 @@ class PreferencesWindow(QtGui.QDialog):          TRIGGERS:              self.ui.cbProvidersServices.currentIndexChanged[unicode] -        Loads the services that the provider provides into the UI for -        the user to enable or disable. +        Fill the services list with the selected provider's services.          :param domain: the domain of the provider to load services from.          :type domain: str @@ -351,10 +357,6 @@ class PreferencesWindow(QtGui.QDialog):          if not domain:              return -        provider_config = self._get_provider_config(domain) -        if provider_config is None: -            return -          # set the proper connection for the 'save' button          try:              self.ui.pbSaveServices.clicked.disconnect() @@ -364,7 +366,21 @@ class PreferencesWindow(QtGui.QDialog):          save_services = partial(self._save_enabled_services, domain)          self.ui.pbSaveServices.clicked.connect(save_services) -        services = get_supported(provider_config.get_services()) +        self._backend.provider_get_supported_services(domain) + +    @QtCore.Slot(str) +    def _load_services(self, services): +        """ +        TRIGGERS: +            self.ui.cbProvidersServices.currentIndexChanged[unicode] + +        Loads the services that the provider provides into the UI for +        the user to enable or disable. + +        :param domain: the domain of the provider to load services from. +        :type domain: str +        """ +        domain = self.ui.cbProvidersServices.currentText()          services_conf = self._settings.get_enabled_services(domain)          # discard changes if other provider is selected @@ -412,27 +428,15 @@ class PreferencesWindow(QtGui.QDialog):          self._set_providers_services_status(msg, success=True)          self.preferences_saved.emit() -    def _get_provider_config(self, domain): -        """ -        Helper to return a valid Provider Config from the domain name. - -        :param domain: the domain name of the provider. -        :type domain: str - -        :rtype: ProviderConfig or None if there is a problem loading the config -        """ -        provider_config = ProviderConfig() -        if not provider_config.load(get_provider_path(domain)): -            provider_config = None - -        return provider_config -      def _backend_connect(self):          """          Helper to connect to backend signals          """          sig = self._backend.signaler +        sig.prov_provides_mx.connect(self._provides_mx) +        sig.prov_get_supported_services.connect(self._load_services) +          sig.srp_status_logged_in.connect(self._is_logged_in)          sig.srp_status_not_logged_in.connect(self._not_logged_in) diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index ce45b431..4d774907 100644 --- a/src/leap/bitmask/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -26,8 +26,6 @@ from PySide import QtCore, QtGui  from leap.bitmask.config import flags  from leap.bitmask.config.leapsettings import LeapSettings -from leap.bitmask.config.providerconfig import ProviderConfig -from leap.bitmask.provider import get_provider_path  from leap.bitmask.services import get_service_display_name, get_supported  from leap.bitmask.util.credentials import password_checks, username_checks  from leap.bitmask.util.credentials import USERNAME_REGEX @@ -88,10 +86,9 @@ class Wizard(QtGui.QWizard):          self._backend_connect()          self._domain = None -        # HACK!! We need provider_config for the time being, it'll be -        # removed -        self._provider_config = ( -            self._backend._components["provider"]._provider_config) + +        # this details are set when the provider download is complete. +        self._provider_details = None          # We will store a reference to the defers for eventual use          # (eg, to cancel them) but not doing anything with them right now. @@ -513,10 +510,12 @@ class Wizard(QtGui.QWizard):          check. Since this check is the last of this set, it also          completes the page if passed          """ -        if self._provider_config.load(get_provider_path(self._domain)): +        if data[self._backend.PASSED_KEY]:              self._complete_task(data, self.ui.lblProviderInfo,                                  True, self.SELECT_PROVIDER_PAGE)              self._provider_checks_ok = True +            lang = QtCore.QLocale.system().name() +            self._backend.provider_get_details(self._domain, lang)          else:              new_data = {                  self._backend.PASSED_KEY: False, @@ -538,6 +537,16 @@ class Wizard(QtGui.QWizard):          else:              self.ui.cbProviders.setEnabled(True) +    @QtCore.Slot() +    def _provider_get_details(self, details): +        """ +        Set the details for the just downloaded provider. + +        :param details: the details of the provider. +        :type details: ProviderConfigLight +        """ +        self._provider_details = details +      @QtCore.Slot(dict)      def _download_ca_cert(self, data):          """ @@ -605,11 +614,9 @@ class Wizard(QtGui.QWizard):          the user to enable or disable.          """          self.ui.grpServices.setTitle( -            self.tr("Services by %s") % -            (self._provider_config.get_name(),)) +            self.tr("Services by {0}").format(self._provider_details.name)) -        services = get_supported( -            self._provider_config.get_services()) +        services = get_supported(self._provider_details.services)          for service in services:              try: @@ -652,38 +659,31 @@ class Wizard(QtGui.QWizard):              if not self._provider_setup_ok:                  self._reset_provider_setup()                  sub_title = self.tr("Gathering configuration options for {0}") -                sub_title = sub_title.format(self._provider_config.get_name()) +                sub_title = sub_title.format(self._provider_details.name)                  self.page(pageId).setSubTitle(sub_title)                  self.ui.lblDownloadCaCert.setPixmap(self.QUESTION_ICON)                  self._provider_setup_defer = self._backend.\                      provider_bootstrap(self._domain)          if pageId == self.PRESENT_PROVIDER_PAGE: -            self.page(pageId).setSubTitle(self.tr("Description of services " -                                                  "offered by %s") % -                                          (self._provider_config -                                           .get_name(),)) - -            lang = QtCore.QLocale.system().name() -            self.ui.lblProviderName.setText( -                "<b>%s</b>" % -                (self._provider_config.get_name(lang=lang),)) -            self.ui.lblProviderURL.setText( -                "https://%s" % (self._provider_config.get_domain(),)) -            self.ui.lblProviderDesc.setText( -                "<i>%s</i>" % -                (self._provider_config.get_description(lang=lang),)) - -            self.ui.lblServicesOffered.setText(self._provider_config -                                               .get_services_string()) -            self.ui.lblProviderPolicy.setText(self._provider_config -                                              .get_enrollment_policy()) +            sub_title = self.tr("Description of services offered by {0}") +            sub_title = sub_title.format(self._provider_details.name) +            self.page(pageId).setSubTitle(sub_title) + +            details = self._provider_details +            name = "<b>{0}</b>".format(details.name) +            domain = "https://{0}".format(details.domain) +            description = "<i>{0}</i>".format(details.description) +            self.ui.lblProviderName.setText(name) +            self.ui.lblProviderURL.setText(domain) +            self.ui.lblProviderDesc.setText(description) +            self.ui.lblServicesOffered.setText(details.services_string) +            self.ui.lblProviderPolicy.setText(details.enrollment_policy)          if pageId == self.REGISTER_USER_PAGE: -            self.page(pageId).setSubTitle(self.tr("Register a new user with " -                                                  "%s") % -                                          (self._provider_config -                                           .get_name(),)) +            sub_title = self.tr("Register a new user with {0}") +            sub_title = sub_title.format(self._provider_details.name) +            self.page(pageId).setSubTitle(sub_title)              self.ui.chkRemember.setVisible(False)          if pageId == self.SERVICES_PAGE: @@ -706,8 +706,6 @@ class Wizard(QtGui.QWizard):          if self.currentPage() == self.page(self.SELECT_PROVIDER_PAGE):              if self._use_existing_provider:                  self._domain = self.ui.cbProviders.currentText() -                self._provider_config = ProviderConfig.get_provider_config( -                    self._domain)                  if self._show_register:                      return self.REGISTER_USER_PAGE                  else: @@ -732,6 +730,7 @@ class Wizard(QtGui.QWizard):          sig.prov_name_resolution.connect(self._name_resolution)          sig.prov_https_connection.connect(self._https_connection)          sig.prov_download_provider_info.connect(self._download_provider_info) +        sig.prov_get_details.connect(self._provider_get_details)          sig.prov_download_ca_cert.connect(self._download_ca_cert)          sig.prov_check_ca_fingerprint.connect(self._check_ca_fingerprint) diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index 2bdad7e2..db12fd80 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -188,8 +188,9 @@ class SoledadBootstrapper(AbstractBootstrapper):          try:              self.load_and_sync_soledad(uuid, offline=True)              self._signaler.signal(self._signaler.SOLEDAD_OFFLINE_FINISHED) -        except Exception: +        except Exception as e:              # TODO: we should handle more specific exceptions in here +            logger.exception(e)              self._signaler.signal(self._signaler.SOLEDAD_OFFLINE_FAILED)      def _get_soledad_local_params(self, uuid, offline=False): | 
