Merge lp:~mikemc/ubuntuone-control-panel/fix-1248326 into lp:ubuntuone-control-panel

Proposed by Mike McCracken
Status: Merged
Approved by: Mike McCracken
Approved revision: 415
Merged at revision: 409
Proposed branch: lp:~mikemc/ubuntuone-control-panel/fix-1248326
Merge into: lp:ubuntuone-control-panel
Diff against target: 343 lines (+123/-13)
9 files modified
ubuntuone/controlpanel/gui/qt/account.py (+13/-2)
ubuntuone/controlpanel/gui/qt/controlpanel.py (+21/-4)
ubuntuone/controlpanel/gui/qt/device.py (+9/-1)
ubuntuone/controlpanel/gui/qt/devices.py (+10/-2)
ubuntuone/controlpanel/gui/qt/folders.py (+12/-4)
ubuntuone/controlpanel/gui/qt/tests/test_account.py (+16/-0)
ubuntuone/controlpanel/gui/qt/tests/test_controlpanel.py (+8/-0)
ubuntuone/controlpanel/gui/qt/tests/test_devices.py (+18/-0)
ubuntuone/controlpanel/gui/qt/tests/test_folders.py (+16/-0)
To merge this branch: bzr merge lp:~mikemc/ubuntuone-control-panel/fix-1248326
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve
dobey (community) Approve
Review via email: mp+196800@code.launchpad.net

Commit message

- Prompt user to re-login with SSO if UnauthorizedError is raised by web client. (LP: #1248326)

Description of the change

- Prompt user to re-login with SSO if UnauthorizedError is raised by web client. (LP: #1248326)

To test: log in and then invalidate the token using the web site.
Then trigger a web call by changing to either the devices or account tabs.
The SSO login window should pop up immediately.
Previously, the uncaught exception traceback was just shown to the user.

To post a comment you must log in.
Revision history for this message
dobey (dobey) wrote :

No tests?

review: Needs Fixing
Revision history for this message
dobey (dobey) :
review: Approve
Revision history for this message
Roberto Alsina (ralsina) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'ubuntuone/controlpanel/gui/qt/account.py'
--- ubuntuone/controlpanel/gui/qt/account.py 2012-02-22 15:35:13 +0000
+++ ubuntuone/controlpanel/gui/qt/account.py 2013-11-27 19:55:46 +0000
@@ -19,6 +19,8 @@
1919
20"""The user interface for the control panel for Ubuntu One."""20"""The user interface for the control panel for Ubuntu One."""
2121
22from PyQt4 import QtCore
23
22from twisted.internet import defer24from twisted.internet import defer
2325
24from ubuntuone.controlpanel.logger import setup_logging, log_call26from ubuntuone.controlpanel.logger import setup_logging, log_call
@@ -33,6 +35,7 @@
33from ubuntuone.controlpanel.gui.qt.ubuntuonebin import UbuntuOneBin35from ubuntuone.controlpanel.gui.qt.ubuntuonebin import UbuntuOneBin
34from ubuntuone.controlpanel.gui.qt.ui import account_ui36from ubuntuone.controlpanel.gui.qt.ui import account_ui
3537
38from ubuntu_sso.utils.webclient.common import UnauthorizedError
3639
37logger = setup_logging('qt.account')40logger = setup_logging('qt.account')
3841
@@ -43,6 +46,8 @@
43 ui_class = account_ui46 ui_class = account_ui
44 logger = logger47 logger = logger
4548
49 credentialsCleared = QtCore.pyqtSignal()
50
46 def _setup(self):51 def _setup(self):
47 """Do some extra setupping for the UI."""52 """Do some extra setupping for the UI."""
48 super(AccountPanel, self)._setup()53 super(AccountPanel, self)._setup()
@@ -58,8 +63,14 @@
58 def load(self):63 def load(self):
59 """Load info."""64 """Load info."""
60 self.is_processing = True65 self.is_processing = True
61 info = yield self.backend.account_info()66 try:
62 self.process_info(info)67 info = yield self.backend.account_info()
68 except UnauthorizedError:
69 self.is_processing = False
70 logger.debug("handling UnauthorizedError from account_info()")
71 self.credentialsCleared.emit()
72 else:
73 self.process_info(info)
6374
64 @log_call(logger.debug)75 @log_call(logger.debug)
65 def process_info(self, info):76 def process_info(self, info):
6677
=== modified file 'ubuntuone/controlpanel/gui/qt/controlpanel.py'
--- ubuntuone/controlpanel/gui/qt/controlpanel.py 2013-03-11 18:46:14 +0000
+++ ubuntuone/controlpanel/gui/qt/controlpanel.py 2013-11-27 19:55:46 +0000
@@ -46,6 +46,7 @@
46from ubuntuone.controlpanel.gui.qt.ubuntuonebin import UbuntuOneBin46from ubuntuone.controlpanel.gui.qt.ubuntuonebin import UbuntuOneBin
47from ubuntuone.controlpanel.gui.qt.ui import controlpanel_ui47from ubuntuone.controlpanel.gui.qt.ui import controlpanel_ui
4848
49from ubuntu_sso.utils.webclient.common import UnauthorizedError
4950
50logger = setup_logging('qt.controlpanel')51logger = setup_logging('qt.controlpanel')
5152
@@ -96,6 +97,10 @@
96 # account info97 # account info
97 self.ui.tab_widget.show_overlay = False98 self.ui.tab_widget.show_overlay = False
9899
100 for tab in [self.ui.account_tab, self.ui.folders_tab,
101 self.ui.devices_tab]:
102 tab.credentialsCleared.connect(self.on_credentials_cleared)
103
99 @defer.inlineCallbacks104 @defer.inlineCallbacks
100 def connect_file_sync(self):105 def connect_file_sync(self):
101 """Connect file sync service if the setting autoconnect is enabled."""106 """Connect file sync service if the setting autoconnect is enabled."""
@@ -122,14 +127,26 @@
122 self.connect_file_sync()127 self.connect_file_sync()
123 yield self.show_management_ui()128 yield self.show_management_ui()
124129
130 @log_call(logger.debug)
131 @defer.inlineCallbacks
132 def on_credentials_cleared(self):
133 """Prompt user to log back in after credentials have been deleted."""
134 yield self.backend.login()
135 # ignore returned credentials from login(), load() re-gets them.
136 yield self.load()
137
125 @defer.inlineCallbacks138 @defer.inlineCallbacks
126 def show_management_ui(self):139 def show_management_ui(self):
127 """Show mgmt UI. File sync is already connected if desired."""140 """Show mgmt UI. File sync is already connected if desired."""
128 self.ui.switcher.setCurrentWidget(self.ui.management)141 self.ui.switcher.setCurrentWidget(self.ui.management)
129 info = yield self.backend.account_info()142 try:
130 self.process_info(info)143 info = yield self.backend.account_info()
131 self.is_processing = False144 except UnauthorizedError:
132 self.ui.tab_widget.show_overlay = True145 self.on_credentials_cleared()
146 else:
147 self.process_info(info)
148 self.is_processing = False
149 self.ui.tab_widget.show_overlay = True
133150
134 # pylint: disable=E0202151 # pylint: disable=E0202
135 @defer.inlineCallbacks152 @defer.inlineCallbacks
136153
=== modified file 'ubuntuone/controlpanel/gui/qt/device.py'
--- ubuntuone/controlpanel/gui/qt/device.py 2012-03-08 20:46:13 +0000
+++ ubuntuone/controlpanel/gui/qt/device.py 2013-11-27 19:55:46 +0000
@@ -37,6 +37,8 @@
37from ubuntuone.controlpanel.gui.qt.ui import device_ui37from ubuntuone.controlpanel.gui.qt.ui import device_ui
38from ubuntuone.controlpanel.logger import setup_logging38from ubuntuone.controlpanel.logger import setup_logging
3939
40from ubuntu_sso.utils.webclient.common import UnauthorizedError
41
40COMPUTER_ICON = "computer"42COMPUTER_ICON = "computer"
41PHONE_ICON = "phone"43PHONE_ICON = "phone"
42DEFAULT_ICON = COMPUTER_ICON44DEFAULT_ICON = COMPUTER_ICON
@@ -105,7 +107,13 @@
105 response = QtGui.QMessageBox.warning(self, '', msg, buttons, NO)107 response = QtGui.QMessageBox.warning(self, '', msg, buttons, NO)
106108
107 if response == YES:109 if response == YES:
108 yield self.backend.remove_device(device_id=self.id)110 try:
111 yield self.backend.remove_device(device_id=self.id)
112 except UnauthorizedError:
113 # Ignore UnauthorizedError because it means our
114 # local device was invalidated remotely, which we can
115 # handle the same way
116 pass
109 self.removed.emit()117 self.removed.emit()
110 else:118 else:
111 self.removeCanceled.emit()119 self.removeCanceled.emit()
112120
=== modified file 'ubuntuone/controlpanel/gui/qt/devices.py'
--- ubuntuone/controlpanel/gui/qt/devices.py 2012-03-08 20:46:13 +0000
+++ ubuntuone/controlpanel/gui/qt/devices.py 2013-11-27 19:55:46 +0000
@@ -35,6 +35,7 @@
35from ubuntuone.controlpanel.gui.qt.ubuntuonebin import UbuntuOneBin35from ubuntuone.controlpanel.gui.qt.ubuntuonebin import UbuntuOneBin
36from ubuntuone.controlpanel.gui.qt import device36from ubuntuone.controlpanel.gui.qt import device
3737
38from ubuntu_sso.utils.webclient.common import UnauthorizedError
3839
39logger = setup_logging('qt.devices')40logger = setup_logging('qt.devices')
4041
@@ -45,6 +46,7 @@
45 ui_class = devices_ui46 ui_class = devices_ui
46 logger = logger47 logger = logger
4748
49 credentialsCleared = QtCore.pyqtSignal()
48 localDeviceRemoved = QtCore.pyqtSignal()50 localDeviceRemoved = QtCore.pyqtSignal()
4951
50 def _setup(self):52 def _setup(self):
@@ -60,8 +62,14 @@
60 def load(self):62 def load(self):
61 """Load info."""63 """Load info."""
62 self.is_processing = True64 self.is_processing = True
63 info = yield self.backend.device_names_info()65 try:
64 self.process_info(info)66 info = yield self.backend.device_names_info()
67 except UnauthorizedError:
68 self.is_processing = False
69 logger.debug("handling UnauthorizedError from device_names_info()")
70 self.credentialsCleared.emit()
71 else:
72 self.process_info(info)
6573
66 @log_call(logger.debug)74 @log_call(logger.debug)
67 def process_info(self, info):75 def process_info(self, info):
6876
=== modified file 'ubuntuone/controlpanel/gui/qt/folders.py'
--- ubuntuone/controlpanel/gui/qt/folders.py 2012-11-29 20:15:08 +0000
+++ ubuntuone/controlpanel/gui/qt/folders.py 2013-11-27 19:55:46 +0000
@@ -63,6 +63,7 @@
63from ubuntuone.controlpanel.gui.qt.ubuntuonebin import UbuntuOneBin63from ubuntuone.controlpanel.gui.qt.ubuntuonebin import UbuntuOneBin
64from ubuntuone.controlpanel.gui.qt.ui import folders_ui, local_folders_ui64from ubuntuone.controlpanel.gui.qt.ui import folders_ui, local_folders_ui
6565
66from ubuntu_sso.utils.webclient.common import UnauthorizedError
6667
67logger = setup_logging('qt.folders')68logger = setup_logging('qt.folders')
6869
@@ -118,6 +119,8 @@
118 ui_class = folders_ui119 ui_class = folders_ui
119 widget_items = {}120 widget_items = {}
120121
122 credentialsCleared = QtCore.pyqtSignal()
123
121 def _setup(self):124 def _setup(self):
122 """Do some extra setupping for the UI."""125 """Do some extra setupping for the UI."""
123 super(FoldersPanel, self)._setup()126 super(FoldersPanel, self)._setup()
@@ -157,7 +160,6 @@
157 @log_call(logger.info)160 @log_call(logger.info)
158 def on_folder_created(self, new_folder):161 def on_folder_created(self, new_folder):
159 """Reload folder info after folder creation."""162 """Reload folder info after folder creation."""
160 self.is_processing = True
161 self.load()163 self.load()
162164
163 # pylint: disable=E0202165 # pylint: disable=E0202
@@ -165,9 +167,15 @@
165 def load(self):167 def load(self):
166 """Load specific tab info."""168 """Load specific tab info."""
167 self.is_processing = True169 self.is_processing = True
168 info = yield self.backend.volumes_info(with_storage_info=False,170 try:
169 refresh=self.remote_folders)171 info = yield self.backend.volumes_info(with_storage_info=False,
170 self.process_info(info)172 refresh=self.remote_folders)
173 except UnauthorizedError:
174 self.is_processing = False
175 logger.debug("handling UnauthorizedError from volumes_info")
176 self.credentialsCleared.emit()
177 else:
178 self.process_info(info)
171179
172 @handle_errors(logger=logger)180 @handle_errors(logger=logger)
173 @log_call(logger.debug)181 @log_call(logger.debug)
174182
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_account.py'
--- ubuntuone/controlpanel/gui/qt/tests/test_account.py 2012-03-12 16:58:16 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/test_account.py 2013-11-27 19:55:46 +0000
@@ -27,6 +27,9 @@
27from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import (27from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import (
28 UbuntuOneBinTestCase,28 UbuntuOneBinTestCase,
29)29)
30from ubuntuone.controlpanel.gui.tests import FakeSignal
31
32from ubuntu_sso.utils.webclient.common import UnauthorizedError
3033
3134
32class AccountPanelTestCase(UbuntuOneBinTestCase):35class AccountPanelTestCase(UbuntuOneBinTestCase):
@@ -59,6 +62,19 @@
59 yield self.ui.load()62 yield self.ui.load()
60 self.assert_backend_called('account_info')63 self.assert_backend_called('account_info')
6164
65 @defer.inlineCallbacks
66 def test_load_signals_on_unauthorized(self):
67 """Emit credentialsCleared when UnauthorizedError is raised"""
68 def account_info_error(*args, **kwargs):
69 raise UnauthorizedError()
70 fake_cleared_signal = FakeSignal()
71 fake_cleared_signal.connect(self._set_called)
72 self.patch(self.ui.backend, 'account_info', account_info_error)
73 self.patch(self.ui, 'credentialsCleared', fake_cleared_signal)
74
75 yield self.ui.load()
76 self.assertEqual(self._called, ((), {}))
77
62 def test_process_info(self):78 def test_process_info(self):
63 """The info is processed when ready."""79 """The info is processed when ready."""
64 self.ui.process_info(SAMPLE_ACCOUNT_INFO)80 self.ui.process_info(SAMPLE_ACCOUNT_INFO)
6581
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_controlpanel.py'
--- ubuntuone/controlpanel/gui/qt/tests/test_controlpanel.py 2013-03-12 19:25:09 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/test_controlpanel.py 2013-11-27 19:55:46 +0000
@@ -107,6 +107,14 @@
107 self.assertEqual(self._called, ((), {}))107 self.assertEqual(self._called, ((), {}))
108108
109 @defer.inlineCallbacks109 @defer.inlineCallbacks
110 def test_on_credentials_cleared(self):
111 """Call backend.login and self.load."""
112 self.patch(self.ui, 'load', self._set_called)
113 yield self.ui.on_credentials_cleared()
114 self.assert_backend_called('login')
115 self.assertEqual(self._called, ((), {}))
116
117 @defer.inlineCallbacks
110 def test_info_is_requested_on_load(self):118 def test_info_is_requested_on_load(self):
111 """The info is requested to the backend."""119 """The info is requested to the backend."""
112 self.patch(self.ui, 'process_info', self._set_called)120 self.patch(self.ui, 'process_info', self._set_called)
113121
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_devices.py'
--- ubuntuone/controlpanel/gui/qt/tests/test_devices.py 2012-03-12 16:53:02 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/test_devices.py 2013-11-27 19:55:46 +0000
@@ -26,6 +26,10 @@
26 UbuntuOneBinTestCase,26 UbuntuOneBinTestCase,
27)27)
2828
29from ubuntuone.controlpanel.gui.tests import FakeSignal
30
31from ubuntu_sso.utils.webclient.common import UnauthorizedError
32
2933
30class DevicesPanelTestCase(UbuntuOneBinTestCase):34class DevicesPanelTestCase(UbuntuOneBinTestCase):
31 """Test the qt control panel."""35 """Test the qt control panel."""
@@ -58,6 +62,20 @@
58 yield self.ui.load()62 yield self.ui.load()
59 self.assert_backend_called('device_names_info')63 self.assert_backend_called('device_names_info')
6064
65 @defer.inlineCallbacks
66 def test_load_signals_on_unauthorized(self):
67 """Emit credentialsCleared when UnauthorizedError is raised"""
68 def device_names_info_error(*args, **kwargs):
69 raise UnauthorizedError()
70 fake_cleared_signal = FakeSignal()
71 fake_cleared_signal.connect(self._set_called)
72 self.patch(self.ui.backend, 'device_names_info',
73 device_names_info_error)
74 self.patch(self.ui, 'credentialsCleared', fake_cleared_signal)
75
76 yield self.ui.load()
77 self.assertEqual(self._called, ((), {}))
78
61 def test_no_devices_at_startup(self):79 def test_no_devices_at_startup(self):
62 """The UI is reset at startup."""80 """The UI is reset at startup."""
63 self.assertEqual(self.ui.ui.list_devices.count(), 0)81 self.assertEqual(self.ui.ui.list_devices.count(), 0)
6482
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_folders.py'
--- ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2012-11-30 17:55:58 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2013-11-27 19:55:46 +0000
@@ -31,6 +31,7 @@
3131
32from ubuntuone.controlpanel.tests import helper_fail32from ubuntuone.controlpanel.tests import helper_fail
33from ubuntuone.controlpanel.gui.tests import (33from ubuntuone.controlpanel.gui.tests import (
34 FakeSignal,
34 FAKE_VOLUMES_INFO,35 FAKE_VOLUMES_INFO,
35 FAKE_VOLUMES_MINIMAL_INFO,36 FAKE_VOLUMES_MINIMAL_INFO,
36 FAKE_VOLUMES_NO_FREE_SPACE_INFO,37 FAKE_VOLUMES_NO_FREE_SPACE_INFO,
@@ -49,6 +50,8 @@
49 UbuntuOneBinTestCase,50 UbuntuOneBinTestCase,
50)51)
5152
53from ubuntu_sso.utils.webclient.common import UnauthorizedError
54
52# Access to a protected member55# Access to a protected member
53# Instance of 'ControlBackend' has no '_called' member56# Instance of 'ControlBackend' has no '_called' member
54# pylint: disable=W0212, E110357# pylint: disable=W0212, E1103
@@ -730,6 +733,19 @@
730 parent = super(RemoteFoldersPanelTestCase, self)733 parent = super(RemoteFoldersPanelTestCase, self)
731 parent.test_process_info_with_music_folder(volumes=volumes)734 parent.test_process_info_with_music_folder(volumes=volumes)
732735
736 @defer.inlineCallbacks
737 def test_load_signals_on_unauthorized(self):
738 """Emit credentialsCleared when UnauthorizedError is raised"""
739 def volumes_info_error(*args, **kwargs):
740 raise UnauthorizedError()
741 fake_cleared_signal = FakeSignal()
742 fake_cleared_signal.connect(self._set_called)
743 self.patch(self.ui.backend, 'volumes_info', volumes_info_error)
744 self.patch(self.ui, 'credentialsCleared', fake_cleared_signal)
745
746 yield self.ui.load()
747 self.assertEqual(self._called, ((), {}))
748
733 def test_share_publish_button(self):749 def test_share_publish_button(self):
734 """When clicking the share/publish button, the proper url is opened."""750 """When clicking the share/publish button, the proper url is opened."""
735 self.assertFalse(self.ui.ui.share_publish_button.isVisible())751 self.assertFalse(self.ui.ui.share_publish_button.isVisible())

Subscribers

People subscribed via source and target branches