Merge lp:~ralsina/ubuntu-sso-client/login-user-password into lp:ubuntu-sso-client

Proposed by Roberto Alsina
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
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 CredentialManagement classes so it's possible to
login using that.

Description of the change

Add a login_user_password method to the Credential and CredentialManagement classes so it's possible to
login using that.

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

Looks good!

review: Approve
Revision history for this message
Alejandro J. Cura (alecu) wrote :

Tested IRL ok and code looks great!

review: Approve
Revision history for this message
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.

Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :
Download full text (79.5 KiB)

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_sso.utils.tests.test_ui
  GetPasswordStrengTestCase
    test_eight_chars_and_num ... [OK]
    test_eight_chars_low_and_cap ... [OK]
    test_eight_chars_low_canp_num ... [OK]
    test_eight_chars_password ... [OK]
    test_eiqgh_chars_and_special ... [OK]
    test_eleven_chars_and_num ... [OK]
    test_eleven_chars_low_cap ... [OK]
    test_eleven_num_low_cap ... [OK]
    test_eleven_num_special ... [OK]
    test_long_password ... [OK]
    test_small_password ... [OK]
    test_too_small_password ... [OK]
  IsCorrectEmailAddress
    test_is_correct_email_false ... [OK]
    test_is_correct_email_true ... [OK]
  IsMinRequiredPasswordTestCase
    test_correct_password ... [OK]
    test_no_enough_chars ... [OK]
    test_no_number ... [OK]
    test_no_uppercase ... [OK]
ubuntu_sso.utils.tests.test_txsecrets
  AltItemTestCase
    test_create_item_four_fields_per_secret ... [OK]
    test_get_value_four_fields_per_secret ... [OK]
  BaseTestCase
    runTest ... [OK]
  CollectionTestCase
    test_create_item ... ERROR:dbus.connection:Unable to set arguments ({'org.freedesktop.Secret.Collection.Label': dbus.String(u'sample_keyring', variant_level=1)}, '') according to signature u'a{sv}': <type 'exceptions.TypeError'>: Fewer items found in D-Bus signature than in Python arguments
                                                  [OK]
    test_create_item_prompt ... ERROR:dbus.connection:Unable to set arguments ({'org.freedesktop.Secret.Collection.Label': dbus.String(u'sample_keyring', variant_level=1)}, '') according to signature u'a{sv}': <type 'exceptions.TypeError'>: Fewer items found in D-Bus signature than in Python arguments
                                           [OK]
    test_create_item_prompt_dismissed ... ERROR:dbus.connection:Unable to set arguments ({'org.freedesktop.Secret.Collection.Label': dbus.String(u'sample_keyring', variant_level=1)}, '') according to signature u'a{sv}': <type 'exceptions.TypeError'>: Fewer items found in D-Bus signature than in Python arguments
                                 [OK]
    test_create_item_throw...

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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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+ ))

Subscribers

People subscribed via source and target branches