Merge lp:~ralsina/ubuntu-sso-client/login-user-password into lp:ubuntu-sso-client
- login-user-password
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Roberto Alsina | ||||
Approved revision: | 786 | ||||
Merged at revision: | 749 | ||||
Proposed branch: | lp:~ralsina/ubuntu-sso-client/login-user-password | ||||
Merge into: | lp:ubuntu-sso-client | ||||
Diff against target: |
401 lines (+198/-14) 8 files modified
ubuntu_sso/credentials.py (+32/-3) ubuntu_sso/main/__init__.py (+9/-0) ubuntu_sso/main/linux.py (+6/-0) ubuntu_sso/main/tests/test_common.py (+1/-1) ubuntu_sso/main/tests/test_windows.py (+0/-1) ubuntu_sso/main/windows.py (+39/-9) ubuntu_sso/qt/tests/login_u_p.py (+54/-0) ubuntu_sso/tests/test_credentials.py (+57/-0) |
||||
To merge this branch: | bzr merge lp:~ralsina/ubuntu-sso-client/login-user-password | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alejandro J. Cura (community) | Approve | ||
Natalia Bidart (community) | Approve | ||
Review via email: mp+69336@code.launchpad.net |
Commit message
Add a login_user_password method to the Credential and CredentialManag
login using that.
Description of the change
Add a login_user_password method to the Credential and CredentialManag
login using that.
Alejandro J. Cura (alecu) wrote : | # |
Tested IRL ok and code looks great!
Ubuntu One Auto Pilot (otto-pilot) wrote : | # |
There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.
Ubuntu One Auto Pilot (otto-pilot) wrote : | # |
The attempt to merge lp:~ralsina/ubuntu-sso-client/login-user-password into lp:ubuntu-sso-client failed. Below is the output from the failed tests.
Running test suite for ubuntu_sso
Xlib: extension "RANDR" missing on display ":99".
ubuntu_
GetPasswordSt
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
test_
IsCorrectEmai
test_
test_
IsMinRequired
test_
test_
test_no_number ... [OK]
test_
ubuntu_
AltItemTestCase
test_
test_
BaseTestCase
runTest ... [OK]
CollectionTes
test_
test_
test_
test_
- 783. By Roberto Alsina
-
Oops
- 784. By Roberto Alsina
-
Oops
- 785. By Roberto Alsina
-
remove test that can't work on linux
- 786. By Roberto Alsina
-
style fix:
Preview Diff
1 | === modified file 'ubuntu_sso/credentials.py' |
2 | --- ubuntu_sso/credentials.py 2011-01-02 03:34:23 +0000 |
3 | +++ ubuntu_sso/credentials.py 2011-07-29 14:29:55 +0000 |
4 | @@ -50,7 +50,6 @@ |
5 | from ubuntu_sso.keyring import Keyring |
6 | from ubuntu_sso.logger import setup_logging |
7 | |
8 | - |
9 | logger = setup_logging('ubuntu_sso.credentials') |
10 | |
11 | |
12 | @@ -184,6 +183,7 @@ |
13 | self._error_cb = error_cb |
14 | self.denial_cb = denial_cb |
15 | self.gui = None # will hold the GUI instance |
16 | + self.login_root = None # Will hold SSOLoginRoot instance |
17 | |
18 | @handle_failures(msg='Problem while retrieving credentials') |
19 | @inlineCallbacks |
20 | @@ -263,15 +263,39 @@ |
21 | self.gui.registration_success_callback = self._login_success_cb |
22 | self.gui.user_cancellation_callback = self._auth_denial_cb |
23 | |
24 | + @handle_exceptions(msg='Problem logging with email and password.') |
25 | + def _do_login(self, email, password): |
26 | + """Login using email/password, connect outcome signals.""" |
27 | + from ubuntu_sso.main import SSOLoginRoot |
28 | + |
29 | + def error(app_name, error): |
30 | + """Call error_cb with the right number of arguments.""" |
31 | + self.error_cb(error) |
32 | + |
33 | + self.login_root = SSOLoginRoot() |
34 | + self.login_root.login( |
35 | + self.app_name, |
36 | + email, |
37 | + password, |
38 | + self._login_success_cb, |
39 | + error, |
40 | + error, |
41 | + ) |
42 | + |
43 | @handle_failures(msg='Problem while retrieving credentials') |
44 | @inlineCallbacks |
45 | - def _login_or_register(self, login_only): |
46 | + def _login_or_register(self, login_only, email=None, password=None): |
47 | """Get credentials if found else prompt the GUI.""" |
48 | + logger.info("_login_or_register: login_only=%r email=%r.", |
49 | + login_only, email) |
50 | token = yield self.find_credentials() |
51 | if token is not None and len(token) > 0: |
52 | self.success_cb(token) |
53 | elif token == {}: |
54 | - self._show_ui(login_only) |
55 | + if email and password: |
56 | + self._do_login(email, password) |
57 | + else: |
58 | + self._show_ui(login_only) |
59 | else: |
60 | # something went wrong with find_credentials, already handled. |
61 | logger.info('_login_or_register: call to "find_credentials" went ' |
62 | @@ -313,3 +337,8 @@ |
63 | def login(self): |
64 | """Get credentials if found else prompt the GUI to login.""" |
65 | return self._login_or_register(login_only=True) |
66 | + |
67 | + def login_email_password(self, email, password): |
68 | + """Login using email and password.""" |
69 | + return self._login_or_register(login_only=True, |
70 | + email=email, password=password) |
71 | |
72 | === modified file 'ubuntu_sso/main/__init__.py' |
73 | --- ubuntu_sso/main/__init__.py 2011-07-26 13:11:33 +0000 |
74 | +++ ubuntu_sso/main/__init__.py 2011-07-29 14:29:55 +0000 |
75 | @@ -399,6 +399,15 @@ |
76 | obj = Credentials(app_name, **self._parse_args(args)) |
77 | obj.login() |
78 | |
79 | + def login_email_password(self, app_name, args): |
80 | + """Get credentials if found else prompt GUI to login.""" |
81 | + self.ref_count += 1 |
82 | + email = args.get('email') |
83 | + password = args.get('password') |
84 | + obj = Credentials(app_name, **self._parse_args(args)) |
85 | + obj.login_email_password(email, password) |
86 | + |
87 | + |
88 | # pylint: disable=C0103 |
89 | SSOLogin = None |
90 | SSOCredentials = None |
91 | |
92 | === modified file 'ubuntu_sso/main/linux.py' |
93 | --- ubuntu_sso/main/linux.py 2011-07-26 13:45:36 +0000 |
94 | +++ ubuntu_sso/main/linux.py 2011-07-29 14:29:55 +0000 |
95 | @@ -462,3 +462,9 @@ |
96 | def login(self, app_name, args): |
97 | """Get credentials if found else prompt GUI to login.""" |
98 | self.root.login(app_name, args) |
99 | + |
100 | + @dbus.service.method(dbus_interface=DBUS_CREDENTIALS_IFACE, |
101 | + in_signature='sa{ss}', out_signature='') |
102 | + def login_email_password(self, app_name, args): |
103 | + """Get credentials if found, else login.""" |
104 | + raise NotImplementedError |
105 | |
106 | === modified file 'ubuntu_sso/main/tests/test_common.py' |
107 | --- ubuntu_sso/main/tests/test_common.py 2011-07-26 13:45:36 +0000 |
108 | +++ ubuntu_sso/main/tests/test_common.py 2011-07-29 14:29:55 +0000 |
109 | @@ -189,7 +189,7 @@ |
110 | self.cred.clear_token(app_name, result_cb, error_cb) |
111 | |
112 | |
113 | -class CredentialsManagementMockedTestCase(MockerTestCase): |
114 | +class CredentialsManagementMockedTestCase(MockerTestCase, TestCase): |
115 | """Test that the call are relied correctly.""" |
116 | |
117 | def setUp(self): |
118 | |
119 | === modified file 'ubuntu_sso/main/tests/test_windows.py' |
120 | --- ubuntu_sso/main/tests/test_windows.py 2011-07-27 19:47:59 +0000 |
121 | +++ ubuntu_sso/main/tests/test_windows.py 2011-07-29 14:29:55 +0000 |
122 | @@ -1331,7 +1331,6 @@ |
123 | self.assertEqual(connect_result, ussoc) |
124 | self.assertTrue(mac.port_requested, "The port must be requested.") |
125 | self.assertNotEqual(ussoc.sso_login, None) |
126 | - self.assertNotEqual(ussoc.sso_cred, None) |
127 | self.assertNotEqual(ussoc.cred_management, None) |
128 | |
129 | def test_get_activation_cmdline(self): |
130 | |
131 | === modified file 'ubuntu_sso/main/windows.py' |
132 | --- ubuntu_sso/main/windows.py 2011-07-27 19:47:59 +0000 |
133 | +++ ubuntu_sso/main/windows.py 2011-07-29 14:29:55 +0000 |
134 | @@ -17,6 +17,8 @@ |
135 | # with this program. If not, see <http://www.gnu.org/licenses/>. |
136 | """Main implementation on windows.""" |
137 | |
138 | +import warnings |
139 | + |
140 | # pylint: disable=F0401 |
141 | from _winreg import HKEY_LOCAL_MACHINE, OpenKey, QueryValueEx |
142 | |
143 | @@ -74,9 +76,25 @@ |
144 | |
145 | |
146 | def remote_handler(handler): |
147 | - """Execute a callback in a remote object.""" |
148 | + """Execute a callback in a remote object. |
149 | + |
150 | + If the callback takes arguments, it's assumed that the last |
151 | + one is a twisted Failure, and it has no keyword arguments. |
152 | + """ |
153 | if handler: |
154 | - return lambda: handler.callRemote('execute') |
155 | + |
156 | + def f(*args): |
157 | + """Process arguments and call remote.""" |
158 | + try: |
159 | + args = list(args) |
160 | + if args: |
161 | + args[-1] = except_to_errdict(args[-1].value) |
162 | + return handler.callRemote('execute', *args) |
163 | + # Yes, I want to catch everything |
164 | + # pylint: disable=W0703 |
165 | + except Exception: |
166 | + logger.exception("Remote handler argument processing error:") |
167 | + return f |
168 | return lambda: None |
169 | |
170 | |
171 | @@ -102,7 +120,8 @@ |
172 | # the calls in twisted will be called with the args in a diff order, |
173 | # in order to follow the linux api, we swap them around with a lambda |
174 | d.addCallback(lambda result, app: result_cb(app, result), app_name) |
175 | - d.addErrback(lambda err, app: error_cb(app, err), app_name) |
176 | + d.addErrback(lambda err, app: error_cb(app, |
177 | + except_to_errdict(err.value)), app_name) |
178 | |
179 | |
180 | class RemoteMeta(type): |
181 | @@ -440,6 +459,7 @@ |
182 | 'register', |
183 | 'shutdown', |
184 | 'login', |
185 | + 'login_email_password', |
186 | ] |
187 | |
188 | def __init__(self, timeout_func, shutdown_func, *args, **kwargs): |
189 | @@ -557,6 +577,10 @@ |
190 | """Get credentials if found else prompt GUI to login.""" |
191 | self.root.login(app_name, args) |
192 | |
193 | + def login_email_password(self, app_name, args): |
194 | + """Get credentials if found, else login.""" |
195 | + self.root.login_email_password(app_name, args) |
196 | + |
197 | |
198 | class UbuntuSSORoot(object, Root): |
199 | """Root object that exposes the diff referenceable objects.""" |
200 | @@ -638,10 +662,10 @@ |
201 | """Create a new instance.""" |
202 | self.cb = cb |
203 | |
204 | - def remote_execute(self): |
205 | + def remote_execute(self, *args, **kwargs): |
206 | """Execute the callback.""" |
207 | if self.cb: |
208 | - self.cb() |
209 | + self.cb(*args, **kwargs) |
210 | |
211 | |
212 | def callbacks(callbacks_indexes=None, callbacks_names=None): |
213 | @@ -775,7 +799,10 @@ |
214 | |
215 | |
216 | class SSOCredentialsClient(RemoteClient, Referenceable): |
217 | - """Client that can perform calls to the remote SSOCredentials object.""" |
218 | + """Deprecated client for the remote SSOCredentials object. |
219 | + |
220 | + This class is deprecated! |
221 | + """ |
222 | |
223 | __metaclass__ = RemoteMeta |
224 | |
225 | @@ -788,6 +815,8 @@ |
226 | |
227 | def __init__(self, remote_login): |
228 | """Create a client for the cred API.""" |
229 | + warnings.warn("SSOCredentialsClient is deprecated.", |
230 | + DeprecationWarning) |
231 | super(SSOCredentialsClient, self).__init__(remote_login) |
232 | |
233 | @signal |
234 | @@ -933,6 +962,10 @@ |
235 | def login(self, app_name, args): |
236 | """Get credentials if found else prompt GUI to login.""" |
237 | |
238 | + @remote |
239 | + def login_email_password(self, app_name, args): |
240 | + """Get credentials if found else login.""" |
241 | + |
242 | |
243 | class UbuntuSSOClientException(Exception): |
244 | """Raised when there are issues connecting to the process.""" |
245 | @@ -943,7 +976,6 @@ |
246 | |
247 | def __init__(self): |
248 | self.sso_login = None |
249 | - self.sso_cred = None |
250 | self.cred_management = None |
251 | self.factory = None |
252 | self.client = None |
253 | @@ -954,8 +986,6 @@ |
254 | sso_login = yield root.callRemote('get_sso_login') |
255 | logger.debug('SSOLogin is %s', sso_login) |
256 | self.sso_login = SSOLoginClient(sso_login) |
257 | - sso_cred = yield root.callRemote('get_sso_credentials') |
258 | - self.sso_cred = SSOCredentialsClient(sso_cred) |
259 | cred_management = yield root.callRemote('get_cred_manager') |
260 | self.cred_management = CredentialsManagementClient(cred_management) |
261 | defer.returnValue(self) |
262 | |
263 | === added file 'ubuntu_sso/qt/tests/login_u_p.py' |
264 | --- ubuntu_sso/qt/tests/login_u_p.py 1970-01-01 00:00:00 +0000 |
265 | +++ ubuntu_sso/qt/tests/login_u_p.py 2011-07-29 14:29:55 +0000 |
266 | @@ -0,0 +1,54 @@ |
267 | +# -*- coding: utf-8 -*- |
268 | +# Author: Manuel de la Pena <manuel@canonical.com> |
269 | +# |
270 | +# Copyright 2011 Canonical Ltd. |
271 | +# |
272 | +# This program is free software: you can redistribute it and/or modify it |
273 | +# under the terms of the GNU General Public License version 3, as published |
274 | +# by the Free Software Foundation. |
275 | +# |
276 | +# This program is distributed in the hope that it will be useful, but |
277 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
278 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
279 | +# PURPOSE. See the GNU General Public License for more details. |
280 | +# |
281 | +# You should have received a copy of the GNU General Public License along |
282 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
283 | +"""Script that shows the qt gui.""" |
284 | + |
285 | +# pylint: disable=F0401, E1101 |
286 | +from twisted.internet import reactor |
287 | +from twisted.internet.defer import inlineCallbacks |
288 | +from ubuntu_sso.main.windows import UbuntuSSOClient |
289 | + |
290 | + |
291 | +def found(*args): |
292 | + """The credentials were found.""" |
293 | + print "creds found", args |
294 | + reactor.stop() |
295 | + |
296 | + |
297 | +def errback(*args): |
298 | + """Unsuccessful login.""" |
299 | + print "EB:", args |
300 | + |
301 | + |
302 | +@inlineCallbacks |
303 | +def main(): |
304 | + """Perform a client request to be logged in.""" |
305 | + client = UbuntuSSOClient() |
306 | + client = yield client.connect() |
307 | + yield client.cred_management.register_to_signals() |
308 | + client.cred_management.on_credentials_found_cb = found |
309 | + client.cred_management.on_credentials_error_cb = errback |
310 | + yield client.cred_management.login_email_password('SUPER', dict( |
311 | + app_name='SUPER', |
312 | + email='xyz@canonical.com', |
313 | + password='ABC', |
314 | + )) |
315 | + print "called ok" |
316 | + |
317 | + |
318 | +if __name__ == '__main__': |
319 | + main() |
320 | + reactor.run() |
321 | |
322 | === modified file 'ubuntu_sso/tests/test_credentials.py' |
323 | --- ubuntu_sso/tests/test_credentials.py 2011-03-09 17:04:41 +0000 |
324 | +++ ubuntu_sso/tests/test_credentials.py 2011-07-29 14:29:55 +0000 |
325 | @@ -26,8 +26,10 @@ |
326 | from twisted.internet.defer import inlineCallbacks |
327 | from twisted.trial.unittest import TestCase, FailTest |
328 | from ubuntuone.devtools.handlers import MementoHandler |
329 | +from ubuntuone.devtools.testcase import skipIfOS |
330 | |
331 | from ubuntu_sso import credentials |
332 | +import ubuntu_sso.main |
333 | from ubuntu_sso.credentials import (APP_NAME_KEY, HELP_TEXT_KEY, NO_OP, |
334 | PING_URL_KEY, TC_URL_KEY, UI_CLASS_KEY, UI_MODULE_KEY, WINDOW_ID_KEY, |
335 | ERROR_KEY, ERROR_DETAIL_KEY) |
336 | @@ -82,6 +84,18 @@ |
337 | self.user_cancellation_callback = None |
338 | |
339 | |
340 | +class FakedSSOLoginRoot(object): |
341 | + """Fake a SSOLoginRoot.""" |
342 | + |
343 | + args = [] |
344 | + kwargs = {} |
345 | + |
346 | + def login(self, *args, **kwargs): |
347 | + """Fake login.""" |
348 | + self.args = args |
349 | + self.kwargs = kwargs |
350 | + |
351 | + |
352 | class BasicTestCase(TestCase): |
353 | """Test case with a helper tracker.""" |
354 | |
355 | @@ -579,3 +593,46 @@ |
356 | |
357 | operation = 'login' |
358 | login_only = True |
359 | + |
360 | + |
361 | +class LoginUserPasswordTestCase(CredentialsTestCase): |
362 | + """Test suite for the login method.""" |
363 | + |
364 | + operation = 'login_email_password' |
365 | + email = 'email' |
366 | + password = 'password' |
367 | + |
368 | + def setUp(self): |
369 | + super(LoginUserPasswordTestCase, self).setUp() |
370 | + self.acc_kwargs = { |
371 | + APP_NAME_KEY: APP_NAME, |
372 | + 'email': self.email, |
373 | + 'password': self.password, |
374 | + } |
375 | + self.patch(ubuntu_sso.main, 'SSOLoginRoot', FakedSSOLoginRoot) |
376 | + |
377 | + @skipIfOS('linux2', 'Not implemented on Linux yet.') |
378 | + @inlineCallbacks |
379 | + def test_with_existent_token(self): |
380 | + """The operation returns the credentials if already in keyring.""" |
381 | + self.patch(credentials.Keyring, 'get_credentials', |
382 | + lambda kr, app: defer.succeed(TOKEN)) |
383 | + |
384 | + yield getattr(self.obj, self.operation)(self.email, self.password) |
385 | + self.assertEqual(self._called, (('success', APP_NAME, TOKEN), {})) |
386 | + |
387 | + @skipIfOS('linux2', 'Not implemented on Linux yet.') |
388 | + @inlineCallbacks |
389 | + def test_without_existent_token(self): |
390 | + """The operation returns the credentials obtained.""" |
391 | + self.patch(credentials.Keyring, 'get_credentials', |
392 | + lambda kr, app: defer.succeed(None)) |
393 | + |
394 | + yield getattr(self.obj, self.operation)(self.email, self.password) |
395 | + self.assertIsInstance(self.obj.login_root, FakedSSOLoginRoot) |
396 | + #pylint: disable=E1101 |
397 | + self.assertEqual(self.obj.login_root.args[:3], ( |
398 | + APP_NAME, |
399 | + self.email, |
400 | + self.password, |
401 | + )) |
Looks good!