diff options
| -rw-r--r-- | changes/bug-3294_improve-add-missing-files | 1 | ||||
| -rw-r--r-- | changes/bug-3319_change-log-out-texts | 1 | ||||
| -rw-r--r-- | changes/bug_3274-fix-negative-rates | 1 | ||||
| -rw-r--r-- | changes/bug_always_raise_when_visible | 1 | ||||
| -rw-r--r-- | changes/bug_regex_username | 2 | ||||
| -rw-r--r-- | changes/feature_reintegrate_smtp | 1 | ||||
| -rw-r--r-- | changes/improve_displayed_error_messages | 2 | ||||
| -rw-r--r-- | src/leap/config/tests/test_providerconfig.py | 4 | ||||
| -rw-r--r-- | src/leap/gui/login.py | 8 | ||||
| -rw-r--r-- | src/leap/gui/mainwindow.py | 45 | ||||
| -rw-r--r-- | src/leap/gui/statuspanel.py | 5 | ||||
| -rw-r--r-- | src/leap/gui/ui/mainwindow.ui | 8 | ||||
| -rw-r--r-- | src/leap/gui/ui/wizard.ui | 2 | ||||
| -rw-r--r-- | src/leap/platform_init/initializers.py | 35 | ||||
| -rw-r--r-- | src/leap/services/__init__.py | 2 | ||||
| -rw-r--r-- | src/leap/services/eip/vpnlaunchers.py | 2 | ||||
| -rw-r--r-- | src/leap/services/soledad/soledadbootstrapper.py | 2 | 
17 files changed, 88 insertions, 34 deletions
| diff --git a/changes/bug-3294_improve-add-missing-files b/changes/bug-3294_improve-add-missing-files new file mode 100644 index 00000000..ff1f0723 --- /dev/null +++ b/changes/bug-3294_improve-add-missing-files @@ -0,0 +1 @@ +  o Add missing files does not stop if a command fails, also warns the user if there was an error. Closes #3294. diff --git a/changes/bug-3319_change-log-out-texts b/changes/bug-3319_change-log-out-texts new file mode 100644 index 00000000..ffe1cef8 --- /dev/null +++ b/changes/bug-3319_change-log-out-texts @@ -0,0 +1 @@ +  o Replace 'Sign Out' with 'Log Out' and 'User' with 'Username'. Closes #3319. diff --git a/changes/bug_3274-fix-negative-rates b/changes/bug_3274-fix-negative-rates new file mode 100644 index 00000000..78df7a4f --- /dev/null +++ b/changes/bug_3274-fix-negative-rates @@ -0,0 +1 @@ +  o Bugfix, avoid getting negative rates. Closes #3274. diff --git a/changes/bug_always_raise_when_visible b/changes/bug_always_raise_when_visible new file mode 100644 index 00000000..21610bf2 --- /dev/null +++ b/changes/bug_always_raise_when_visible @@ -0,0 +1 @@ +  o Raise window when setting it as visible. Fixes #3374
\ No newline at end of file diff --git a/changes/bug_regex_username b/changes/bug_regex_username new file mode 100644 index 00000000..9de9f2d1 --- /dev/null +++ b/changes/bug_regex_username @@ -0,0 +1,2 @@ +  o Validate the username in the login form against the same regexp as +    the wizard registration form. Fixes #3214.
\ No newline at end of file diff --git a/changes/feature_reintegrate_smtp b/changes/feature_reintegrate_smtp new file mode 100644 index 00000000..3466dc57 --- /dev/null +++ b/changes/feature_reintegrate_smtp @@ -0,0 +1 @@ +  o Reintegrate SMTP relay module. Closes #3375
\ No newline at end of file diff --git a/changes/improve_displayed_error_messages b/changes/improve_displayed_error_messages new file mode 100644 index 00000000..90f8b7ff --- /dev/null +++ b/changes/improve_displayed_error_messages @@ -0,0 +1,2 @@ +  o Display a more generic error message in the main window, and leave +    the detailed one for the log. Closes #3373.
\ No newline at end of file diff --git a/src/leap/config/tests/test_providerconfig.py b/src/leap/config/tests/test_providerconfig.py index 4e86a5f7..ff2828e6 100644 --- a/src/leap/config/tests/test_providerconfig.py +++ b/src/leap/config/tests/test_providerconfig.py @@ -28,7 +28,7 @@ import json  import copy  from leap.common.testing.basetest import BaseLeapTest -from leap.config.providerconfig import ProviderConfig +from leap.config.providerconfig import ProviderConfig, MissingCACert  from leap.services import get_supported  from mock import Mock @@ -209,7 +209,7 @@ class ProviderConfigTest(BaseLeapTest):          provider_domain = 'test.provider.com'          pc.get_domain = Mock(return_value=provider_domain) -        with self.assertRaises(AssertionError): +        with self.assertRaises(MissingCACert):              pc.get_ca_cert_path()      def test_provides_eip(self): diff --git a/src/leap/gui/login.py b/src/leap/gui/login.py index 3eb1fe39..3c994597 100644 --- a/src/leap/gui/login.py +++ b/src/leap/gui/login.py @@ -44,6 +44,8 @@ class LoginWidget(QtGui.QWidget):      MAX_STATUS_WIDTH = 40 +    BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$" +      def __init__(self, settings, parent=None):          """          Constructs the LoginWidget. @@ -77,6 +79,10 @@ class LoginWidget(QtGui.QWidget):          self.ui.btnCreateAccount.clicked.connect(              self.show_wizard) +        username_re = QtCore.QRegExp(self.BARE_USERNAME_REGEX) +        self.ui.lnUser.setValidator( +            QtGui.QRegExpValidator(username_re, self)) +      def _remember_state_changed(self, state):          """          Saves the remember state in the LeapSettings @@ -146,7 +152,7 @@ class LoginWidget(QtGui.QWidget):      def get_user(self):          """ -        Returns the user that appears in the widget +        Returns the user that appears in the widget.          :rtype: str          """ diff --git a/src/leap/gui/mainwindow.py b/src/leap/gui/mainwindow.py index ed0d4652..87dd4f5c 100644 --- a/src/leap/gui/mainwindow.py +++ b/src/leap/gui/mainwindow.py @@ -218,8 +218,8 @@ class MainWindow(QtGui.QMainWindow):          self._vpn.qtsigs.process_finished.connect(              self._eip_finished) -        self.ui.action_sign_out.setEnabled(False) -        self.ui.action_sign_out.triggered.connect(self._logout) +        self.ui.action_log_out.setEnabled(False) +        self.ui.action_log_out.triggered.connect(self._logout)          self.ui.action_about_leap.triggered.connect(self._about)          self.ui.action_quit.triggered.connect(self.quit)          self.ui.action_wizard.triggered.connect(self._launch_wizard) @@ -563,7 +563,7 @@ class MainWindow(QtGui.QMainWindow):          systrayMenu.addAction(preferences_action)          systrayMenu.addAction(help_action)          systrayMenu.addSeparator() -        systrayMenu.addAction(self.ui.action_sign_out) +        systrayMenu.addAction(self.ui.action_log_out)          systrayMenu.addAction(self.ui.action_quit)          self._systray = QtGui.QSystemTrayIcon(self)          self._systray.setContextMenu(systrayMenu) @@ -603,7 +603,11 @@ class MainWindow(QtGui.QMainWindow):          Toggles the window visibility          """ -        self.setVisible(not self.isVisible()) +        if not self.isVisible(): +            self.show() +            self.raise_() +        else: +            self.hide()      def _center_window(self):          """ @@ -745,11 +749,13 @@ class MainWindow(QtGui.QMainWindow):                      download_if_needed=True)              else:                  self._login_widget.set_status( -                    self.tr("Could not load provider configuration.")) +                    self.tr("Unable to login: Problem with provider")) +                logger.error("Could not load provider configuration.")                  self._login_widget.set_enabled(True)          else:              self._login_widget.set_status( -                data[self._provider_bootstrapper.ERROR_KEY]) +                self.tr("Unable to login: Problem with provider")) +            logger.error(data[self._provider_bootstrapper.ERROR_KEY])              self._login_widget.set_enabled(True)      def _login(self): @@ -852,7 +858,8 @@ class MainWindow(QtGui.QMainWindow):              self._login_defer = self._srp_auth.authenticate(username, password)          else:              self._login_widget.set_status( -                data[self._provider_bootstrapper.ERROR_KEY]) +                "Unable to login: Problem with provider") +            logger.error(data[self._provider_bootstrapper.ERROR_KEY])              self._login_widget.set_enabled(True)      def _authentication_finished(self, ok, message): @@ -863,10 +870,16 @@ class MainWindow(QtGui.QMainWindow):          Once the user is properly authenticated, try starting the EIP          service          """ + +        # In general we want to "filter" likely complicated error +        # messages, but in this case, the messages make more sense as +        # they come. Since they are "Unknown user" or "Unknown +        # password"          self._login_widget.set_status(message, error=not ok) +          if ok:              self._logged_user = self._login_widget.get_user() -            self.ui.action_sign_out.setEnabled(True) +            self.ui.action_log_out.setEnabled(True)              # We leave a bit of room for the user to see the              # "Succeeded" message and then we switch to the EIP status              # panel @@ -983,12 +996,14 @@ class MainWindow(QtGui.QMainWindow):                  # TODO: Make the encrypted_only configurable                  from leap.mail.smtp import setup_smtp_relay +                client_cert = self._eip_config.get_client_cert_path( +                    self._provider_config)                  setup_smtp_relay(port=1234,                                   keymanager=self._keymanager,                                   smtp_host=host,                                   smtp_port=port, -                                 smtp_username=".", -                                 smtp_password=".", +                                 smtp_cert=client_cert, +                                 smtp_key=client_cert,                                   encrypted_only=False)      def _get_socket_host(self): @@ -1234,7 +1249,7 @@ class MainWindow(QtGui.QMainWindow):      def _logout(self):          """          SLOT -        TRIGGER: self.ui.action_sign_out.triggered +        TRIGGER: self.ui.action_log_out.triggered          Starts the logout sequence          """ @@ -1251,7 +1266,7 @@ class MainWindow(QtGui.QMainWindow):          logging out          """          self._logged_user = None -        self.ui.action_sign_out.setEnabled(False) +        self.ui.action_log_out.setEnabled(False)          self.ui.stackedWidget.setCurrentIndex(self.LOGIN_INDEX)          self._login_widget.set_password("")          self._login_widget.set_enabled(True) @@ -1275,7 +1290,8 @@ class MainWindow(QtGui.QMainWindow):              self._login_widget.set_cancel(False)              self._login_widget.set_enabled(True)              self._login_widget.set_status( -                data[self._provider_bootstrapper.ERROR_KEY]) +                self.tr("Unable to connect: Problem with provider")) +            logger.error(data[self._provider_bootstrapper.ERROR_KEY])      def _eip_intermediate_stage(self, data):          """ @@ -1290,7 +1306,8 @@ class MainWindow(QtGui.QMainWindow):          passed = data[self._provider_bootstrapper.PASSED_KEY]          if not passed:              self._login_widget.set_status( -                data[self._provider_bootstrapper.ERROR_KEY]) +                self.tr("Unable to connect: Problem with provider")) +            logger.error(data[self._provider_bootstrapper.ERROR_KEY])              self._already_started_eip = False      def _eip_finished(self, exitCode): diff --git a/src/leap/gui/statuspanel.py b/src/leap/gui/statuspanel.py index 7c824e01..f3424c7c 100644 --- a/src/leap/gui/statuspanel.py +++ b/src/leap/gui/statuspanel.py @@ -86,6 +86,11 @@ class RateMovingAverage(object):              rate = float(deltatraffic) / float(deltat) / 1024          except ZeroDivisionError:              rate = 0 + +        # In some cases we get negative rates +        if rate < 0: +            rate = 0 +          return rate      def get_total(self): diff --git a/src/leap/gui/ui/mainwindow.ui b/src/leap/gui/ui/mainwindow.ui index 58827fe0..67d78736 100644 --- a/src/leap/gui/ui/mainwindow.ui +++ b/src/leap/gui/ui/mainwindow.ui @@ -253,14 +253,14 @@       <x>0</x>       <y>0</y>       <width>429</width> -     <height>25</height> +     <height>21</height>      </rect>     </property>     <widget class="QMenu" name="menuSession">      <property name="title">       <string>&Session</string>      </property> -    <addaction name="action_sign_out"/> +    <addaction name="action_log_out"/>      <addaction name="separator"/>      <addaction name="action_quit"/>     </widget> @@ -276,9 +276,9 @@     <addaction name="menuHelp"/>    </widget>    <widget class="QStatusBar" name="statusbar"/> -  <action name="action_sign_out"> +  <action name="action_log_out">     <property name="text"> -    <string>&Sign out</string> +    <string>Log &out</string>     </property>    </action>    <action name="action_quit"> diff --git a/src/leap/gui/ui/wizard.ui b/src/leap/gui/ui/wizard.ui index 4b9cab1c..d8acd69a 100644 --- a/src/leap/gui/ui/wizard.ui +++ b/src/leap/gui/ui/wizard.ui @@ -668,7 +668,7 @@      <item row="2" column="0">       <widget class="QLabel" name="label_15">        <property name="text"> -       <string><b>User:</b></string> +       <string><b>Username:</b></string>        </property>        <property name="alignment">         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> diff --git a/src/leap/platform_init/initializers.py b/src/leap/platform_init/initializers.py index 3523c117..cc5f6e87 100644 --- a/src/leap/platform_init/initializers.py +++ b/src/leap/platform_init/initializers.py @@ -122,10 +122,15 @@ def check_missing():                  logger.warning(                      "Installer not found for platform %s." % (_system,))                  return -            install_missing_fun( -                # XXX maybe move constants to fun -                UPDOWN_BADEXEC_MSG, -                UPDOWN_NOTFOUND_MSG) + +            # XXX maybe move constants to fun +            ok = install_missing_fun(UPDOWN_BADEXEC_MSG, UPDOWN_NOTFOUND_MSG) +            if not ok: +                msg = QtGui.QMessageBox() +                msg.setWindowTitle(msg.tr("Problem installing files")) +                msg.setText(msg.tr('Some of the files could not be copied.')) +                msg.setIcon(QtGui.QMessageBox.Warning) +                msg.exec_()          elif ret == QtGui.QMessageBox.No:              logger.debug("Not installing missing scripts, " @@ -235,9 +240,12 @@ def _darwin_install_missing_scripts(badexec, notfound):      :type badexec: str      :param notfound: error for notifying missing path.      :type notfound: str +    :returns: True if the files could be copied successfully. +    :rtype: bool      """      # We expect to execute this from some way of bundle, since      # the up/down scripts should be put in place by the installer. +    success = False      installer_path = os.path.join(          os.getcwd(),          "..", @@ -261,7 +269,9 @@ def _darwin_install_missing_scripts(badexec, notfound):              ret = subprocess.call(                  cmdline, stdout=subprocess.PIPE,                  shell=True) -            assert([ret])  # happy flakes +            success = ret == 0 +            if not success: +                logger.error("Install missing scripts failed.")          except Exception as exc:              logger.error(badexec)              logger.error("Error was: %r" % (exc,)) @@ -274,6 +284,8 @@ def _darwin_install_missing_scripts(badexec, notfound):          logger.error(notfound)          logger.debug('path searched: %s' % (installer_path,)) +    return success +  def DarwinInitializer():      """ @@ -339,10 +351,11 @@ def _linux_install_missing_scripts(badexec, notfound):      :type badexec: str      :param notfound: error for notifying missing path.      :type notfound: str +    :returns: True if the files could be copied successfully. +    :rtype: bool      """ -    installer_path = os.path.join( -        os.getcwd(), -        "apps", "eip", "files") +    success = False +    installer_path = os.path.join(os.getcwd(), "apps", "eip", "files")      launcher = vpnlaunchers.LinuxVPNLauncher      # XXX refactor with darwin, same block. @@ -370,7 +383,9 @@ def _linux_install_missing_scripts(badexec, notfound):              ret = subprocess.call(                  cmdline, stdout=subprocess.PIPE,                  shell=True) -            assert([ret])  # happy flakes +            success = ret == 0 +            if not success: +                logger.error("Install missing scripts failed.")          except Exception as exc:              logger.error(badexec)              logger.error("Error was: %r" % (exc,)) @@ -383,6 +398,8 @@ def _linux_install_missing_scripts(badexec, notfound):          logger.error(notfound)          logger.debug('path searched: %s' % (installer_path,)) +    return success +  def LinuxInitializer():      """ diff --git a/src/leap/services/__init__.py b/src/leap/services/__init__.py index fc4aa416..253359cd 100644 --- a/src/leap/services/__init__.py +++ b/src/leap/services/__init__.py @@ -17,7 +17,7 @@  """  Services module.  """ -DEPLOYED = ["openvpn"]  # for 0.2.2 release +DEPLOYED = ["openvpn", "mx"]  def get_supported(services): diff --git a/src/leap/services/eip/vpnlaunchers.py b/src/leap/services/eip/vpnlaunchers.py index b591b3ca..0151c1c6 100644 --- a/src/leap/services/eip/vpnlaunchers.py +++ b/src/leap/services/eip/vpnlaunchers.py @@ -292,7 +292,7 @@ class LinuxVPNLauncher(VPNLauncher):          """          to = kls.SYSTEM_CONFIG -        cmd = '#!/bin/sh\nset -e\n' +        cmd = '#!/bin/sh\n'          cmd += 'mkdir -p "%s"\n' % (to, )          cmd += 'cp "%s/%s" "%s"\n' % (frompath, kls.UP_DOWN_FILE, to)          cmd += 'cp "%s" "%s"\n' % (pol_file, kls.POLKIT_PATH) diff --git a/src/leap/services/soledad/soledadbootstrapper.py b/src/leap/services/soledad/soledadbootstrapper.py index f14e9e50..ac3243c1 100644 --- a/src/leap/services/soledad/soledadbootstrapper.py +++ b/src/leap/services/soledad/soledadbootstrapper.py @@ -192,7 +192,7 @@ class SoledadBootstrapper(AbstractBootstrapper):          srp_auth = SRPAuth(self._provider_config)          self._keymanager = KeyManager(              address, -            "https://%s:6425" % (self._provider_config.get_domain()), +            "https://nicknym.%s:6425" % (self._provider_config.get_domain(),),              self._soledad,              #token=srp_auth.get_token(),  # TODO: enable token usage              session_id=srp_auth.get_session_id(), | 
