diff options
| -rw-r--r-- | changes/feature_5191_handle-invalid-auth-token-error | 2 | ||||
| -rw-r--r-- | src/leap/bitmask/gui/mail_status.py | 38 | ||||
| -rw-r--r-- | src/leap/bitmask/gui/mainwindow.py | 2 | ||||
| -rw-r--r-- | src/leap/bitmask/services/mail/conductor.py | 2 | ||||
| -rw-r--r-- | src/leap/bitmask/services/mail/connection.py | 2 | ||||
| -rw-r--r-- | src/leap/bitmask/services/soledad/soledadbootstrapper.py | 18 | 
6 files changed, 56 insertions, 8 deletions
| diff --git a/changes/feature_5191_handle-invalid-auth-token-error b/changes/feature_5191_handle-invalid-auth-token-error new file mode 100644 index 00000000..6acdaad0 --- /dev/null +++ b/changes/feature_5191_handle-invalid-auth-token-error @@ -0,0 +1,2 @@ +- Handle invalid auth tokens when syncing Soledad, and show an error on the +  GUI (#5191). diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py index 8da26f6d..44a138e2 100644 --- a/src/leap/bitmask/gui/mail_status.py +++ b/src/leap/bitmask/gui/mail_status.py @@ -112,6 +112,10 @@ class MailStatusWidget(QtGui.QWidget):                   callback=self._mail_handle_imap_events,                   reqcbk=lambda req, resp: None) +        register(signal=proto.SOLEDAD_INVALID_AUTH_TOKEN, +                 callback=self.set_soledad_invalid_auth_token, +                 reqcbk=lambda req, resp: None) +          self._soledad_event.connect(              self._mail_handle_soledad_events_slot)          self._imap_event.connect( @@ -191,6 +195,17 @@ class MailStatusWidget(QtGui.QWidget):          msg = self.tr("There was an unexpected problem with Soledad.")          self._set_mail_status(msg, ready=-1) +    def set_soledad_invalid_auth_token(self): +        """ +        SLOT +        TRIGGER: +            SoledadBootstrapper.soledad_invalid_token + +        This method is called when the auth token is invalid +        """ +        msg = self.tr("Invalid auth token, try logging in again.") +        self._set_mail_status(msg, ready=-1) +      def _set_mail_status(self, status, ready=0):          """          Sets the Mail status in the label and in the tray icon. @@ -384,7 +399,7 @@ class MailStatusWidget(QtGui.QWidget):      def about_to_start(self):          """ -        Displays the correct UI for the point where mail components +        Display the correct UI for the point where mail components          haven't really started, but they are about to in a second.          """          self._set_mail_status(self.tr("About to start, please wait..."), @@ -392,7 +407,7 @@ class MailStatusWidget(QtGui.QWidget):      def set_disabled(self):          """ -        Displays the correct UI for disabled mail. +        Display the correct UI for disabled mail.          """          self._set_mail_status(self.tr("Disabled"), -1) @@ -403,7 +418,7 @@ class MailStatusWidget(QtGui.QWidget):      @QtCore.Slot()      def mail_state_disconnected(self):          """ -        Displays the correct UI for the disconnected state. +        Display the correct UI for the disconnected state.          """          # XXX this should handle the disabled state better.          self._started = False @@ -415,7 +430,7 @@ class MailStatusWidget(QtGui.QWidget):      @QtCore.Slot()      def mail_state_connecting(self):          """ -        Displays the correct UI for the connecting state. +        Display the correct UI for the connecting state.          """          self._disabled = False          self._started = True @@ -424,23 +439,32 @@ class MailStatusWidget(QtGui.QWidget):      @QtCore.Slot()      def mail_state_disconnecting(self):          """ -        Displays the correct UI for the connecting state. +        Display the correct UI for the connecting state.          """          self._set_mail_status(self.tr("Disconnecting..."), 1)      @QtCore.Slot()      def mail_state_connected(self):          """ -        Displays the correct UI for the connected state. +        Display the correct UI for the connected state.          """          self._set_mail_status(self.tr("ON"), 2)      @QtCore.Slot()      def mail_state_disabled(self):          """ -        Displays the correct UI for the disabled state. +        Display the correct UI for the disabled state.          """          self._disabled = True          status = self.tr("You must be logged in to use {0}.").format(              self._service_name)          self._set_mail_status(status, -1) + +    @QtCore.Slot() +    def soledad_invalid_auth_token(self): +        """ +        Display the correct UI for the invalid token state +        """ +        self._disabled = True +        status = self.tr("Invalid auth token, try logging in again.") +        self._set_mail_status(status, -1) diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 758bff4e..e4e71dcc 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -262,6 +262,8 @@ class MainWindow(QtGui.QMainWindow):              self._soledad_bootstrapped_stage)          self._soledad_bootstrapper.soledad_timeout.connect(              self._retry_soledad_connection) +        self._soledad_bootstrapper.soledad_invalid_auth_token.connect( +            self._mail_status.set_soledad_invalid_auth_token)          self._soledad_bootstrapper.soledad_failed.connect(              self._mail_status.set_soledad_failed) diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py index f5892468..79f324dc 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -35,6 +35,7 @@ from leap.common.check import leap_assert  from leap.common.events import register as leap_register  from leap.common.events import events_pb2 as leap_events +  logger = logging.getLogger(__name__) @@ -406,3 +407,4 @@ class MailConductor(IMAPControl, SMTPControl):          qtsigs.connecting_signal.connect(widget.mail_state_connecting)          qtsigs.disconnecting_signal.connect(widget.mail_state_disconnecting)          qtsigs.disconnected_signal.connect(widget.mail_state_disconnected) +        qtsigs.soledad_invalid_auth_token.connect(widget.soledad_invalid_auth_token) diff --git a/src/leap/bitmask/services/mail/connection.py b/src/leap/bitmask/services/mail/connection.py index 29378f62..fdc28fe4 100644 --- a/src/leap/bitmask/services/mail/connection.py +++ b/src/leap/bitmask/services/mail/connection.py @@ -93,6 +93,8 @@ class MailConnectionSignals(QtCore.QObject):      connection_died_signal = QtCore.Signal()      connection_aborted_signal = QtCore.Signal() +    soledad_invalid_auth_token = QtCore.Signal() +  class MailConnection(AbstractLEAPConnection): diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index 7aa86a02..ad5ee4d0 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -44,6 +44,7 @@ from leap.common.check import leap_assert, leap_assert_type, leap_check  from leap.common.files import which  from leap.keymanager import KeyManager, openpgp  from leap.keymanager.errors import KeyNotFound +from leap.soledad.common.errors import InvalidAuthTokenError  from leap.soledad.client import Soledad, BootstrapSequenceError  logger = logging.getLogger(__name__) @@ -139,6 +140,7 @@ class SoledadBootstrapper(AbstractBootstrapper):      gen_key = QtCore.Signal(dict)      local_only_ready = QtCore.Signal(dict)      soledad_timeout = QtCore.Signal() +    soledad_invalid_auth_token = QtCore.Signal()      soledad_failed = QtCore.Signal()      def __init__(self): @@ -258,6 +260,12 @@ class SoledadBootstrapper(AbstractBootstrapper):          return server_url, cert_file +    def _soledad_sync_errback(self, failure): +        failure.trap(InvalidAuthTokenError) +        # in the case of an invalid token we have already turned off mail and +        # warned the user in _do_soledad_sync() + +      def load_and_sync_soledad(self, uuid=None, offline=False):          """          Once everthing is in the right place, we instantiate and sync @@ -298,7 +306,8 @@ class SoledadBootstrapper(AbstractBootstrapper):                  self._keymanager.get_key(                      address, openpgp.OpenPGPKey,                      private=True, fetch_remote=False) -                threads.deferToThread(self._do_soledad_sync) +                d = threads.deferToThread(self._do_soledad_sync) +                d.addErrback(self._soledad_sync_errback)              except KeyNotFound:                  logger.debug("Key not found. Generating key for %s" %                               (address,)) @@ -350,6 +359,9 @@ class SoledadBootstrapper(AbstractBootstrapper):                  # ubuntu folks.                  sync_tries -= 1                  continue +            except InvalidAuthTokenError: +                self.soledad_invalid_auth_token.emit() +                raise              except Exception as e:                  logger.exception("Unhandled error while syncing "                                   "soledad: %r" % (e,)) @@ -444,6 +456,10 @@ class SoledadBootstrapper(AbstractBootstrapper):          except (sqlite_ProgrammingError, sqlcipher_ProgrammingError) as e:              logger.exception("%r" % (e,))              raise +        except InvalidAuthTokenError: +            # token is invalid, probably expired +            logger.error('Invalid auth token while trying to sync Soledad') +            raise          except Exception as exc:              logger.exception("Unhandled error while syncing "                               "soledad: %r" % (exc,)) | 
