Merge lp:~nataliabidart/ubuntu/maverick/ubuntu-sso-client/ubuntu-sso-client-1.0.9 into lp:ubuntu/maverick/ubuntu-sso-client
- Maverick (10.10)
- ubuntu-sso-client-1.0.9
- Merge into maverick
Status: | Superseded | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~nataliabidart/ubuntu/maverick/ubuntu-sso-client/ubuntu-sso-client-1.0.9 | ||||
Merge into: | lp:ubuntu/maverick/ubuntu-sso-client | ||||
Diff against target: |
1307 lines (+490/-147) 12 files modified
PKG-INFO (+1/-1) bin/ubuntu-sso-login (+11/-17) data/ui.glade (+40/-32) debian/changelog (+61/-0) debian/control (+2/-1) debian/watch (+1/-1) run-tests (+1/-1) setup.py (+3/-2) ubuntu_sso/gui.py (+33/-22) ubuntu_sso/main.py (+108/-39) ubuntu_sso/tests/test_gui.py (+65/-20) ubuntu_sso/tests/test_main.py (+164/-11) |
||||
To merge this branch: | bzr merge lp:~nataliabidart/ubuntu/maverick/ubuntu-sso-client/ubuntu-sso-client-1.0.9 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Sponsors | Pending | ||
Review via email: mp+57379@code.launchpad.net |
Commit message
Description of the change
* New upstream release:
[ Natalia B. Bidart <email address hidden> ]
- Register now uses the 'displayname' field to pass it on to SSO as display name (LP: #709494).
Unmerged revisions
- 22. By Natalia Bidart
-
Attaching bug Bug #709494.
- 21. By Natalia Bidart
-
* New upstream release:
[ Natalia B. Bidart <email address hidden> ]
- Register now uses the 'displayname' field to pass it on to SSO as
display name (LP: #709494). - 20. By Natalia Bidart
-
* New upstream release.
[ Natalia B. Bidart <email address hidden> ]
* Avoid generating an extra token when attempting to validate a user
account (LP: #687523). - 19. By Sebastien Bacher
-
releasing version 1.0.7-0ubuntu1
- 18. By Natalia Bidart
-
* New upstream release:
[ Alejandro J. Cura <email address hidden> ]
* Replace twisted gtk reactor with the standard gtk mainloop. (LP: #655327).[ Alejandro J. Cura <email address hidden> ]
* Call the dbus mainloop thread init (fixes LP: #656545).* Adding .bzr-builddeb/
default. conf as per Michael Vog (mvo) request. * Adding dpkg (>= 1.15.7.2) as Pre-Depends (fixes LP: #658768).
* Adding gnome-keyring as dep since python-gnomekeyring doesn't install it.
Preview Diff
1 | === modified file 'PKG-INFO' | |||
2 | --- PKG-INFO 2010-10-01 14:57:22 +0000 | |||
3 | +++ PKG-INFO 2011-04-12 19:01:16 +0000 | |||
4 | @@ -1,6 +1,6 @@ | |||
5 | 1 | Metadata-Version: 1.1 | 1 | Metadata-Version: 1.1 |
6 | 2 | Name: ubuntu-sso-client | 2 | Name: ubuntu-sso-client |
8 | 3 | Version: 1.0.3 | 3 | Version: 1.0.9 |
9 | 4 | Summary: Ubuntu Single Sign-On client | 4 | Summary: Ubuntu Single Sign-On client |
10 | 5 | Home-page: https://launchpad.net/ubuntu-sso-client | 5 | Home-page: https://launchpad.net/ubuntu-sso-client |
11 | 6 | Author: Natalia Bidart | 6 | Author: Natalia Bidart |
12 | 7 | 7 | ||
13 | === modified file 'bin/ubuntu-sso-login' | |||
14 | --- bin/ubuntu-sso-login 2010-10-01 14:57:22 +0000 | |||
15 | +++ bin/ubuntu-sso-login 2011-04-12 19:01:16 +0000 | |||
16 | @@ -42,6 +42,7 @@ | |||
17 | 42 | import signal | 42 | import signal |
18 | 43 | import sys | 43 | import sys |
19 | 44 | 44 | ||
20 | 45 | import dbus.mainloop.glib | ||
21 | 45 | import dbus.service | 46 | import dbus.service |
22 | 46 | import gtk | 47 | import gtk |
23 | 47 | 48 | ||
24 | @@ -57,21 +58,21 @@ | |||
25 | 57 | 58 | ||
26 | 58 | 59 | ||
27 | 59 | logger = setup_logging("ubuntu-sso-login") | 60 | logger = setup_logging("ubuntu-sso-login") |
28 | 61 | dbus.mainloop.glib.threads_init() | ||
29 | 60 | gtk.gdk.threads_init() | 62 | gtk.gdk.threads_init() |
30 | 61 | DBusGMainLoop(set_as_default=True) | 63 | DBusGMainLoop(set_as_default=True) |
31 | 62 | 64 | ||
32 | 63 | 65 | ||
33 | 64 | def sighup_handler(*a, **kw): | 66 | def sighup_handler(*a, **kw): |
42 | 65 | """Stop the service. | 67 | """Stop the service.""" |
43 | 66 | 68 | # This handler may be called in any thread, so is not thread safe. | |
44 | 67 | This is not thread safe, see the link below for info: | 69 | # See the link below for info: |
45 | 68 | www.listware.net/201004/gtk-devel-list/115067-unix-signals-in-glib.html | 70 | # www.listware.net/201004/gtk-devel-list/115067-unix-signals-in-glib.html |
46 | 69 | """ | 71 | # |
47 | 70 | from twisted.internet import reactor | 72 | # gtk.main_quit and the logger methods are safe to be called from any thread. |
48 | 71 | # Module 'twisted.internet.reactor' has no 'stop' member | 73 | # Just don't call other random stuff here. |
41 | 72 | # pylint: disable=E1101 | ||
49 | 73 | logger.info("Stoping Ubuntu SSO login manager since SIGHUP was received.") | 74 | logger.info("Stoping Ubuntu SSO login manager since SIGHUP was received.") |
51 | 74 | reactor.stop() | 75 | gtk.main_quit() |
52 | 75 | 76 | ||
53 | 76 | 77 | ||
54 | 77 | if __name__ == "__main__": | 78 | if __name__ == "__main__": |
55 | @@ -83,10 +84,6 @@ | |||
56 | 83 | logger.error("Ubuntu SSO login manager already running, quitting.") | 84 | logger.error("Ubuntu SSO login manager already running, quitting.") |
57 | 84 | sys.exit(0) | 85 | sys.exit(0) |
58 | 85 | 86 | ||
59 | 86 | logger.debug("Installing the Twisted gtk2reactor.") | ||
60 | 87 | from twisted.internet import gtk2reactor | ||
61 | 88 | gtk2reactor.install() | ||
62 | 89 | |||
63 | 90 | logger.debug("Hooking up SIGHUP with handler %r.", sighup_handler) | 87 | logger.debug("Hooking up SIGHUP with handler %r.", sighup_handler) |
64 | 91 | signal.signal(signal.SIGHUP, sighup_handler) | 88 | signal.signal(signal.SIGHUP, sighup_handler) |
65 | 92 | 89 | ||
66 | @@ -97,7 +94,4 @@ | |||
67 | 97 | bus=dbus.SessionBus()), | 94 | bus=dbus.SessionBus()), |
68 | 98 | object_path=DBUS_CRED_PATH) | 95 | object_path=DBUS_CRED_PATH) |
69 | 99 | 96 | ||
74 | 100 | from twisted.internet import reactor | 97 | gtk.main() |
71 | 101 | # Module 'twisted.internet.reactor' has no 'run' member | ||
72 | 102 | # pylint: disable=E1101 | ||
73 | 103 | reactor.run() | ||
75 | 104 | 98 | ||
76 | === modified file 'data/ui.glade' | |||
77 | --- data/ui.glade 2010-08-27 22:16:40 +0000 | |||
78 | +++ data/ui.glade 2011-04-12 19:01:16 +0000 | |||
79 | @@ -264,36 +264,62 @@ | |||
80 | 264 | </packing> | 264 | </packing> |
81 | 265 | </child> | 265 | </child> |
82 | 266 | <child> | 266 | <child> |
84 | 267 | <object class="GtkHButtonBox" id="hbuttonbox1"> | 267 | <object class="GtkHBox" id="hbox2"> |
85 | 268 | <property name="visible">True</property> | 268 | <property name="visible">True</property> |
86 | 269 | <property name="spacing">5</property> | ||
87 | 270 | <property name="layout_style">end</property> | ||
88 | 271 | <child> | 269 | <child> |
91 | 272 | <object class="GtkButton" id="join_cancel_button"> | 270 | <object class="GtkLinkButton" id="login_button"> |
92 | 273 | <property name="label">gtk-cancel</property> | 271 | <property name="label">login button</property> |
93 | 274 | <property name="visible">True</property> | 272 | <property name="visible">True</property> |
94 | 275 | <property name="can_focus">True</property> | 273 | <property name="can_focus">True</property> |
95 | 276 | <property name="receives_default">True</property> | 274 | <property name="receives_default">True</property> |
97 | 277 | <property name="use_stock">True</property> | 275 | <property name="relief">none</property> |
98 | 276 | <signal name="clicked" handler="on_sign_in_button_clicked" swapped="no"/> | ||
99 | 278 | </object> | 277 | </object> |
100 | 279 | <packing> | 278 | <packing> |
101 | 280 | <property name="expand">False</property> | 279 | <property name="expand">False</property> |
103 | 281 | <property name="fill">False</property> | 280 | <property name="fill">True</property> |
104 | 282 | <property name="position">0</property> | 281 | <property name="position">0</property> |
105 | 283 | </packing> | 282 | </packing> |
106 | 284 | </child> | 283 | </child> |
107 | 285 | <child> | 284 | <child> |
110 | 286 | <object class="GtkButton" id="join_ok_button"> | 285 | <object class="GtkHButtonBox" id="hbuttonbox1"> |
109 | 287 | <property name="label">gtk-go-forward</property> | ||
111 | 288 | <property name="visible">True</property> | 286 | <property name="visible">True</property> |
116 | 289 | <property name="can_focus">True</property> | 287 | <property name="can_focus">False</property> |
117 | 290 | <property name="receives_default">True</property> | 288 | <property name="spacing">5</property> |
118 | 291 | <property name="use_stock">True</property> | 289 | <property name="layout_style">end</property> |
119 | 292 | <signal name="clicked" handler="on_join_ok_button_clicked"/> | 290 | <child> |
120 | 291 | <object class="GtkButton" id="join_cancel_button"> | ||
121 | 292 | <property name="label">gtk-cancel</property> | ||
122 | 293 | <property name="visible">True</property> | ||
123 | 294 | <property name="can_focus">True</property> | ||
124 | 295 | <property name="receives_default">True</property> | ||
125 | 296 | <property name="use_stock">True</property> | ||
126 | 297 | </object> | ||
127 | 298 | <packing> | ||
128 | 299 | <property name="expand">False</property> | ||
129 | 300 | <property name="fill">False</property> | ||
130 | 301 | <property name="position">0</property> | ||
131 | 302 | </packing> | ||
132 | 303 | </child> | ||
133 | 304 | <child> | ||
134 | 305 | <object class="GtkButton" id="join_ok_button"> | ||
135 | 306 | <property name="label">gtk-go-forward</property> | ||
136 | 307 | <property name="visible">True</property> | ||
137 | 308 | <property name="can_focus">True</property> | ||
138 | 309 | <property name="receives_default">True</property> | ||
139 | 310 | <property name="use_stock">True</property> | ||
140 | 311 | <signal name="clicked" handler="on_join_ok_button_clicked" swapped="no"/> | ||
141 | 312 | </object> | ||
142 | 313 | <packing> | ||
143 | 314 | <property name="expand">False</property> | ||
144 | 315 | <property name="fill">False</property> | ||
145 | 316 | <property name="position">1</property> | ||
146 | 317 | </packing> | ||
147 | 318 | </child> | ||
148 | 293 | </object> | 319 | </object> |
149 | 294 | <packing> | 320 | <packing> |
150 | 295 | <property name="expand">False</property> | 321 | <property name="expand">False</property> |
152 | 296 | <property name="fill">False</property> | 322 | <property name="pack_type">end</property> |
153 | 297 | <property name="position">1</property> | 323 | <property name="position">1</property> |
154 | 298 | </packing> | 324 | </packing> |
155 | 299 | </child> | 325 | </child> |
156 | @@ -303,24 +329,6 @@ | |||
157 | 303 | <property name="position">12</property> | 329 | <property name="position">12</property> |
158 | 304 | </packing> | 330 | </packing> |
159 | 305 | </child> | 331 | </child> |
160 | 306 | <child> | ||
161 | 307 | <object class="GtkLinkButton" id="login_button"> | ||
162 | 308 | <property name="label" translatable="yes">login button</property> | ||
163 | 309 | <property name="visible">True</property> | ||
164 | 310 | <property name="can_focus">True</property> | ||
165 | 311 | <property name="receives_default">True</property> | ||
166 | 312 | <property name="has_tooltip">True</property> | ||
167 | 313 | <property name="relief">none</property> | ||
168 | 314 | <signal name="clicked" handler="on_sign_in_button_clicked"/> | ||
169 | 315 | </object> | ||
170 | 316 | <packing> | ||
171 | 317 | <property name="expand">False</property> | ||
172 | 318 | <property name="position">13</property> | ||
173 | 319 | </packing> | ||
174 | 320 | </child> | ||
175 | 321 | <child> | ||
176 | 322 | <placeholder/> | ||
177 | 323 | </child> | ||
178 | 324 | </object> | 332 | </object> |
179 | 325 | <object class="GtkVBox" id="processing_vbox"> | 333 | <object class="GtkVBox" id="processing_vbox"> |
180 | 326 | <property name="visible">True</property> | 334 | <property name="visible">True</property> |
181 | 327 | 335 | ||
182 | === modified file 'debian/changelog' | |||
183 | --- debian/changelog 2010-10-01 15:35:43 +0000 | |||
184 | +++ debian/changelog 2011-04-12 19:01:16 +0000 | |||
185 | @@ -1,3 +1,64 @@ | |||
186 | 1 | ubuntu-sso-client (1.0.9-0ubuntu1) UNRELEASED; urgency=low | ||
187 | 2 | |||
188 | 3 | * New upstream release: | ||
189 | 4 | |||
190 | 5 | [ Natalia B. Bidart <natalia.bidart@canonical.com> ] | ||
191 | 6 | - Register now uses the 'displayname' field to pass it on to SSO as | ||
192 | 7 | display name (LP: #709494). | ||
193 | 8 | |||
194 | 9 | -- Natalia Bidart (nessita) <nataliabidart@gmail.com> Tue, 29 Mar 2011 16:26:42 -0300 | ||
195 | 10 | |||
196 | 11 | ubuntu-sso-client (1.0.8-0ubuntu1) maverick-proposed; urgency=low | ||
197 | 12 | |||
198 | 13 | * New upstream release. | ||
199 | 14 | |||
200 | 15 | [ Natalia B. Bidart <natalia.bidart@canonical.com> ] | ||
201 | 16 | * Avoid generating an extra token when attempting to validate a user | ||
202 | 17 | account (LP: #687523). | ||
203 | 18 | |||
204 | 19 | -- Natalia Bidart (nessita) <nataliabidart@gmail.com> Thu, 16 Dec 2010 13:19:01 -0300 | ||
205 | 20 | |||
206 | 21 | ubuntu-sso-client (1.0.7-0ubuntu1) maverick-proposed; urgency=low | ||
207 | 22 | |||
208 | 23 | * New upstream release (1.0.6, 1.0.7): | ||
209 | 24 | |||
210 | 25 | [ Natalia B. Bidart <natalia.bidart@canonical.com> ] | ||
211 | 26 | * Added a new DBus signal UserNotValidated to indicate when a user is | ||
212 | 27 | registered but not validated (LP: #667899). | ||
213 | 28 | * Added new workflow so email validation is requested if necessary. | ||
214 | 29 | * The verify email page should be always built, not only on registration. | ||
215 | 30 | |||
216 | 31 | [ Alejandro J. Cura <alecu@canonical.com> ] | ||
217 | 32 | * Store credentials on the keyring *only* from the main thread (LP: | ||
218 | 33 | #656545). | ||
219 | 34 | |||
220 | 35 | * New upstream release (1.0.5): | ||
221 | 36 | |||
222 | 37 | [ Natalia B. Bidart <natalia.bidart@canonical.com> ] | ||
223 | 38 | |||
224 | 39 | * Credentials are removed if the pinging to the server fails or any | ||
225 | 40 | other exception occurs (LP: #660516). | ||
226 | 41 | |||
227 | 42 | -- Natalia Bidart (nessita) <nataliabidart@gmail.com> Thu, 04 Nov 2010 09:21:00 -0300 | ||
228 | 43 | |||
229 | 44 | ubuntu-sso-client (1.0.4-0ubuntu1) maverick-proposed; urgency=low | ||
230 | 45 | |||
231 | 46 | * New upstream release: | ||
232 | 47 | |||
233 | 48 | [ Alejandro J. Cura <alecu@canonical.com> ] | ||
234 | 49 | * Replace twisted gtk reactor with the standard gtk mainloop. (LP: #655327). | ||
235 | 50 | |||
236 | 51 | [ Alejandro J. Cura <alecu@canonical.com> ] | ||
237 | 52 | * Call the dbus mainloop thread init (fixes LP: #656545). | ||
238 | 53 | |||
239 | 54 | * Adding .bzr-builddeb/default.conf as per Michael Vog (mvo) request. | ||
240 | 55 | |||
241 | 56 | * Adding dpkg (>= 1.15.7.2) as Pre-Depends (fixes LP: #658768). | ||
242 | 57 | |||
243 | 58 | * Adding gnome-keyring as dep since python-gnomekeyring doesn't install it. | ||
244 | 59 | |||
245 | 60 | -- Natalia Bidart (nessita) <nataliabidart@gmail.com> Tue, 12 Oct 2010 10:07:55 -0300 | ||
246 | 61 | |||
247 | 1 | ubuntu-sso-client (1.0.3-0ubuntu1) maverick; urgency=low | 62 | ubuntu-sso-client (1.0.3-0ubuntu1) maverick; urgency=low |
248 | 2 | 63 | ||
249 | 3 | * New upstream release: | 64 | * New upstream release: |
250 | 4 | 65 | ||
251 | === modified file 'debian/control' | |||
252 | --- debian/control 2010-09-13 15:02:42 +0000 | |||
253 | +++ debian/control 2011-04-12 19:01:16 +0000 | |||
254 | @@ -13,9 +13,10 @@ | |||
255 | 13 | Package: ubuntu-sso-client | 13 | Package: ubuntu-sso-client |
256 | 14 | Architecture: all | 14 | Architecture: all |
257 | 15 | XB-Python-Version: ${python:Versions} | 15 | XB-Python-Version: ${python:Versions} |
258 | 16 | Pre-Depends: dpkg (>=1.15.7.2), | ||
259 | 16 | Depends: ${misc:Depends}, | 17 | Depends: ${misc:Depends}, |
260 | 17 | ${python:Depends}, | 18 | ${python:Depends}, |
262 | 18 | dpkg (>=1.15.7.2), | 19 | gnome-keyring, |
263 | 19 | python-dbus, | 20 | python-dbus, |
264 | 20 | python-gnomekeyring, | 21 | python-gnomekeyring, |
265 | 21 | python-gtk2, | 22 | python-gtk2, |
266 | 22 | 23 | ||
267 | === modified file 'debian/watch' | |||
268 | --- debian/watch 2010-09-22 18:53:18 +0000 | |||
269 | +++ debian/watch 2011-04-12 19:01:16 +0000 | |||
270 | @@ -1,3 +1,3 @@ | |||
271 | 1 | version=3 | 1 | version=3 |
273 | 2 | http://launchpad.net/ubuntu-sso-client/+download?start=10 .*/ubuntu-sso-client-([0-9.]+)\.tar\.gz | 2 | http://launchpad.net/ubuntu-sso-client/+download?start=20 .*/ubuntu-sso-client-([0-9.]+)\.tar\.gz |
274 | 3 | 3 | ||
275 | 4 | 4 | ||
276 | === modified file 'run-tests' | |||
277 | --- run-tests 2010-09-08 19:25:02 +0000 | |||
278 | +++ run-tests 2011-04-12 19:01:16 +0000 | |||
279 | @@ -16,7 +16,7 @@ | |||
280 | 16 | # with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | # with this program. If not, see <http://www.gnu.org/licenses/>. |
281 | 17 | 17 | ||
282 | 18 | `which xvfb-run` ./contrib/test "$@" | 18 | `which xvfb-run` ./contrib/test "$@" |
284 | 19 | pylint contrib ubuntu_sso | 19 | pylint ubuntu_sso |
285 | 20 | if [ -x `which pep8` ]; then | 20 | if [ -x `which pep8` ]; then |
286 | 21 | pep8 --repeat bin/ contrib/ ubuntu_sso/ | 21 | pep8 --repeat bin/ contrib/ ubuntu_sso/ |
287 | 22 | else | 22 | else |
288 | 23 | 23 | ||
289 | === modified file 'setup.py' | |||
290 | --- setup.py 2010-10-01 14:57:22 +0000 | |||
291 | +++ setup.py 2011-04-12 19:01:16 +0000 | |||
292 | @@ -36,7 +36,8 @@ | |||
293 | 36 | from distutils.command import clean, build | 36 | from distutils.command import clean, build |
294 | 37 | 37 | ||
295 | 38 | # Defining variables for various rules here, similar to a Makefile.am | 38 | # Defining variables for various rules here, similar to a Makefile.am |
297 | 39 | CLEANFILES = ['data/com.ubuntu.sso.service'] | 39 | CLEANFILES = ['data/com.ubuntu.sso.service', 'po/ubuntu-sso-client.pot', |
298 | 40 | 'MANIFEST'] | ||
299 | 40 | 41 | ||
300 | 41 | 42 | ||
301 | 42 | # XXX: This needs some serious cleanup | 43 | # XXX: This needs some serious cleanup |
302 | @@ -86,7 +87,7 @@ | |||
303 | 86 | 87 | ||
304 | 87 | DistUtilsExtra.auto.setup( | 88 | DistUtilsExtra.auto.setup( |
305 | 88 | name='ubuntu-sso-client', | 89 | name='ubuntu-sso-client', |
307 | 89 | version='1.0.3', | 90 | version='1.0.9', |
308 | 90 | license='GPL v3', | 91 | license='GPL v3', |
309 | 91 | author='Natalia Bidart', | 92 | author='Natalia Bidart', |
310 | 92 | author_email='natalia.bidart@canonical.com', | 93 | author_email='natalia.bidart@canonical.com', |
311 | 93 | 94 | ||
312 | === modified file 'ubuntu_sso/gui.py' | |||
313 | --- ubuntu_sso/gui.py 2010-10-01 14:57:22 +0000 | |||
314 | +++ ubuntu_sso/gui.py 2011-04-12 19:01:16 +0000 | |||
315 | @@ -28,7 +28,7 @@ | |||
316 | 28 | import dbus | 28 | import dbus |
317 | 29 | import gettext | 29 | import gettext |
318 | 30 | import gobject | 30 | import gobject |
320 | 31 | import gtk | 31 | import gtk # pylint: disable=W0403 |
321 | 32 | import webkit | 32 | import webkit |
322 | 33 | import xdg | 33 | import xdg |
323 | 34 | 34 | ||
324 | @@ -125,7 +125,7 @@ | |||
325 | 125 | self.is_password = is_password | 125 | self.is_password = is_password |
326 | 126 | self.warning = None | 126 | self.warning = None |
327 | 127 | 127 | ||
329 | 128 | super(LabeledEntry, self).__init__(*args, **kwargs) | 128 | gtk.Entry.__init__(self, *args, **kwargs) |
330 | 129 | 129 | ||
331 | 130 | self.set_width_chars(DEFAULT_WIDTH) | 130 | self.set_width_chars(DEFAULT_WIDTH) |
332 | 131 | self._set_label(self, None) | 131 | self._set_label(self, None) |
333 | @@ -161,7 +161,7 @@ | |||
334 | 161 | 161 | ||
335 | 162 | def get_text(self): | 162 | def get_text(self): |
336 | 163 | """Get text only if it's not the label nor empty.""" | 163 | """Get text only if it's not the label nor empty.""" |
338 | 164 | result = super(LabeledEntry, self).get_text() | 164 | result = gtk.Entry.get_text(self) |
339 | 165 | if result == self.label or result.isspace(): | 165 | if result == self.label or result.isspace(): |
340 | 166 | result = '' | 166 | result = '' |
341 | 167 | return result | 167 | return result |
342 | @@ -252,6 +252,8 @@ | |||
343 | 252 | self.tc_uri = tc_uri | 252 | self.tc_uri = tc_uri |
344 | 253 | self.help_text = help_text | 253 | self.help_text = help_text |
345 | 254 | self.close_callback = close_callback | 254 | self.close_callback = close_callback |
346 | 255 | self.user_email = None | ||
347 | 256 | self.user_password = None | ||
348 | 255 | 257 | ||
349 | 256 | ui_filename = get_data_file('ui.glade') | 258 | ui_filename = get_data_file('ui.glade') |
350 | 257 | builder = gtk.Builder() | 259 | builder = gtk.Builder() |
351 | @@ -319,13 +321,13 @@ | |||
352 | 319 | self._append_page(self._build_login_page()) | 321 | self._append_page(self._build_login_page()) |
353 | 320 | self._append_page(self._build_request_password_token_page()) | 322 | self._append_page(self._build_request_password_token_page()) |
354 | 321 | self._append_page(self._build_set_new_password_page()) | 323 | self._append_page(self._build_set_new_password_page()) |
355 | 324 | self._append_page(self._build_verify_email_page()) | ||
356 | 322 | 325 | ||
357 | 323 | window_size = None | 326 | window_size = None |
358 | 324 | if not login_only: | 327 | if not login_only: |
359 | 325 | window_size = (550, 500) | 328 | window_size = (550, 500) |
360 | 326 | self._append_page(self._build_enter_details_page()) | 329 | self._append_page(self._build_enter_details_page()) |
361 | 327 | self._append_page(self._build_tc_page()) | 330 | self._append_page(self._build_tc_page()) |
362 | 328 | self._append_page(self._build_verify_email_page()) | ||
363 | 329 | self.login_button.grab_focus() | 331 | self.login_button.grab_focus() |
364 | 330 | self._set_current_page(self.enter_details_vbox) | 332 | self._set_current_page(self.enter_details_vbox) |
365 | 331 | else: | 333 | else: |
366 | @@ -357,6 +359,8 @@ | |||
367 | 357 | self._filter_by_app_name(self.on_logged_in), | 359 | self._filter_by_app_name(self.on_logged_in), |
368 | 358 | 'LoginError': | 360 | 'LoginError': |
369 | 359 | self._filter_by_app_name(self.on_login_error), | 361 | self._filter_by_app_name(self.on_login_error), |
370 | 362 | 'UserNotValidated': | ||
371 | 363 | self._filter_by_app_name(self.on_user_not_validated), | ||
372 | 360 | 'PasswordResetTokenSent': | 364 | 'PasswordResetTokenSent': |
373 | 361 | self._filter_by_app_name(self.on_password_reset_token_sent), | 365 | self._filter_by_app_name(self.on_password_reset_token_sent), |
374 | 362 | 'PasswordResetError': | 366 | 'PasswordResetError': |
375 | @@ -383,8 +387,6 @@ | |||
376 | 383 | msg = 'UbuntuSSOClientGUI: failed set_transient_for win id %r' | 387 | msg = 'UbuntuSSOClientGUI: failed set_transient_for win id %r' |
377 | 384 | logger.exception(msg, window_id) | 388 | logger.exception(msg, window_id) |
378 | 385 | 389 | ||
379 | 386 | # Hidding unused widgets to save some space (LP #627440). | ||
380 | 387 | self.name_entry.hide() | ||
381 | 388 | self.yes_to_updates_checkbutton.hide() | 390 | self.yes_to_updates_checkbutton.hide() |
382 | 389 | 391 | ||
383 | 390 | self.window.show() | 392 | self.window.show() |
384 | @@ -417,8 +419,8 @@ | |||
385 | 417 | 419 | ||
386 | 418 | match = self.bus.add_signal_receiver(method, signal_name=signal, | 420 | match = self.bus.add_signal_receiver(method, signal_name=signal, |
387 | 419 | dbus_interface=iface) | 421 | dbus_interface=iface) |
390 | 420 | logger.info('Connecting signal %r with method %r at iface %r.' \ | 422 | logger.debug('Connecting signal %r with method %r at iface %r.' \ |
391 | 421 | 'Match: %r', signal, method, iface, match) | 423 | 'Match: %r', signal, method, iface, match) |
392 | 422 | self._signals_receivers[(iface, signal)] = method | 424 | self._signals_receivers[(iface, signal)] = method |
393 | 423 | 425 | ||
394 | 424 | def _debug(self, *args, **kwargs): | 426 | def _debug(self, *args, **kwargs): |
395 | @@ -725,8 +727,8 @@ | |||
396 | 725 | remove = self.bus.remove_signal_receiver | 727 | remove = self.bus.remove_signal_receiver |
397 | 726 | for (iface, signal) in self._signals_receivers.keys(): | 728 | for (iface, signal) in self._signals_receivers.keys(): |
398 | 727 | method = self._signals_receivers.pop((iface, signal)) | 729 | method = self._signals_receivers.pop((iface, signal)) |
401 | 728 | logger.info('Removing signal %r with method %r at iface %r.', | 730 | logger.debug('Removing signal %r with method %r at iface %r.', |
402 | 729 | signal, method, iface) | 731 | signal, method, iface) |
403 | 730 | remove(method, signal_name=signal, dbus_interface=iface) | 732 | remove(method, signal_name=signal, dbus_interface=iface) |
404 | 731 | 733 | ||
405 | 732 | # hide the main window | 734 | # hide the main window |
406 | @@ -765,11 +767,10 @@ | |||
407 | 765 | 767 | ||
408 | 766 | error = False | 768 | error = False |
409 | 767 | 769 | ||
415 | 768 | # Hidding unused widgets to save some space (LP #627440). | 770 | name = self.name_entry.get_text() |
416 | 769 | #name = self.name_entry.get_text() | 771 | if not name: |
417 | 770 | #if not name: | 772 | self.name_entry.set_warning(self.FIELD_REQUIRED) |
418 | 771 | # self.name_entry.set_warning(self.FIELD_REQUIRED) | 773 | error = True |
414 | 772 | # error = True | ||
419 | 773 | 774 | ||
420 | 774 | # check email | 775 | # check email |
421 | 775 | email1 = self.email1_entry.get_text() | 776 | email1 = self.email1_entry.get_text() |
422 | @@ -804,12 +805,15 @@ | |||
423 | 804 | return | 805 | return |
424 | 805 | 806 | ||
425 | 806 | self._set_current_page(self.processing_vbox) | 807 | self._set_current_page(self.processing_vbox) |
426 | 808 | self.user_email = email1 | ||
427 | 809 | self.user_password = password1 | ||
428 | 807 | 810 | ||
434 | 808 | logger.info('Calling register_user with email %r, password <hidden>,' \ | 811 | logger.info('Calling register_with_name with email %r, password, ' |
435 | 809 | ' captcha_id %r and captcha_solution %r.', email1, | 812 | '<hidden> name %r, captcha_id %r and captcha_solution %r.', |
436 | 810 | self._captcha_id, captcha_solution) | 813 | email1, name, self._captcha_id, captcha_solution) |
437 | 811 | f = self.backend.register_user | 814 | f = self.backend.register_with_name |
438 | 812 | f(self.app_name, email1, password1, self._captcha_id, captcha_solution, | 815 | f(self.app_name, email1, password1, name, |
439 | 816 | self._captcha_id, captcha_solution, | ||
440 | 813 | reply_handler=NO_OP, error_handler=NO_OP) | 817 | reply_handler=NO_OP, error_handler=NO_OP) |
441 | 814 | 818 | ||
442 | 815 | def on_tc_button_clicked(self, *args, **kwargs): | 819 | def on_tc_button_clicked(self, *args, **kwargs): |
443 | @@ -832,8 +836,8 @@ | |||
444 | 832 | self.email_token_entry.set_warning(self.FIELD_REQUIRED) | 836 | self.email_token_entry.set_warning(self.FIELD_REQUIRED) |
445 | 833 | return | 837 | return |
446 | 834 | 838 | ||
449 | 835 | email = self.email1_entry.get_text() | 839 | email = self.user_email |
450 | 836 | password = self.password1_entry.get_text() | 840 | password = self.user_password |
451 | 837 | f = self.backend.validate_email | 841 | f = self.backend.validate_email |
452 | 838 | logger.info('Calling validate_email with email %r, password <hidden>' \ | 842 | logger.info('Calling validate_email with email %r, password <hidden>' \ |
453 | 839 | ', app_name %r and email_token %r.', email, self.app_name, | 843 | ', app_name %r and email_token %r.', email, self.app_name, |
454 | @@ -871,6 +875,8 @@ | |||
455 | 871 | reply_handler=NO_OP, error_handler=NO_OP) | 875 | reply_handler=NO_OP, error_handler=NO_OP) |
456 | 872 | 876 | ||
457 | 873 | self._set_current_page(self.processing_vbox) | 877 | self._set_current_page(self.processing_vbox) |
458 | 878 | self.user_email = email | ||
459 | 879 | self.user_password = password | ||
460 | 874 | 880 | ||
461 | 875 | def on_login_back_button_clicked(self, *args, **kwargs): | 881 | def on_login_back_button_clicked(self, *args, **kwargs): |
462 | 876 | """User wants to go to the previous page.""" | 882 | """User wants to go to the previous page.""" |
463 | @@ -1061,6 +1067,11 @@ | |||
464 | 1061 | msg)) | 1067 | msg)) |
465 | 1062 | 1068 | ||
466 | 1063 | @log_call | 1069 | @log_call |
467 | 1070 | def on_user_not_validated(self, app_name, email, *args, **kwargs): | ||
468 | 1071 | """User was not validated.""" | ||
469 | 1072 | self.on_user_registered(app_name, email) | ||
470 | 1073 | |||
471 | 1074 | @log_call | ||
472 | 1064 | def on_password_reset_token_sent(self, app_name, email, *args, **kwargs): | 1075 | def on_password_reset_token_sent(self, app_name, email, *args, **kwargs): |
473 | 1065 | """Password reset token was successfully sent.""" | 1076 | """Password reset token was successfully sent.""" |
474 | 1066 | msg = self.SET_NEW_PASSWORD_LABEL % {'email': email} | 1077 | msg = self.SET_NEW_PASSWORD_LABEL % {'email': email} |
475 | 1067 | 1078 | ||
476 | === modified file 'ubuntu_sso/main.py' | |||
477 | --- ubuntu_sso/main.py 2010-09-14 19:28:09 +0000 | |||
478 | +++ ubuntu_sso/main.py 2011-04-12 19:01:16 +0000 | |||
479 | @@ -55,6 +55,7 @@ | |||
480 | 55 | logger = setup_logging("ubuntu_sso.main") | 55 | logger = setup_logging("ubuntu_sso.main") |
481 | 56 | PING_URL = "https://one.ubuntu.com/oauth/sso-finished-so-get-tokens/" | 56 | PING_URL = "https://one.ubuntu.com/oauth/sso-finished-so-get-tokens/" |
482 | 57 | SERVICE_URL = "https://login.ubuntu.com/api/1.0" | 57 | SERVICE_URL = "https://login.ubuntu.com/api/1.0" |
483 | 58 | NO_OP = lambda *args, **kwargs: None | ||
484 | 58 | 59 | ||
485 | 59 | 60 | ||
486 | 60 | class NoDefaultConfigError(Exception): | 61 | class NoDefaultConfigError(Exception): |
487 | @@ -96,10 +97,16 @@ | |||
488 | 96 | """The new password could not be set.""" | 97 | """The new password could not be set.""" |
489 | 97 | 98 | ||
490 | 98 | 99 | ||
492 | 99 | def keyring_store_credentials(app_name, credentials): | 100 | def keyring_store_credentials(app_name, credentials, callback, *cb_args): |
493 | 100 | """Store the credentials in the keyring.""" | 101 | """Store the credentials in the keyring.""" |
496 | 101 | logger.info('keyring_store_credentials: app_name "%s".', app_name) | 102 | |
497 | 102 | Keyring(app_name).set_ubuntusso_attr(credentials) | 103 | def _inner(): |
498 | 104 | """Store the credentials, and trigger the callback.""" | ||
499 | 105 | logger.info('keyring_store_credentials: app_name "%s".', app_name) | ||
500 | 106 | Keyring(app_name).set_ubuntusso_attr(credentials) | ||
501 | 107 | callback(*cb_args) | ||
502 | 108 | |||
503 | 109 | gobject.idle_add(_inner) | ||
504 | 103 | 110 | ||
505 | 104 | 111 | ||
506 | 105 | def keyring_get_credentials(app_name): | 112 | def keyring_get_credentials(app_name): |
507 | @@ -164,24 +171,27 @@ | |||
508 | 164 | 171 | ||
509 | 165 | return captcha['captcha_id'] | 172 | return captcha['captcha_id'] |
510 | 166 | 173 | ||
512 | 167 | def register_user(self, email, password, captcha_id, captcha_solution): | 174 | def register_with_name(self, email, password, displayname, |
513 | 175 | captcha_id, captcha_solution): | ||
514 | 168 | """Register a new user with 'email' and 'password'.""" | 176 | """Register a new user with 'email' and 'password'.""" |
518 | 169 | logger.debug('register_user: email: %r password: <hidden>, ' | 177 | logger.debug('register_with_name: email: %r password: <hidden>, ' |
519 | 170 | 'captcha_id: %r, captcha_solution: %r', | 178 | 'displayname: %r, captcha_id: %r, captcha_solution: %r', |
520 | 171 | email, captcha_id, captcha_solution) | 179 | email, displayname, captcha_id, captcha_solution) |
521 | 172 | sso_service = self.sso_service_class(None, self.service_url) | 180 | sso_service = self.sso_service_class(None, self.service_url) |
522 | 173 | if not self._valid_email(email): | 181 | if not self._valid_email(email): |
524 | 174 | logger.error('register_user: InvalidEmailError for email: %r', | 182 | logger.error('register_with_name: InvalidEmailError for email: %r', |
525 | 175 | email) | 183 | email) |
526 | 176 | raise InvalidEmailError() | 184 | raise InvalidEmailError() |
527 | 177 | if not self._valid_password(password): | 185 | if not self._valid_password(password): |
529 | 178 | logger.error('register_user: InvalidPasswordError') | 186 | logger.error('register_with_name: InvalidPasswordError') |
530 | 179 | raise InvalidPasswordError() | 187 | raise InvalidPasswordError() |
531 | 180 | 188 | ||
532 | 181 | result = sso_service.registrations.register( | 189 | result = sso_service.registrations.register( |
534 | 182 | email=email, password=password, captcha_id=captcha_id, | 190 | email=email, password=password, |
535 | 191 | displayname=displayname, | ||
536 | 192 | captcha_id=captcha_id, | ||
537 | 183 | captcha_solution=captcha_solution) | 193 | captcha_solution=captcha_solution) |
539 | 184 | logger.info('register_user: email: %r result: %r', email, result) | 194 | logger.info('register_with_name: email: %r result: %r', email, result) |
540 | 185 | 195 | ||
541 | 186 | if result['status'] == 'error': | 196 | if result['status'] == 'error': |
542 | 187 | errorsdict = self._format_webservice_errors(result['errors']) | 197 | errorsdict = self._format_webservice_errors(result['errors']) |
543 | @@ -191,6 +201,17 @@ | |||
544 | 191 | else: | 201 | else: |
545 | 192 | return email | 202 | return email |
546 | 193 | 203 | ||
547 | 204 | def register_user(self, email, password, | ||
548 | 205 | captcha_id, captcha_solution): | ||
549 | 206 | """Register a new user with 'email' and 'password'.""" | ||
550 | 207 | logger.debug('register_user: email: %r password: <hidden>, ' | ||
551 | 208 | 'captcha_id: %r, captcha_solution: %r', | ||
552 | 209 | email, captcha_id, captcha_solution) | ||
553 | 210 | res = self.register_with_name(email, password, displayname='', | ||
554 | 211 | captcha_id=captcha_id, | ||
555 | 212 | captcha_solution=captcha_solution) | ||
556 | 213 | return res | ||
557 | 214 | |||
558 | 194 | def login(self, email, password, token_name): | 215 | def login(self, email, password, token_name): |
559 | 195 | """Login a user with 'email' and 'password'.""" | 216 | """Login a user with 'email' and 'password'.""" |
560 | 196 | logger.debug('login: email: %r password: <hidden>, token_name: %r', | 217 | logger.debug('login: email: %r password: <hidden>, token_name: %r', |
561 | @@ -209,6 +230,25 @@ | |||
562 | 209 | 'token_name: %r', credentials['consumer_key'], token_name) | 230 | 'token_name: %r', credentials['consumer_key'], token_name) |
563 | 210 | return credentials | 231 | return credentials |
564 | 211 | 232 | ||
565 | 233 | def is_validated(self, token, sso_service=None): | ||
566 | 234 | """Return if user with 'email' and 'password' is validated.""" | ||
567 | 235 | logger.debug('is_validated: requesting accounts.me() info.') | ||
568 | 236 | if sso_service is None: | ||
569 | 237 | oauth_token = oauth.OAuthToken(token['token'], | ||
570 | 238 | token['token_secret']) | ||
571 | 239 | authorizer = OAuthAuthorizer(token['consumer_key'], | ||
572 | 240 | token['consumer_secret'], | ||
573 | 241 | oauth_token) | ||
574 | 242 | sso_service = self.sso_service_class(authorizer, self.service_url) | ||
575 | 243 | |||
576 | 244 | me_info = sso_service.accounts.me() | ||
577 | 245 | key = 'preferred_email' | ||
578 | 246 | result = key in me_info and me_info[key] != None | ||
579 | 247 | |||
580 | 248 | logger.info('is_validated: consumer_key: %r, result: %r.', | ||
581 | 249 | token['consumer_key'], result) | ||
582 | 250 | return result | ||
583 | 251 | |||
584 | 212 | def validate_email(self, email, password, email_token, token_name): | 252 | def validate_email(self, email, password, email_token, token_name): |
585 | 213 | """Validate an email token for user with 'email' and 'password'.""" | 253 | """Validate an email token for user with 'email' and 'password'.""" |
586 | 214 | logger.debug('validate_email: email: %r password: <hidden>, ' | 254 | logger.debug('validate_email: email: %r password: <hidden>, ' |
587 | @@ -311,12 +351,8 @@ | |||
588 | 311 | dbus.service.Object.__init__(self, object_path="/sso", | 351 | dbus.service.Object.__init__(self, object_path="/sso", |
589 | 312 | bus_name=bus_name) | 352 | bus_name=bus_name) |
590 | 313 | self.sso_login_processor_class = sso_login_processor_class | 353 | self.sso_login_processor_class = sso_login_processor_class |
597 | 314 | self.sso_service_class = sso_service_class | 354 | self.processor = self.sso_login_processor_class( |
598 | 315 | 355 | sso_service_class=sso_service_class) | |
593 | 316 | def processor(self): | ||
594 | 317 | """Create a login processor with the given class and service class.""" | ||
595 | 318 | return self.sso_login_processor_class( | ||
596 | 319 | sso_service_class=self.sso_service_class) | ||
599 | 320 | 356 | ||
600 | 321 | # generate_capcha signals | 357 | # generate_capcha signals |
601 | 322 | @dbus.service.signal(DBUS_IFACE_USER_NAME, signature="ss") | 358 | @dbus.service.signal(DBUS_IFACE_USER_NAME, signature="ss") |
602 | @@ -337,7 +373,7 @@ | |||
603 | 337 | """Call the matching method in the processor.""" | 373 | """Call the matching method in the processor.""" |
604 | 338 | def f(): | 374 | def f(): |
605 | 339 | """Inner function that will be run in a thread.""" | 375 | """Inner function that will be run in a thread.""" |
607 | 340 | return self.processor().generate_captcha(filename) | 376 | return self.processor.generate_captcha(filename) |
608 | 341 | blocking(f, app_name, self.CaptchaGenerated, | 377 | blocking(f, app_name, self.CaptchaGenerated, |
609 | 342 | self.CaptchaGenerationError) | 378 | self.CaptchaGenerationError) |
610 | 343 | 379 | ||
611 | @@ -361,8 +397,19 @@ | |||
612 | 361 | """Call the matching method in the processor.""" | 397 | """Call the matching method in the processor.""" |
613 | 362 | def f(): | 398 | def f(): |
614 | 363 | """Inner function that will be run in a thread.""" | 399 | """Inner function that will be run in a thread.""" |
617 | 364 | return self.processor().register_user(email, password, | 400 | return self.processor.register_user(email, password, |
618 | 365 | captcha_id, captcha_solution) | 401 | captcha_id, captcha_solution) |
619 | 402 | blocking(f, app_name, self.UserRegistered, self.UserRegistrationError) | ||
620 | 403 | |||
621 | 404 | @dbus.service.method(dbus_interface=DBUS_IFACE_USER_NAME, | ||
622 | 405 | in_signature='ssssss') | ||
623 | 406 | def register_with_name(self, app_name, email, password, name, | ||
624 | 407 | captcha_id, captcha_solution): | ||
625 | 408 | """Call the matching method in the processor.""" | ||
626 | 409 | def f(): | ||
627 | 410 | """Inner function that will be run in a thread.""" | ||
628 | 411 | return self.processor.register_with_name(email, password, name, | ||
629 | 412 | captcha_id, captcha_solution) | ||
630 | 366 | blocking(f, app_name, self.UserRegistered, self.UserRegistrationError) | 413 | blocking(f, app_name, self.UserRegistered, self.UserRegistrationError) |
631 | 367 | 414 | ||
632 | 368 | # login signals | 415 | # login signals |
633 | @@ -378,6 +425,12 @@ | |||
634 | 378 | logger.debug('SSOLogin: emitting LoginError with ' | 425 | logger.debug('SSOLogin: emitting LoginError with ' |
635 | 379 | 'app_name "%s" and error %r', app_name, error) | 426 | 'app_name "%s" and error %r', app_name, error) |
636 | 380 | 427 | ||
637 | 428 | @dbus.service.signal(DBUS_IFACE_USER_NAME, signature="ss") | ||
638 | 429 | def UserNotValidated(self, app_name, result): | ||
639 | 430 | """Signal thrown when the user is not validated.""" | ||
640 | 431 | logger.debug('SSOLogin: emitting UserNotValidated with app_name "%s" ' | ||
641 | 432 | 'and result %r', app_name, result) | ||
642 | 433 | |||
643 | 381 | @dbus.service.method(dbus_interface=DBUS_IFACE_USER_NAME, | 434 | @dbus.service.method(dbus_interface=DBUS_IFACE_USER_NAME, |
644 | 382 | in_signature='sss') | 435 | in_signature='sss') |
645 | 383 | def login(self, app_name, email, password): | 436 | def login(self, app_name, email, password): |
646 | @@ -387,13 +440,21 @@ | |||
647 | 387 | token_name = get_token_name(app_name) | 440 | token_name = get_token_name(app_name) |
648 | 388 | logger.debug('login: token_name %r, email %r, password <hidden>.', | 441 | logger.debug('login: token_name %r, email %r, password <hidden>.', |
649 | 389 | token_name, email) | 442 | token_name, email) |
651 | 390 | credentials = self.processor().login(email, password, token_name) | 443 | credentials = self.processor.login(email, password, token_name) |
652 | 391 | logger.debug('login returned not None credentials? %r.', | 444 | logger.debug('login returned not None credentials? %r.', |
653 | 392 | credentials is not None) | 445 | credentials is not None) |
658 | 393 | assert credentials is not None | 446 | return credentials |
659 | 394 | keyring_store_credentials(app_name, credentials) | 447 | |
660 | 395 | return email | 448 | def success_cb(app_name, credentials): |
661 | 396 | blocking(f, app_name, self.LoggedIn, self.LoginError) | 449 | """Login finished successfull.""" |
662 | 450 | is_validated = self.processor.is_validated(credentials) | ||
663 | 451 | logger.debug('user is validated? %r.', is_validated) | ||
664 | 452 | if is_validated: | ||
665 | 453 | keyring_store_credentials(app_name, credentials, | ||
666 | 454 | self.LoggedIn, app_name, email) | ||
667 | 455 | else: | ||
668 | 456 | self.UserNotValidated(app_name, email) | ||
669 | 457 | blocking(f, app_name, success_cb, self.LoginError) | ||
670 | 397 | 458 | ||
671 | 398 | # validate_email signals | 459 | # validate_email signals |
672 | 399 | @dbus.service.signal(DBUS_IFACE_USER_NAME, signature="ss") | 460 | @dbus.service.signal(DBUS_IFACE_USER_NAME, signature="ss") |
673 | @@ -415,11 +476,16 @@ | |||
674 | 415 | def f(): | 476 | def f(): |
675 | 416 | """Inner function that will be run in a thread.""" | 477 | """Inner function that will be run in a thread.""" |
676 | 417 | token_name = get_token_name(app_name) | 478 | token_name = get_token_name(app_name) |
682 | 418 | credentials = self.processor().validate_email(email, password, | 479 | credentials = self.processor.validate_email(email, password, |
683 | 419 | email_token, token_name) | 480 | email_token, token_name) |
684 | 420 | keyring_store_credentials(app_name, credentials) | 481 | |
685 | 421 | return email | 482 | def _email_stored(): |
686 | 422 | blocking(f, app_name, self.EmailValidated, self.EmailValidationError) | 483 | """The email was stored, so call the signal.""" |
687 | 484 | self.EmailValidated(app_name, email) | ||
688 | 485 | |||
689 | 486 | keyring_store_credentials(app_name, credentials, _email_stored) | ||
690 | 487 | |||
691 | 488 | blocking(f, app_name, NO_OP, self.EmailValidationError) | ||
692 | 423 | 489 | ||
693 | 424 | # request_password_reset_token signals | 490 | # request_password_reset_token signals |
694 | 425 | @dbus.service.signal(DBUS_IFACE_USER_NAME, signature="ss") | 491 | @dbus.service.signal(DBUS_IFACE_USER_NAME, signature="ss") |
695 | @@ -440,7 +506,7 @@ | |||
696 | 440 | """Call the matching method in the processor.""" | 506 | """Call the matching method in the processor.""" |
697 | 441 | def f(): | 507 | def f(): |
698 | 442 | """Inner function that will be run in a thread.""" | 508 | """Inner function that will be run in a thread.""" |
700 | 443 | return self.processor().request_password_reset_token(email) | 509 | return self.processor.request_password_reset_token(email) |
701 | 444 | blocking(f, app_name, self.PasswordResetTokenSent, | 510 | blocking(f, app_name, self.PasswordResetTokenSent, |
702 | 445 | self.PasswordResetError) | 511 | self.PasswordResetError) |
703 | 446 | 512 | ||
704 | @@ -463,8 +529,8 @@ | |||
705 | 463 | """Call the matching method in the processor.""" | 529 | """Call the matching method in the processor.""" |
706 | 464 | def f(): | 530 | def f(): |
707 | 465 | """Inner function that will be run in a thread.""" | 531 | """Inner function that will be run in a thread.""" |
710 | 466 | return self.processor().set_new_password(email, token, | 532 | return self.processor.set_new_password(email, token, |
711 | 467 | new_password) | 533 | new_password) |
712 | 468 | blocking(f, app_name, self.PasswordChanged, self.PasswordChangeError) | 534 | blocking(f, app_name, self.PasswordChanged, self.PasswordChangeError) |
713 | 469 | 535 | ||
714 | 470 | 536 | ||
715 | @@ -481,19 +547,19 @@ | |||
716 | 481 | @dbus.service.signal(DBUS_IFACE_CRED_NAME, signature="s") | 547 | @dbus.service.signal(DBUS_IFACE_CRED_NAME, signature="s") |
717 | 482 | def AuthorizationDenied(self, app_name): | 548 | def AuthorizationDenied(self, app_name): |
718 | 483 | """Signal thrown when the user denies the authorization.""" | 549 | """Signal thrown when the user denies the authorization.""" |
721 | 484 | logger.info('SSOLogin: emitting AuthorizationDenied with app_name ' | 550 | logger.info('SSOCredentials: emitting AuthorizationDenied with ' |
722 | 485 | '"%s"', app_name) | 551 | 'app_name "%s"', app_name) |
723 | 486 | 552 | ||
724 | 487 | @dbus.service.signal(DBUS_IFACE_CRED_NAME, signature="sa{ss}") | 553 | @dbus.service.signal(DBUS_IFACE_CRED_NAME, signature="sa{ss}") |
725 | 488 | def CredentialsFound(self, app_name, credentials): | 554 | def CredentialsFound(self, app_name, credentials): |
726 | 489 | """Signal thrown when the credentials are found.""" | 555 | """Signal thrown when the credentials are found.""" |
729 | 490 | logger.info('SSOLogin: emitting CredentialsFound with app_name "%s"', | 556 | logger.info('SSOCredentials: emitting CredentialsFound with ' |
730 | 491 | app_name) | 557 | 'app_name "%s"', app_name) |
731 | 492 | 558 | ||
732 | 493 | @dbus.service.signal(DBUS_IFACE_CRED_NAME, signature="sss") | 559 | @dbus.service.signal(DBUS_IFACE_CRED_NAME, signature="sss") |
733 | 494 | def CredentialsError(self, app_name, error_message, detailed_error): | 560 | def CredentialsError(self, app_name, error_message, detailed_error): |
734 | 495 | """Signal thrown when there is a problem finding the credentials.""" | 561 | """Signal thrown when there is a problem finding the credentials.""" |
736 | 496 | logger.debug('SSOCredentials: emitting CredentialsError with app_name ' | 562 | logger.error('SSOCredentials: emitting CredentialsError with app_name ' |
737 | 497 | '"%s" and error_message %r', app_name, error_message) | 563 | '"%s" and error_message %r', app_name, error_message) |
738 | 498 | 564 | ||
739 | 499 | @dbus.service.method(dbus_interface=DBUS_IFACE_CRED_NAME, | 565 | @dbus.service.method(dbus_interface=DBUS_IFACE_CRED_NAME, |
740 | @@ -510,7 +576,8 @@ | |||
741 | 510 | 576 | ||
742 | 511 | def _login_success_cb(self, dialog, app_name, email): | 577 | def _login_success_cb(self, dialog, app_name, email): |
743 | 512 | """Handles the response from the UI dialog.""" | 578 | """Handles the response from the UI dialog.""" |
745 | 513 | logger.info('Login successful for app %r, email %r', app_name, email) | 579 | logger.info('Login successful for app %r, email %r. Still pending to ' |
746 | 580 | 'ping server and send result signal.', app_name, email) | ||
747 | 514 | try: | 581 | try: |
748 | 515 | creds = keyring_get_credentials(app_name) | 582 | creds = keyring_get_credentials(app_name) |
749 | 516 | self._ping_url(app_name, email, creds) | 583 | self._ping_url(app_name, email, creds) |
750 | @@ -518,6 +585,7 @@ | |||
751 | 518 | except: # pylint: disable=W0702 | 585 | except: # pylint: disable=W0702 |
752 | 519 | msg = "Problem getting the credentials from the keyring." | 586 | msg = "Problem getting the credentials from the keyring." |
753 | 520 | logger.exception(msg) | 587 | logger.exception(msg) |
754 | 588 | self.clear_token(app_name) | ||
755 | 521 | self.CredentialsError(app_name, msg, traceback.format_exc()) | 589 | self.CredentialsError(app_name, msg, traceback.format_exc()) |
756 | 522 | 590 | ||
757 | 523 | def _login_error_cb(self, dialog, app_name, error): | 591 | def _login_error_cb(self, dialog, app_name, error): |
758 | @@ -639,6 +707,7 @@ | |||
759 | 639 | 707 | ||
760 | 640 | 'app_name' is the name of the application. | 708 | 'app_name' is the name of the application. |
761 | 641 | """ | 709 | """ |
762 | 710 | logger.info('Clearing credentials for app %r.', app_name) | ||
763 | 642 | try: | 711 | try: |
764 | 643 | creds = Keyring(app_name) | 712 | creds = Keyring(app_name) |
765 | 644 | creds.delete_ubuntusso_attr() | 713 | creds.delete_ubuntusso_attr() |
766 | 645 | 714 | ||
767 | === modified file 'ubuntu_sso/tests/test_gui.py' | |||
768 | --- ubuntu_sso/tests/test_gui.py 2010-09-08 19:25:02 +0000 | |||
769 | +++ ubuntu_sso/tests/test_gui.py 2011-04-12 19:01:16 +0000 | |||
770 | @@ -63,7 +63,7 @@ | |||
771 | 63 | self._args = args | 63 | self._args = args |
772 | 64 | self._kwargs = kwargs | 64 | self._kwargs = kwargs |
773 | 65 | self._called = {} | 65 | self._called = {} |
775 | 66 | for i in ('generate_captcha', 'login', 'register_user', | 66 | for i in ('generate_captcha', 'login', 'register_with_name', |
776 | 67 | 'validate_email', 'request_password_reset_token', | 67 | 'validate_email', 'request_password_reset_token', |
777 | 68 | 'set_new_password'): | 68 | 'set_new_password'): |
778 | 69 | setattr(self, i, self._record_call(i)) | 69 | setattr(self, i, self._record_call(i)) |
779 | @@ -674,11 +674,11 @@ | |||
780 | 674 | """Clicking 'join_ok_button' sends info to backend using 'register'.""" | 674 | """Clicking 'join_ok_button' sends info to backend using 'register'.""" |
781 | 675 | self.click_join_with_valid_data() | 675 | self.click_join_with_valid_data() |
782 | 676 | 676 | ||
785 | 677 | # assert register_user was called | 677 | # assert register_with_name was called |
786 | 678 | expected = 'register_user' | 678 | expected = 'register_with_name' |
787 | 679 | self.assertIn(expected, self.ui.backend._called) | 679 | self.assertIn(expected, self.ui.backend._called) |
788 | 680 | self.assertEqual(self.ui.backend._called[expected], | 680 | self.assertEqual(self.ui.backend._called[expected], |
790 | 681 | ((APP_NAME, EMAIL, PASSWORD, CAPTCHA_ID, | 681 | ((APP_NAME, EMAIL, PASSWORD, NAME, CAPTCHA_ID, |
791 | 682 | CAPTCHA_SOLUTION), | 682 | CAPTCHA_SOLUTION), |
792 | 683 | dict(reply_handler=gui.NO_OP, | 683 | dict(reply_handler=gui.NO_OP, |
793 | 684 | error_handler=gui.NO_OP))) | 684 | error_handler=gui.NO_OP))) |
794 | @@ -856,6 +856,12 @@ | |||
795 | 856 | self.ui.join_ok_button.clicked() | 856 | self.ui.join_ok_button.clicked() |
796 | 857 | self.assertTrue(self._called) | 857 | self.assertTrue(self._called) |
797 | 858 | 858 | ||
798 | 859 | def test_user_and_pass_are_cached(self): | ||
799 | 860 | """Username and password are temporarly cached for further use.""" | ||
800 | 861 | self.click_join_with_valid_data() | ||
801 | 862 | self.assertEqual(self.ui.user_email, EMAIL) | ||
802 | 863 | self.assertEqual(self.ui.user_password, PASSWORD) | ||
803 | 864 | |||
804 | 859 | 865 | ||
805 | 860 | class NoTermsAndConditionsTestCase(UbuntuSSOClientTestCase): | 866 | class NoTermsAndConditionsTestCase(UbuntuSSOClientTestCase): |
806 | 861 | """Test suite for the user registration (with no t&c link).""" | 867 | """Test suite for the user registration (with no t&c link).""" |
807 | @@ -1005,6 +1011,17 @@ | |||
808 | 1005 | dict(reply_handler=gui.NO_OP, | 1011 | dict(reply_handler=gui.NO_OP, |
809 | 1006 | error_handler=gui.NO_OP))) | 1012 | error_handler=gui.NO_OP))) |
810 | 1007 | 1013 | ||
811 | 1014 | def test_on_verify_token_button_clicked(self): | ||
812 | 1015 | """Verify token uses cached user_email and user_password.""" | ||
813 | 1016 | self.ui.user_email = 'test@me.com' | ||
814 | 1017 | self.ui.user_password = 'yadda-yedda' | ||
815 | 1018 | self.ui.on_verify_token_button_clicked() | ||
816 | 1019 | self.assertEqual(self.ui.backend._called['validate_email'], | ||
817 | 1020 | ((APP_NAME, self.ui.user_email, | ||
818 | 1021 | self.ui.user_password, EMAIL_TOKEN), | ||
819 | 1022 | dict(reply_handler=gui.NO_OP, | ||
820 | 1023 | error_handler=gui.NO_OP))) | ||
821 | 1024 | |||
822 | 1008 | def test_on_verify_token_button_shows_processing_page(self): | 1025 | def test_on_verify_token_button_shows_processing_page(self): |
823 | 1009 | """Verify token button triggers call to backend.""" | 1026 | """Verify token button triggers call to backend.""" |
824 | 1010 | self.click_verify_email_with_valid_data() | 1027 | self.click_verify_email_with_valid_data() |
825 | @@ -1079,7 +1096,7 @@ | |||
826 | 1079 | 1096 | ||
827 | 1080 | 1097 | ||
828 | 1081 | class VerifyEmailValidationTestCase(UbuntuSSOClientTestCase): | 1098 | class VerifyEmailValidationTestCase(UbuntuSSOClientTestCase): |
830 | 1082 | """Test suite for the user registration (verify email page).""" | 1099 | """Test suite for the user registration validation (verify email page).""" |
831 | 1083 | 1100 | ||
832 | 1084 | def setUp(self): | 1101 | def setUp(self): |
833 | 1085 | """Init.""" | 1102 | """Init.""" |
834 | @@ -1114,6 +1131,20 @@ | |||
835 | 1114 | self.assert_warnings_visibility() | 1131 | self.assert_warnings_visibility() |
836 | 1115 | 1132 | ||
837 | 1116 | 1133 | ||
838 | 1134 | class VerifyEmailLoginOnlyTestCase(VerifyEmailTestCase): | ||
839 | 1135 | """Test suite for the user login (verify email page).""" | ||
840 | 1136 | |||
841 | 1137 | kwargs = dict(app_name=APP_NAME, tc_uri=TC_URI, help_text=HELP_TEXT, | ||
842 | 1138 | login_only=True) | ||
843 | 1139 | |||
844 | 1140 | |||
845 | 1141 | class VerifyEmailValidationLoginOnlyTestCase(VerifyEmailValidationTestCase): | ||
846 | 1142 | """Test suite for the user login validation (verify email page).""" | ||
847 | 1143 | |||
848 | 1144 | kwargs = dict(app_name=APP_NAME, tc_uri=TC_URI, help_text=HELP_TEXT, | ||
849 | 1145 | login_only=True) | ||
850 | 1146 | |||
851 | 1147 | |||
852 | 1117 | class RegistrationValidationTestCase(UbuntuSSOClientTestCase): | 1148 | class RegistrationValidationTestCase(UbuntuSSOClientTestCase): |
853 | 1118 | """Test suite for the user registration validations.""" | 1149 | """Test suite for the user registration validations.""" |
854 | 1119 | 1150 | ||
855 | @@ -1130,12 +1161,7 @@ | |||
856 | 1130 | 1161 | ||
857 | 1131 | self.assert_correct_entry_warning(self.ui.name_entry, | 1162 | self.assert_correct_entry_warning(self.ui.name_entry, |
858 | 1132 | self.ui.FIELD_REQUIRED) | 1163 | self.ui.FIELD_REQUIRED) |
865 | 1133 | self.assertNotIn('register_user', self.ui.backend._called) | 1164 | self.assertNotIn('register_with_name', self.ui.backend._called) |
860 | 1134 | |||
861 | 1135 | # Unused variable 'skip' | ||
862 | 1136 | # pylint: disable=W0612 | ||
863 | 1137 | test_warning_is_shown_if_name_empty.skip = \ | ||
864 | 1138 | 'Unused for now, will be hidden to save space (LP: #627440).' | ||
866 | 1139 | 1165 | ||
867 | 1140 | def test_warning_is_shown_if_empty_email(self): | 1166 | def test_warning_is_shown_if_empty_email(self): |
868 | 1141 | """A warning message is shown if emails are empty.""" | 1167 | """A warning message is shown if emails are empty.""" |
869 | @@ -1148,7 +1174,7 @@ | |||
870 | 1148 | self.ui.FIELD_REQUIRED) | 1174 | self.ui.FIELD_REQUIRED) |
871 | 1149 | self.assert_correct_entry_warning(self.ui.email2_entry, | 1175 | self.assert_correct_entry_warning(self.ui.email2_entry, |
872 | 1150 | self.ui.FIELD_REQUIRED) | 1176 | self.ui.FIELD_REQUIRED) |
874 | 1151 | self.assertNotIn('register_user', self.ui.backend._called) | 1177 | self.assertNotIn('register_with_name', self.ui.backend._called) |
875 | 1152 | 1178 | ||
876 | 1153 | def test_warning_is_shown_if_email_mismatch(self): | 1179 | def test_warning_is_shown_if_email_mismatch(self): |
877 | 1154 | """A warning message is shown if emails doesn't match.""" | 1180 | """A warning message is shown if emails doesn't match.""" |
878 | @@ -1161,7 +1187,7 @@ | |||
879 | 1161 | self.ui.EMAIL_MISMATCH) | 1187 | self.ui.EMAIL_MISMATCH) |
880 | 1162 | self.assert_correct_entry_warning(self.ui.email2_entry, | 1188 | self.assert_correct_entry_warning(self.ui.email2_entry, |
881 | 1163 | self.ui.EMAIL_MISMATCH) | 1189 | self.ui.EMAIL_MISMATCH) |
883 | 1164 | self.assertNotIn('register_user', self.ui.backend._called) | 1190 | self.assertNotIn('register_with_name', self.ui.backend._called) |
884 | 1165 | 1191 | ||
885 | 1166 | def test_warning_is_shown_if_invalid_email(self): | 1192 | def test_warning_is_shown_if_invalid_email(self): |
886 | 1167 | """A warning message is shown if email is invalid.""" | 1193 | """A warning message is shown if email is invalid.""" |
887 | @@ -1174,7 +1200,7 @@ | |||
888 | 1174 | self.ui.EMAIL_INVALID) | 1200 | self.ui.EMAIL_INVALID) |
889 | 1175 | self.assert_correct_entry_warning(self.ui.email2_entry, | 1201 | self.assert_correct_entry_warning(self.ui.email2_entry, |
890 | 1176 | self.ui.EMAIL_INVALID) | 1202 | self.ui.EMAIL_INVALID) |
892 | 1177 | self.assertNotIn('register_user', self.ui.backend._called) | 1203 | self.assertNotIn('register_with_name', self.ui.backend._called) |
893 | 1178 | 1204 | ||
894 | 1179 | def test_password_help_is_always_shown(self): | 1205 | def test_password_help_is_always_shown(self): |
895 | 1180 | """Password help text is correctly displayed.""" | 1206 | """Password help text is correctly displayed.""" |
896 | @@ -1182,7 +1208,7 @@ | |||
897 | 1182 | 'password help text is visible.') | 1208 | 'password help text is visible.') |
898 | 1183 | self.assertEqual(self.ui.password_help_label.get_text(), | 1209 | self.assertEqual(self.ui.password_help_label.get_text(), |
899 | 1184 | self.ui.PASSWORD_HELP) | 1210 | self.ui.PASSWORD_HELP) |
901 | 1185 | self.assertNotIn('register_user', self.ui.backend._called) | 1211 | self.assertNotIn('register_with_name', self.ui.backend._called) |
902 | 1186 | 1212 | ||
903 | 1187 | def test_warning_is_shown_if_password_mismatch(self): | 1213 | def test_warning_is_shown_if_password_mismatch(self): |
904 | 1188 | """A warning message is shown if password doesn't match.""" | 1214 | """A warning message is shown if password doesn't match.""" |
905 | @@ -1195,7 +1221,7 @@ | |||
906 | 1195 | self.ui.PASSWORD_MISMATCH) | 1221 | self.ui.PASSWORD_MISMATCH) |
907 | 1196 | self.assert_correct_entry_warning(self.ui.password2_entry, | 1222 | self.assert_correct_entry_warning(self.ui.password2_entry, |
908 | 1197 | self.ui.PASSWORD_MISMATCH) | 1223 | self.ui.PASSWORD_MISMATCH) |
910 | 1198 | self.assertNotIn('register_user', self.ui.backend._called) | 1224 | self.assertNotIn('register_with_name', self.ui.backend._called) |
911 | 1199 | 1225 | ||
912 | 1200 | def test_warning_is_shown_if_password_too_weak(self): | 1226 | def test_warning_is_shown_if_password_too_weak(self): |
913 | 1201 | """A warning message is shown if password is too weak.""" | 1227 | """A warning message is shown if password is too weak.""" |
914 | @@ -1210,7 +1236,7 @@ | |||
915 | 1210 | self.ui.PASSWORD_TOO_WEAK) | 1236 | self.ui.PASSWORD_TOO_WEAK) |
916 | 1211 | self.assert_correct_entry_warning(self.ui.password2_entry, | 1237 | self.assert_correct_entry_warning(self.ui.password2_entry, |
917 | 1212 | self.ui.PASSWORD_TOO_WEAK) | 1238 | self.ui.PASSWORD_TOO_WEAK) |
919 | 1213 | self.assertNotIn('register_user', self.ui.backend._called) | 1239 | self.assertNotIn('register_with_name', self.ui.backend._called) |
920 | 1214 | 1240 | ||
921 | 1215 | def test_warning_is_shown_if_tc_not_accepted(self): | 1241 | def test_warning_is_shown_if_tc_not_accepted(self): |
922 | 1216 | """A warning message is shown if TC are not accepted.""" | 1242 | """A warning message is shown if TC are not accepted.""" |
923 | @@ -1221,7 +1247,7 @@ | |||
924 | 1221 | 1247 | ||
925 | 1222 | self.assert_correct_label_warning(self.ui.tc_warning_label, | 1248 | self.assert_correct_label_warning(self.ui.tc_warning_label, |
926 | 1223 | self.ui.TC_NOT_ACCEPTED) | 1249 | self.ui.TC_NOT_ACCEPTED) |
928 | 1224 | self.assertNotIn('register_user', self.ui.backend._called) | 1250 | self.assertNotIn('register_with_name', self.ui.backend._called) |
929 | 1225 | 1251 | ||
930 | 1226 | def test_warning_is_shown_if_not_captcha_solution(self): | 1252 | def test_warning_is_shown_if_not_captcha_solution(self): |
931 | 1227 | """A warning message is shown if TC are not accepted.""" | 1253 | """A warning message is shown if TC are not accepted.""" |
932 | @@ -1232,7 +1258,7 @@ | |||
933 | 1232 | 1258 | ||
934 | 1233 | self.assert_correct_entry_warning(self.ui.captcha_solution_entry, | 1259 | self.assert_correct_entry_warning(self.ui.captcha_solution_entry, |
935 | 1234 | self.ui.FIELD_REQUIRED) | 1260 | self.ui.FIELD_REQUIRED) |
937 | 1235 | self.assertNotIn('register_user', self.ui.backend._called) | 1261 | self.assertNotIn('register_with_name', self.ui.backend._called) |
938 | 1236 | 1262 | ||
939 | 1237 | def test_no_warning_messages_if_valid_data(self): | 1263 | def test_no_warning_messages_if_valid_data(self): |
940 | 1238 | """No warning messages are shown if the data is valid.""" | 1264 | """No warning messages are shown if the data is valid.""" |
941 | @@ -1328,6 +1354,12 @@ | |||
942 | 1328 | self.ui.on_login_error(app_name=APP_NAME, error=self.error) | 1354 | self.ui.on_login_error(app_name=APP_NAME, error=self.error) |
943 | 1329 | self.assert_pages_visibility(login=True) | 1355 | self.assert_pages_visibility(login=True) |
944 | 1330 | 1356 | ||
945 | 1357 | def test_on_user_not_validated_morphs_to_verify_page(self): | ||
946 | 1358 | """On user not validated, the verify page is shown.""" | ||
947 | 1359 | self.click_connect_with_valid_data() | ||
948 | 1360 | self.ui.on_user_not_validated(app_name=APP_NAME, email=EMAIL) | ||
949 | 1361 | self.assert_pages_visibility(verify_email=True) | ||
950 | 1362 | |||
951 | 1331 | def test_on_login_error_a_warning_is_shown(self): | 1363 | def test_on_login_error_a_warning_is_shown(self): |
952 | 1332 | """On user login error, a warning is shown with proper wording.""" | 1364 | """On user login error, a warning is shown with proper wording.""" |
953 | 1333 | self.click_connect_with_valid_data() | 1365 | self.click_connect_with_valid_data() |
954 | @@ -1377,6 +1409,12 @@ | |||
955 | 1377 | self.ui.login_ok_button.clicked() | 1409 | self.ui.login_ok_button.clicked() |
956 | 1378 | self.assertTrue(self._called) | 1410 | self.assertTrue(self._called) |
957 | 1379 | 1411 | ||
958 | 1412 | def test_user_and_pass_are_cached(self): | ||
959 | 1413 | """Username and password are temporarly cached for further use.""" | ||
960 | 1414 | self.click_connect_with_valid_data() | ||
961 | 1415 | self.assertEqual(self.ui.user_email, EMAIL) | ||
962 | 1416 | self.assertEqual(self.ui.user_password, PASSWORD) | ||
963 | 1417 | |||
964 | 1380 | 1418 | ||
965 | 1381 | class LoginValidationTestCase(UbuntuSSOClientTestCase): | 1419 | class LoginValidationTestCase(UbuntuSSOClientTestCase): |
966 | 1382 | """Test suite for the user login validation.""" | 1420 | """Test suite for the user login validation.""" |
967 | @@ -1782,7 +1820,7 @@ | |||
968 | 1782 | """All the backend signals are listed to be binded.""" | 1820 | """All the backend signals are listed to be binded.""" |
969 | 1783 | for sig in ('CaptchaGenerated', 'CaptchaGenerationError', | 1821 | for sig in ('CaptchaGenerated', 'CaptchaGenerationError', |
970 | 1784 | 'UserRegistered', 'UserRegistrationError', | 1822 | 'UserRegistered', 'UserRegistrationError', |
972 | 1785 | 'LoggedIn', 'LoginError', | 1823 | 'LoggedIn', 'LoginError', 'UserNotValidated', |
973 | 1786 | 'EmailValidated', 'EmailValidationError', | 1824 | 'EmailValidated', 'EmailValidationError', |
974 | 1787 | 'PasswordResetTokenSent', 'PasswordResetError', | 1825 | 'PasswordResetTokenSent', 'PasswordResetError', |
975 | 1788 | 'PasswordChanged', 'PasswordChangeError'): | 1826 | 'PasswordChanged', 'PasswordChangeError'): |
976 | @@ -1864,6 +1902,13 @@ | |||
977 | 1864 | self.ui._signals['LoginError'](mismatch_app_name, 'dummy') | 1902 | self.ui._signals['LoginError'](mismatch_app_name, 'dummy') |
978 | 1865 | self.assertFalse(self._called) | 1903 | self.assertFalse(self._called) |
979 | 1866 | 1904 | ||
980 | 1905 | def test_on_user_not_validated_is_not_called(self): | ||
981 | 1906 | """on_user_not_validated is not called if incorrect app_name.""" | ||
982 | 1907 | self.patch(self.ui, 'on_user_not_validated', self._set_called) | ||
983 | 1908 | mismatch_app_name = self.ui.app_name * 2 | ||
984 | 1909 | self.ui._signals['UserNotValidated'](mismatch_app_name, 'dummy') | ||
985 | 1910 | self.assertFalse(self._called) | ||
986 | 1911 | |||
987 | 1867 | def test_on_password_reset_token_sent_is_not_called(self): | 1912 | def test_on_password_reset_token_sent_is_not_called(self): |
988 | 1868 | """on_password_reset_token_sent is not called if incorrect app_name.""" | 1913 | """on_password_reset_token_sent is not called if incorrect app_name.""" |
989 | 1869 | self.patch(self.ui, 'on_password_reset_token_sent', self._set_called) | 1914 | self.patch(self.ui, 'on_password_reset_token_sent', self._set_called) |
990 | 1870 | 1915 | ||
991 | === modified file 'ubuntu_sso/tests/test_main.py' | |||
992 | --- ubuntu_sso/tests/test_main.py 2010-09-08 19:25:02 +0000 | |||
993 | +++ ubuntu_sso/tests/test_main.py 2011-04-12 19:01:16 +0000 | |||
994 | @@ -1,3 +1,5 @@ | |||
995 | 1 | # -*- coding: utf-8 -*- | ||
996 | 2 | # | ||
997 | 1 | # test_main - tests for ubuntu_sso.main | 3 | # test_main - tests for ubuntu_sso.main |
998 | 2 | # | 4 | # |
999 | 3 | # Author: Natalia Bidart <natalia.bidart@canonical.com> | 5 | # Author: Natalia Bidart <natalia.bidart@canonical.com> |
1000 | @@ -63,6 +65,7 @@ | |||
1001 | 63 | EMAIL_ALREADY_REGISTERED = 'a@example.com' | 65 | EMAIL_ALREADY_REGISTERED = 'a@example.com' |
1002 | 64 | EMAIL_TOKEN = 'B2Pgtf' | 66 | EMAIL_TOKEN = 'B2Pgtf' |
1003 | 65 | HELP = 'help text' | 67 | HELP = 'help text' |
1004 | 68 | NAME = 'Juanito Pérez' | ||
1005 | 66 | PASSWORD = 'be4tiFul' | 69 | PASSWORD = 'be4tiFul' |
1006 | 67 | RESET_PASSWORD_TOKEN = '8G5Wtq' | 70 | RESET_PASSWORD_TOKEN = '8G5Wtq' |
1007 | 68 | TOKEN = {u'consumer_key': u'xQ7xDAz', | 71 | TOKEN = {u'consumer_key': u'xQ7xDAz', |
1008 | @@ -107,7 +110,8 @@ | |||
1009 | 107 | class FakedRegistrations(object): | 110 | class FakedRegistrations(object): |
1010 | 108 | """Fake the registrations service.""" | 111 | """Fake the registrations service.""" |
1011 | 109 | 112 | ||
1013 | 110 | def register(self, email, password, captcha_id, captcha_solution): | 113 | def register(self, email, password, displayname, |
1014 | 114 | captcha_id, captcha_solution): | ||
1015 | 111 | """Fake registration. Return a fix result.""" | 115 | """Fake registration. Return a fix result.""" |
1016 | 112 | if email == EMAIL_ALREADY_REGISTERED: | 116 | if email == EMAIL_ALREADY_REGISTERED: |
1017 | 113 | return {'status': 'error', | 117 | return {'status': 'error', |
1018 | @@ -152,6 +156,9 @@ | |||
1019 | 152 | class FakedAccounts(object): | 156 | class FakedAccounts(object): |
1020 | 153 | """Fake the accounts service.""" | 157 | """Fake the accounts service.""" |
1021 | 154 | 158 | ||
1022 | 159 | def __init__(self): | ||
1023 | 160 | self.preferred_email = EMAIL | ||
1024 | 161 | |||
1025 | 155 | def validate_email(self, email_token): | 162 | def validate_email(self, email_token): |
1026 | 156 | """Fake the email validation. Return a fix result.""" | 163 | """Fake the email validation. Return a fix result.""" |
1027 | 157 | if email_token is None: | 164 | if email_token is None: |
1028 | @@ -164,6 +171,17 @@ | |||
1029 | 164 | else: | 171 | else: |
1030 | 165 | return STATUS_EMAIL_OK | 172 | return STATUS_EMAIL_OK |
1031 | 166 | 173 | ||
1032 | 174 | # pylint: disable=E0202, C0103 | ||
1033 | 175 | |||
1034 | 176 | def me(self): | ||
1035 | 177 | """Fake the 'me' information.""" | ||
1036 | 178 | return {u'username': u'Wh46bKY', | ||
1037 | 179 | u'preferred_email': self.preferred_email, | ||
1038 | 180 | u'displayname': u'', | ||
1039 | 181 | u'unverified_emails': [u'aaaaaa@example.com'], | ||
1040 | 182 | u'verified_emails': [], | ||
1041 | 183 | u'openid_identifier': u'Wh46bKY'} | ||
1042 | 184 | |||
1043 | 167 | 185 | ||
1044 | 168 | class FakedSSOServer(object): | 186 | class FakedSSOServer(object): |
1045 | 169 | """Fake an SSO server.""" | 187 | """Fake an SSO server.""" |
1046 | @@ -279,6 +297,29 @@ | |||
1047 | 279 | result = self.processor.login(**self.login_kwargs) | 297 | result = self.processor.login(**self.login_kwargs) |
1048 | 280 | self.assertEqual(TOKEN, result, 'authentication was successful.') | 298 | self.assertEqual(TOKEN, result, 'authentication was successful.') |
1049 | 281 | 299 | ||
1050 | 300 | # is_validated | ||
1051 | 301 | |||
1052 | 302 | def test_is_validated(self): | ||
1053 | 303 | """If preferred email is not None, user is validated.""" | ||
1054 | 304 | result = self.processor.is_validated(token=TOKEN) | ||
1055 | 305 | self.assertTrue(result, 'user must be validated.') | ||
1056 | 306 | |||
1057 | 307 | def test_is_not_validated(self): | ||
1058 | 308 | """If preferred email is None, user is not validated.""" | ||
1059 | 309 | service = FakedSSOServer(None, None) | ||
1060 | 310 | service.accounts.preferred_email = None | ||
1061 | 311 | result = self.processor.is_validated(sso_service=service, | ||
1062 | 312 | token=TOKEN) | ||
1063 | 313 | self.assertFalse(result, 'user must not be validated.') | ||
1064 | 314 | |||
1065 | 315 | def test_is_not_validated_empty_result(self): | ||
1066 | 316 | """If preferred email is None, user is not validated.""" | ||
1067 | 317 | service = FakedSSOServer(None, None) | ||
1068 | 318 | service.accounts.me = lambda: {} | ||
1069 | 319 | result = self.processor.is_validated(sso_service=service, | ||
1070 | 320 | token=TOKEN) | ||
1071 | 321 | self.assertFalse(result, 'user must not be validated.') | ||
1072 | 322 | |||
1073 | 282 | # validate_email | 323 | # validate_email |
1074 | 283 | 324 | ||
1075 | 284 | def test_validate_email_if_status_ok(self): | 325 | def test_validate_email_if_status_ok(self): |
1076 | @@ -362,6 +403,16 @@ | |||
1077 | 362 | self.assertIn('Received invalid reply: %s' % STATUS_UNKNOWN, exc) | 403 | self.assertIn('Received invalid reply: %s' % STATUS_UNKNOWN, exc) |
1078 | 363 | 404 | ||
1079 | 364 | 405 | ||
1080 | 406 | class SSORegistrationWithNameTestCase(SSOLoginProcessorTestCase): | ||
1081 | 407 | """Test suite for the SSO login processor for register_with_name.""" | ||
1082 | 408 | |||
1083 | 409 | def setUp(self): | ||
1084 | 410 | """Init.""" | ||
1085 | 411 | super(SSORegistrationWithNameTestCase, self).setUp() | ||
1086 | 412 | self.register_kwargs['displayname'] = NAME | ||
1087 | 413 | self.processor.register_user = self.processor.register_with_name | ||
1088 | 414 | |||
1089 | 415 | |||
1090 | 365 | class BlockingSampleException(Exception): | 416 | class BlockingSampleException(Exception): |
1091 | 366 | """The exception that will be thrown by the fake blocking.""" | 417 | """The exception that will be thrown by the fake blocking.""" |
1092 | 367 | 418 | ||
1093 | @@ -380,12 +431,13 @@ | |||
1094 | 380 | mockbus._register_object_path(ARGS) | 431 | mockbus._register_object_path(ARGS) |
1095 | 381 | self.mockprocessorclass = None | 432 | self.mockprocessorclass = None |
1096 | 382 | 433 | ||
1098 | 383 | def ksc(k, val): | 434 | def ksc(k, val, callback, *cb_args): |
1099 | 384 | """Assert over token and app_name.""" | 435 | """Assert over token and app_name.""" |
1100 | 385 | self.assertEqual(k, APP_NAME) | 436 | self.assertEqual(k, APP_NAME) |
1101 | 386 | self.assertEqual(val, TOKEN) | 437 | self.assertEqual(val, TOKEN) |
1102 | 387 | self.keyring_was_set = True | 438 | self.keyring_was_set = True |
1103 | 388 | self.keyring_values = k, val | 439 | self.keyring_values = k, val |
1104 | 440 | callback(*cb_args) | ||
1105 | 389 | 441 | ||
1106 | 390 | self.patch(ubuntu_sso.main, "keyring_store_credentials", ksc) | 442 | self.patch(ubuntu_sso.main, "keyring_store_credentials", ksc) |
1107 | 391 | self.keyring_was_set = False | 443 | self.keyring_was_set = False |
1108 | @@ -472,8 +524,8 @@ | |||
1109 | 472 | """Test that the register_user method works ok.""" | 524 | """Test that the register_user method works ok.""" |
1110 | 473 | d = Deferred() | 525 | d = Deferred() |
1111 | 474 | expected_result = "expected result" | 526 | expected_result = "expected result" |
1114 | 475 | self.create_mock_processor().register_user(EMAIL, PASSWORD, CAPTCHA_ID, | 527 | self.create_mock_processor().register_user(EMAIL, PASSWORD, |
1115 | 476 | CAPTCHA_SOLUTION) | 528 | CAPTCHA_ID, CAPTCHA_SOLUTION) |
1116 | 477 | self.mocker.result(expected_result) | 529 | self.mocker.result(expected_result) |
1117 | 478 | self.patch(ubuntu_sso.main, "blocking", self.fake_ok_blocking) | 530 | self.patch(ubuntu_sso.main, "blocking", self.fake_ok_blocking) |
1118 | 479 | self.mocker.replay() | 531 | self.mocker.replay() |
1119 | @@ -496,8 +548,8 @@ | |||
1120 | 496 | """Test that the register_user method fails as expected.""" | 548 | """Test that the register_user method fails as expected.""" |
1121 | 497 | d = Deferred() | 549 | d = Deferred() |
1122 | 498 | expected_result = "expected result" | 550 | expected_result = "expected result" |
1125 | 499 | self.create_mock_processor().register_user(EMAIL, PASSWORD, CAPTCHA_ID, | 551 | self.create_mock_processor().register_user(EMAIL, PASSWORD, |
1126 | 500 | CAPTCHA_SOLUTION) | 552 | CAPTCHA_ID, CAPTCHA_SOLUTION) |
1127 | 501 | self.mocker.result(expected_result) | 553 | self.mocker.result(expected_result) |
1128 | 502 | self.patch(ubuntu_sso.main, "blocking", self.fake_err_blocking) | 554 | self.patch(ubuntu_sso.main, "blocking", self.fake_err_blocking) |
1129 | 503 | self.mocker.replay() | 555 | self.mocker.replay() |
1130 | @@ -516,11 +568,62 @@ | |||
1131 | 516 | CAPTCHA_SOLUTION) | 568 | CAPTCHA_SOLUTION) |
1132 | 517 | return d | 569 | return d |
1133 | 518 | 570 | ||
1134 | 571 | def test_register_with_name(self): | ||
1135 | 572 | """Test that the register_with_name method works ok.""" | ||
1136 | 573 | d = Deferred() | ||
1137 | 574 | expected_result = "expected result" | ||
1138 | 575 | self.create_mock_processor().register_with_name(EMAIL, PASSWORD, NAME, | ||
1139 | 576 | CAPTCHA_ID, CAPTCHA_SOLUTION) | ||
1140 | 577 | self.mocker.result(expected_result) | ||
1141 | 578 | self.patch(ubuntu_sso.main, "blocking", self.fake_ok_blocking) | ||
1142 | 579 | self.mocker.replay() | ||
1143 | 580 | |||
1144 | 581 | def verify(app_name, result): | ||
1145 | 582 | """The actual test.""" | ||
1146 | 583 | self.assertEqual(result, expected_result) | ||
1147 | 584 | self.assertEqual(app_name, APP_NAME) | ||
1148 | 585 | d.callback(result) | ||
1149 | 586 | |||
1150 | 587 | client = SSOLogin(self.mockbusname, | ||
1151 | 588 | sso_login_processor_class=self.mockprocessorclass) | ||
1152 | 589 | self.patch(client, "UserRegistered", verify) | ||
1153 | 590 | self.patch(client, "UserRegistrationError", d.errback) | ||
1154 | 591 | client.register_with_name(APP_NAME, EMAIL, PASSWORD, NAME, CAPTCHA_ID, | ||
1155 | 592 | CAPTCHA_SOLUTION) | ||
1156 | 593 | return d | ||
1157 | 594 | |||
1158 | 595 | def test_register_with_name_error(self): | ||
1159 | 596 | """Test that the register_with_name method fails as expected.""" | ||
1160 | 597 | d = Deferred() | ||
1161 | 598 | expected_result = "expected result" | ||
1162 | 599 | self.create_mock_processor().register_with_name(EMAIL, PASSWORD, NAME, | ||
1163 | 600 | CAPTCHA_ID, CAPTCHA_SOLUTION) | ||
1164 | 601 | self.mocker.result(expected_result) | ||
1165 | 602 | self.patch(ubuntu_sso.main, "blocking", self.fake_err_blocking) | ||
1166 | 603 | self.mocker.replay() | ||
1167 | 604 | |||
1168 | 605 | def verify(app_name, errdict): | ||
1169 | 606 | """The actual test.""" | ||
1170 | 607 | self.assertEqual(errdict["errtype"], "BlockingSampleException") | ||
1171 | 608 | self.assertEqual(app_name, APP_NAME) | ||
1172 | 609 | d.callback("Ok") | ||
1173 | 610 | |||
1174 | 611 | client = SSOLogin(self.mockbusname, | ||
1175 | 612 | sso_login_processor_class=self.mockprocessorclass) | ||
1176 | 613 | self.patch(client, "UserRegistered", d.errback) | ||
1177 | 614 | self.patch(client, "UserRegistrationError", verify) | ||
1178 | 615 | client.register_with_name(APP_NAME, EMAIL, PASSWORD, NAME, CAPTCHA_ID, | ||
1179 | 616 | CAPTCHA_SOLUTION) | ||
1180 | 617 | return d | ||
1181 | 618 | |||
1182 | 519 | def test_login(self): | 619 | def test_login(self): |
1183 | 520 | """Test that the login method works ok.""" | 620 | """Test that the login method works ok.""" |
1184 | 521 | d = Deferred() | 621 | d = Deferred() |
1186 | 522 | self.create_mock_processor().login(EMAIL, PASSWORD, TOKEN_NAME) | 622 | processor = self.create_mock_processor() |
1187 | 623 | processor.login(EMAIL, PASSWORD, TOKEN_NAME) | ||
1188 | 523 | self.mocker.result(TOKEN) | 624 | self.mocker.result(TOKEN) |
1189 | 625 | processor.is_validated(TOKEN) | ||
1190 | 626 | self.mocker.result(True) | ||
1191 | 524 | self.patch(ubuntu_sso.main, "blocking", self.fake_ok_blocking) | 627 | self.patch(ubuntu_sso.main, "blocking", self.fake_ok_blocking) |
1192 | 525 | self.mocker.replay() | 628 | self.mocker.replay() |
1193 | 526 | 629 | ||
1194 | @@ -535,13 +638,40 @@ | |||
1195 | 535 | sso_login_processor_class=self.mockprocessorclass) | 638 | sso_login_processor_class=self.mockprocessorclass) |
1196 | 536 | self.patch(client, "LoggedIn", verify) | 639 | self.patch(client, "LoggedIn", verify) |
1197 | 537 | self.patch(client, "LoginError", d.errback) | 640 | self.patch(client, "LoginError", d.errback) |
1198 | 641 | self.patch(client, "UserNotValidated", d.errback) | ||
1199 | 642 | client.login(APP_NAME, EMAIL, PASSWORD) | ||
1200 | 643 | return d | ||
1201 | 644 | |||
1202 | 645 | def test_login_user_not_validated(self): | ||
1203 | 646 | """Test that the login sends EmailNotValidated signal.""" | ||
1204 | 647 | d = Deferred() | ||
1205 | 648 | processor = self.create_mock_processor() | ||
1206 | 649 | processor.login(EMAIL, PASSWORD, TOKEN_NAME) | ||
1207 | 650 | self.mocker.result(TOKEN) | ||
1208 | 651 | processor.is_validated(TOKEN) | ||
1209 | 652 | self.mocker.result(False) | ||
1210 | 653 | self.patch(ubuntu_sso.main, "blocking", self.fake_ok_blocking) | ||
1211 | 654 | self.mocker.replay() | ||
1212 | 655 | |||
1213 | 656 | def verify(app_name, email): | ||
1214 | 657 | """The actual test.""" | ||
1215 | 658 | self.assertEqual(app_name, APP_NAME) | ||
1216 | 659 | self.assertEqual(email, EMAIL) | ||
1217 | 660 | self.assertFalse(self.keyring_was_set, "Keyring should not be set") | ||
1218 | 661 | d.callback("Ok") | ||
1219 | 662 | |||
1220 | 663 | client = SSOLogin(self.mockbusname, | ||
1221 | 664 | sso_login_processor_class=self.mockprocessorclass) | ||
1222 | 665 | self.patch(client, "LoggedIn", d.errback) | ||
1223 | 666 | self.patch(client, "LoginError", d.errback) | ||
1224 | 667 | self.patch(client, "UserNotValidated", verify) | ||
1225 | 538 | client.login(APP_NAME, EMAIL, PASSWORD) | 668 | client.login(APP_NAME, EMAIL, PASSWORD) |
1226 | 539 | return d | 669 | return d |
1227 | 540 | 670 | ||
1228 | 541 | def test_login_error(self): | 671 | def test_login_error(self): |
1229 | 542 | """Test that the login method fails as expected.""" | 672 | """Test that the login method fails as expected.""" |
1230 | 543 | d = Deferred() | 673 | d = Deferred() |
1232 | 544 | self.mockprocessorclass = self.mocker.mock() | 674 | self.create_mock_processor() |
1233 | 545 | self.patch(ubuntu_sso.main, "blocking", self.fake_err_blocking) | 675 | self.patch(ubuntu_sso.main, "blocking", self.fake_err_blocking) |
1234 | 546 | 676 | ||
1235 | 547 | def fake_gtn(*args): | 677 | def fake_gtn(*args): |
1236 | @@ -562,6 +692,7 @@ | |||
1237 | 562 | sso_login_processor_class=self.mockprocessorclass) | 692 | sso_login_processor_class=self.mockprocessorclass) |
1238 | 563 | self.patch(client, "LoggedIn", d.errback) | 693 | self.patch(client, "LoggedIn", d.errback) |
1239 | 564 | self.patch(client, "LoginError", verify) | 694 | self.patch(client, "LoginError", verify) |
1240 | 695 | self.patch(client, "UserNotValidated", d.errback) | ||
1241 | 565 | client.login(APP_NAME, EMAIL, PASSWORD) | 696 | client.login(APP_NAME, EMAIL, PASSWORD) |
1242 | 566 | return d | 697 | return d |
1243 | 567 | 698 | ||
1244 | @@ -591,7 +722,7 @@ | |||
1245 | 591 | def test_validate_email_error(self): | 722 | def test_validate_email_error(self): |
1246 | 592 | """Test that the validate_email method fails as expected.""" | 723 | """Test that the validate_email method fails as expected.""" |
1247 | 593 | d = Deferred() | 724 | d = Deferred() |
1249 | 594 | self.mockprocessorclass = self.mocker.mock() | 725 | self.create_mock_processor() |
1250 | 595 | self.patch(ubuntu_sso.main, "blocking", self.fake_err_blocking) | 726 | self.patch(ubuntu_sso.main, "blocking", self.fake_err_blocking) |
1251 | 596 | 727 | ||
1252 | 597 | def fake_gtn(*args): | 728 | def fake_gtn(*args): |
1253 | @@ -802,7 +933,7 @@ | |||
1254 | 802 | self.assertEqual(result["errtype"], e.__class__.__name__) | 933 | self.assertEqual(result["errtype"], e.__class__.__name__) |
1255 | 803 | 934 | ||
1256 | 804 | 935 | ||
1258 | 805 | class KeyringCredentialsTestCase(MockerTestCase): | 936 | class KeyringCredentialsTestCase(TestCase, MockerTestCase): |
1259 | 806 | """Check the functions that access the keyring.""" | 937 | """Check the functions that access the keyring.""" |
1260 | 807 | 938 | ||
1261 | 808 | # Invalid name (should match ([a-z_][a-z0-9_]*|[A-Z_][A-Z0-9_]*)$) | 939 | # Invalid name (should match ([a-z_][a-z0-9_]*|[A-Z_][A-Z0-9_]*)$) |
1262 | @@ -810,15 +941,19 @@ | |||
1263 | 810 | 941 | ||
1264 | 811 | def test_keyring_store_cred(self): | 942 | def test_keyring_store_cred(self): |
1265 | 812 | """Verify the method that stores credentials.""" | 943 | """Verify the method that stores credentials.""" |
1266 | 944 | idle_add = lambda f, *args, **kwargs: f(*args, **kwargs) | ||
1267 | 945 | self.patch(gobject, "idle_add", idle_add) | ||
1268 | 813 | token_value = TOKEN | 946 | token_value = TOKEN |
1269 | 814 | mockKeyringClass = self.mocker.replace("ubuntu_sso.keyring.Keyring") | 947 | mockKeyringClass = self.mocker.replace("ubuntu_sso.keyring.Keyring") |
1270 | 815 | mockKeyringClass(APP_NAME) | 948 | mockKeyringClass(APP_NAME) |
1271 | 816 | mockKeyring = self.mocker.mock() | 949 | mockKeyring = self.mocker.mock() |
1272 | 950 | callback = self.mocker.mock() | ||
1273 | 817 | self.mocker.result(mockKeyring) | 951 | self.mocker.result(mockKeyring) |
1274 | 818 | mockKeyring.set_ubuntusso_attr(token_value) | 952 | mockKeyring.set_ubuntusso_attr(token_value) |
1275 | 953 | callback(1, 2, 3) | ||
1276 | 819 | self.mocker.replay() | 954 | self.mocker.replay() |
1277 | 820 | 955 | ||
1279 | 821 | keyring_store_credentials(APP_NAME, token_value) | 956 | keyring_store_credentials(APP_NAME, token_value, callback, 1, 2, 3) |
1280 | 822 | 957 | ||
1281 | 823 | def test_keyring_get_cred(self): | 958 | def test_keyring_get_cred(self): |
1282 | 824 | """The method returns the right token.""" | 959 | """The method returns the right token.""" |
1283 | @@ -1367,6 +1502,24 @@ | |||
1284 | 1367 | self.assertEqual(self.calls[0][0], 'CredentialsError') | 1502 | self.assertEqual(self.calls[0][0], 'CredentialsError') |
1285 | 1368 | self.assertEqual(self.calls[0][1][0], APP_NAME) | 1503 | self.assertEqual(self.calls[0][1][0], APP_NAME) |
1286 | 1369 | 1504 | ||
1287 | 1505 | def test_credentials_are_not_stored_if_ping_failed(self): | ||
1288 | 1506 | """Credentials are not stored if the ping fails.""" | ||
1289 | 1507 | |||
1290 | 1508 | def fail(*args, **kwargs): | ||
1291 | 1509 | """Raise an exception.""" | ||
1292 | 1510 | self.args = AssertionError((args, kwargs)) | ||
1293 | 1511 | # pylint: disable=E0702 | ||
1294 | 1512 | raise self.args | ||
1295 | 1513 | |||
1296 | 1514 | self.patch(self.client, '_ping_url', fail) | ||
1297 | 1515 | self._patch('clear_token') | ||
1298 | 1516 | |||
1299 | 1517 | self.client._login_success_cb(None, APP_NAME, EMAIL) | ||
1300 | 1518 | |||
1301 | 1519 | self.assertEqual(len(self.calls), 1) | ||
1302 | 1520 | self.assertEqual(self.calls[0][0], 'clear_token') | ||
1303 | 1521 | self.assertEqual(self.calls[0][1][0], APP_NAME) | ||
1304 | 1522 | |||
1305 | 1370 | 1523 | ||
1306 | 1371 | class EnvironOverridesTestCase(TestCase): | 1524 | class EnvironOverridesTestCase(TestCase): |
1307 | 1372 | """Some URLs can be set from the environment for testing/QA purposes.""" | 1525 | """Some URLs can be set from the environment for testing/QA purposes.""" |