Merge lp:~mandel/ubuntuone-client/provide_credentials_management into lp:ubuntuone-client

Proposed by Manuel de la Peña
Status: Merged
Approved by: Roberto Alsina
Approved revision: 995
Merged at revision: 984
Proposed branch: lp:~mandel/ubuntuone-client/provide_credentials_management
Merge into: lp:ubuntuone-client
Prerequisite: lp:~mandel/ubuntuone-client/pass_main_to_ipc_root
Diff against target: 1019 lines (+702/-230)
8 files modified
po/POTFILES.in (+1/-0)
tests/platform/linux/test_credentials.py (+4/-5)
tests/platform/windows/test_credentials.py (+155/-0)
tests/test_credentials.py (+99/-0)
ubuntuone/credentials.py (+255/-0)
ubuntuone/platform/linux/__init__.py (+1/-1)
ubuntuone/platform/linux/credentials.py (+56/-224)
ubuntuone/platform/windows/credentials.py (+131/-0)
To merge this branch: bzr merge lp:~mandel/ubuntuone-client/provide_credentials_management
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve
Shane Fagan (community) Approve
Review via email: mp+59743@code.launchpad.net

Commit message

This branch fixed the issue where windows does not have credential management code. This branch does the following:

* Refactor the CredentialsManagementTool so that it can be used by other platforms.
* Implemented the CredentialsManagement code for Windows.

Description of the change

This branch fixed the issue where windows does not have credential management code. This branch does the following:

* Refactor the CredentialsManagementTool so that it can be used by other platforms.
* Implemented the CredentialsManagement code for Windows.

This branch might break control panel (to be confirmed) and has to be tested in both platforms (windows/linux)

On Linux:
$ ./autogen
$ make check

On Windows:

python C:\Python27\Scripts\u1trial tests\platform\windows\test_credentials

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

Passes tests and nothing big pops out in the code

review: Approve
Revision history for this message
Roberto Alsina (ralsina) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'po/POTFILES.in'
2--- po/POTFILES.in 2011-02-21 23:16:03 +0000
3+++ po/POTFILES.in 2011-05-03 09:17:06 +0000
4@@ -1,6 +1,7 @@
5 ubuntuone/clientdefs.py.in
6 ubuntuone/status/aggregator.py
7 ubuntuone/platform/linux/credentials.py
8+ubuntuone/platform/windows/credentials.py
9 data/emblem-ubuntuone-downloading.icon.in
10 data/emblem-ubuntuone-unsynchronized.icon.in
11 data/emblem-ubuntuone-uploading.icon.in
12
13=== modified file 'tests/platform/linux/test_credentials.py'
14--- tests/platform/linux/test_credentials.py 2011-02-15 20:32:42 +0000
15+++ tests/platform/linux/test_credentials.py 2011-05-03 09:17:06 +0000
16@@ -25,12 +25,11 @@
17 from ubuntuone.devtools.handlers import MementoHandler
18
19 from ubuntuone.platform.linux.credentials import (dbus, logger, logging,
20- CredentialsManagement, CredentialsManagementTool, CredentialsError,
21- ubuntu_sso,
22- DBUS_BUS_NAME, DBUS_CREDENTIALS_PATH, DBUS_CREDENTIALS_IFACE,
23- APP_NAME, HELP_TEXT_KEY, DESCRIPTION, TC_URL_KEY, TC_URL,
24- PING_URL_KEY, PING_URL, TIMEOUT_INTERVAL,
25+ CredentialsManagement, ubuntu_sso, DBUS_BUS_NAME, DBUS_CREDENTIALS_PATH,
26+ DBUS_CREDENTIALS_IFACE, APP_NAME, HELP_TEXT_KEY, DESCRIPTION,
27+ TC_URL_KEY, TC_URL, PING_URL_KEY, PING_URL, TIMEOUT_INTERVAL,
28 )
29+from ubuntuone.credentials import CredentialsManagementTool, CredentialsError
30
31 FAKED_CREDENTIALS = {
32 'consumer_key': 'faked_consumer_key',
33
34=== added file 'tests/platform/windows/test_credentials.py'
35--- tests/platform/windows/test_credentials.py 1970-01-01 00:00:00 +0000
36+++ tests/platform/windows/test_credentials.py 2011-05-03 09:17:06 +0000
37@@ -0,0 +1,155 @@
38+#!/usr/bin/env python
39+# -*- coding: utf-8 -*-
40+# Author: Manuel de la Pena <manuel@canonical.com>
41+#
42+# Copyright 2011 Canonical Ltd.
43+#
44+# This program is free software: you can redistribute it and/or modify it
45+# under the terms of the GNU General Public License version 3, as published
46+# by the Free Software Foundation.
47+#
48+# This program is distributed in the hope that it will be useful, but
49+# WITHOUT ANY WARRANTY; without even the implied warranties of
50+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
51+# PURPOSE. See the GNU General Public License for more details.
52+#
53+# You should have received a copy of the GNU General Public License along
54+# with this program. If not, see <http://www.gnu.org/licenses/>.
55+"""Tests for the credentials management on Windows."""
56+
57+from mocker import MockerTestCase
58+
59+from ubuntu_sso.credentials import HELP_TEXT_KEY, PING_URL_KEY, TC_URL_KEY
60+from ubuntuone.platform.windows.credentials import (
61+ CredentialsManagement,
62+ APP_NAME,
63+ DESCRIPTION,
64+ PING_URL,
65+ TC_URL)
66+
67+
68+class TestCredentialsManagement(MockerTestCase):
69+ """Test that the credentials management is correctly used."""
70+
71+ def setUp(self):
72+ """Set the different tests."""
73+ super(TestCredentialsManagement, self).setUp()
74+ self.proxy = self.mocker.mock()
75+ self.management = CredentialsManagement(self.proxy)
76+
77+ def test_find_credentials(self):
78+ """Ensure we do ask corectly for the credentials."""
79+ reply_handler = lambda: None
80+ error_handler = lambda: None
81+ self.proxy.find_credentials(APP_NAME, {}, reply_handler=reply_handler,
82+ error_handler=error_handler)
83+ self.mocker.replay()
84+ self.management.find_credentials(reply_handler=reply_handler,
85+ error_handler=error_handler)
86+
87+ def test_clear_credentials(self):
88+ """Ensure we do clear the credentials."""
89+ reply_handler = lambda: None
90+ error_handler = lambda: None
91+ self.proxy.clear_credentials(APP_NAME, {}, reply_handler=reply_handler,
92+ error_handler=error_handler)
93+ self.mocker.replay()
94+ self.management.clear_credentials(reply_handler=reply_handler,
95+ error_handler=error_handler)
96+
97+ def test_store_credentials(self):
98+ """Store the token for Ubuntu One application."""
99+ credentials = 'creds'
100+ reply_handler = lambda: None
101+ error_handler = lambda: None
102+ self.proxy.store_credentials(APP_NAME, credentials,
103+ reply_handler=reply_handler, error_handler=error_handler)
104+ self.mocker.replay()
105+ self.management.store_credentials(credentials,
106+ reply_handler=reply_handler, error_handler=error_handler)
107+
108+ def test_register(self):
109+ """Get credentials if found else prompt to register to Ubuntu One."""
110+ reply_handler = lambda: None
111+ error_handler = lambda: None
112+ args = dict(test='test', args='args')
113+ extra_params = {HELP_TEXT_KEY: DESCRIPTION, TC_URL_KEY: TC_URL,
114+ PING_URL_KEY: PING_URL}
115+ extra_params.update(args)
116+ self.proxy.register(APP_NAME, extra_params,
117+ reply_handler=reply_handler, error_handler=error_handler)
118+ self.mocker.replay()
119+ self.management.register(args, reply_handler, error_handler)
120+
121+ def test_login(self):
122+ """Get credentials if found else prompt to login to Ubuntu One."""
123+ reply_handler = lambda: None
124+ error_handler = lambda: None
125+ args = dict(test='test', args='args')
126+ extra_params = {HELP_TEXT_KEY: DESCRIPTION, TC_URL_KEY: TC_URL,
127+ PING_URL_KEY: PING_URL}
128+ extra_params.update(args)
129+ self.proxy.login(APP_NAME, extra_params,
130+ reply_handler=reply_handler, error_handler=error_handler)
131+ self.mocker.replay()
132+ self.management.login(args, reply_handler, error_handler)
133+
134+ def test_register_to_credentials_stored(self):
135+ """Register to the CredentialsStored dbus signal."""
136+ callback = lambda: None
137+ self.proxy.on_credentials_stored_cb = callback
138+ self.proxy.on_credentials_stored_cb
139+ self.mocker.result(callback)
140+ self.mocker.replay()
141+ self.assertIs(callback,
142+ self.management.register_to_credentials_stored(callback))
143+
144+ def test_register_to_credentials_cleared(self):
145+ """Register to the CredentialsCleared dbus signal."""
146+ callback = lambda: None
147+ self.proxy.on_credentials_cleared_cb = callback
148+ self.proxy.on_credentials_cleared_cb
149+ self.mocker.result(callback)
150+ self.mocker.replay()
151+ self.assertIs(callback,
152+ self.management.register_to_credentials_cleared(callback))
153+
154+ def test_register_to_credentials_found(self):
155+ """Register to the CredentialsFound dbus signal."""
156+ callback = lambda: None
157+ self.proxy.on_credentials_found_cb = callback
158+ self.proxy.on_credentials_found_cb
159+ self.mocker.result(callback)
160+ self.mocker.replay()
161+ self.assertIs(callback,
162+ self.management.register_to_credentials_found(callback))
163+
164+ def test_register_to_credentials_not_found(self):
165+ """Register to the CredentialsFound dbus signal."""
166+ callback = lambda: None
167+ self.proxy.on_credentials_not_found_cb = callback
168+ self.proxy.on_credentials_not_found_cb
169+ self.mocker.result(callback)
170+ self.mocker.replay()
171+ self.assertIs(callback,
172+ self.management.register_to_credentials_not_found(callback))
173+
174+ def test_register_to_authorization_denied(self):
175+ """Register to the AuthorizationDenied dbus signal."""
176+ callback = lambda: None
177+ self.proxy.on_authorization_denied_cb = callback
178+ self.proxy.on_authorization_denied_cb
179+ self.mocker.result(callback)
180+ self.mocker.replay()
181+ self.assertIs(callback,
182+ self.management.register_to_authorization_denied(callback))
183+
184+ def test_register_to_credentials_error(self):
185+ """Register to the CredentialsError dbus signal."""
186+ callback = lambda: None
187+ self.proxy.on_credentials_error_cb = callback
188+ self.proxy.on_credentials_error_cb
189+ self.mocker.result(callback)
190+ self.mocker.replay()
191+ self.assertIs(callback,
192+ self.management.register_to_credentials_error(callback))
193
194=== added file 'tests/test_credentials.py'
195--- tests/test_credentials.py 1970-01-01 00:00:00 +0000
196+++ tests/test_credentials.py 2011-05-03 09:17:06 +0000
197@@ -0,0 +1,99 @@
198+#!/usr/bin/env python
199+# -*- coding: utf-8 -*-
200+#
201+# Author: Manuel de la Pena<manuel@canonical.com>
202+#
203+# Copyright 2011 Canonical Ltd.
204+#
205+# This program is free software: you can redistribute it and/or modify it
206+# under the terms of the GNU General Public License version 3, as published
207+# by the Free Software Foundation.
208+#
209+# This program is distributed in the hope that it will be useful, but
210+# WITHOUT ANY WARRANTY; without even the implied warranties of
211+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
212+# PURPOSE. See the GNU General Public License for more details.
213+#
214+# You should have received a copy of the GNU General Public License along
215+# with this program. If not, see <http://www.gnu.org/licenses/>.
216+"""Platform independent tests for the credentials management."""
217+
218+from mocker import MockerTestCase, MATCH
219+
220+from ubuntuone.credentials import CredentialsManagementTool
221+
222+
223+class TestCredentialsManagementTool(MockerTestCase):
224+ """Test the crendentials management tool mocking the proxy."""
225+
226+ def setUp(self):
227+ """Set the diff tests."""
228+ super(TestCredentialsManagementTool, self).setUp()
229+ self.get_cred_proxy = self.mocker.replace(
230+ 'ubuntuone.platform.get_creds_proxy')
231+ self.proxy = self.mocker.mock()
232+ self.management_tool = CredentialsManagementTool()
233+
234+ def test_find_credentials(self):
235+ """Test that we do ask for the credentials correctly."""
236+ signals = ['creds_found', 'creds_not_found', 'creds_erro']
237+ self.get_cred_proxy()
238+ self.mocker.result(self.proxy)
239+ self.proxy.register_to_credentials_found(MATCH(callable))
240+ self.mocker.result(signals[0])
241+ self.proxy.register_to_credentials_not_found(MATCH(callable))
242+ self.mocker.result(signals[1])
243+ self.proxy.register_to_credentials_error(MATCH(callable))
244+ self.mocker.result(signals[2])
245+ self.proxy.find_credentials(reply_handler=MATCH(callable),
246+ error_handler=MATCH(callable))
247+ self.mocker.replay()
248+ return self.management_tool.find_credentials()
249+
250+ def test_clear_credentials(self):
251+ """Test that we clear the credentials correctly."""
252+ signals = ['creds_cleared', 'creds_error']
253+ self.get_cred_proxy()
254+ self.mocker.result(self.proxy)
255+ self.proxy.register_to_credentials_cleared(MATCH(callable))
256+ self.mocker.result(signals[0])
257+ self.proxy.register_to_credentials_error(MATCH(callable))
258+ self.mocker.result(signals[1])
259+ self.proxy.clear_credentials(reply_handler=MATCH(callable),
260+ error_handler=MATCH(callable))
261+ self.mocker.replay()
262+ return self.management_tool.clear_credentials()
263+
264+ def test_store_credentials(self):
265+ """Test that we store the credentials correctly."""
266+ token = 'token'
267+ signals = ['creds_stored','creds_error']
268+ self.get_cred_proxy()
269+ self.mocker.result(self.proxy)
270+ self.proxy.register_to_credentials_stored(MATCH(callable))
271+ self.mocker.result(signals[0])
272+ self.proxy.register_to_credentials_error(MATCH(callable))
273+ self.mocker.result(signals[1])
274+ self.proxy.store_credentials(token, reply_handler=MATCH(callable),
275+ error_handler=MATCH(callable))
276+ self.mocker.replay()
277+ return self.management_tool.store_credentials(token)
278+
279+ def test_register(self):
280+ """Test that we correctly register."""
281+ window_id = 10
282+ window_id_dict = dict(window_id=str(window_id))
283+ signals = ['creds_found', 'creds_denied', 'creds_error']
284+ self.get_cred_proxy()
285+ self.mocker.result(self.proxy)
286+ self.proxy.register_to_credentials_found(MATCH(callable))
287+ self.mocker.result(signals[0])
288+ self.proxy.register_to_authorization_denied(MATCH(callable))
289+ self.mocker.result(signals[1])
290+ self.proxy.register_to_credentials_error(MATCH(callable))
291+ self.mocker.result(signals[2])
292+ self.proxy.register(window_id_dict, reply_handler=MATCH(callable),
293+ error_handler=MATCH(callable))
294+ self.mocker.replay()
295+ return self.management_tool.register(window_id=window_id)
296+
297
298=== added file 'ubuntuone/credentials.py'
299--- ubuntuone/credentials.py 1970-01-01 00:00:00 +0000
300+++ ubuntuone/credentials.py 2011-05-03 09:17:06 +0000
301@@ -0,0 +1,255 @@
302+#!/usr/bin/env python
303+# -*- coding: utf-8 -*-
304+#
305+# Author: Natalia B. Bidart <natalia.bidart@canonical.com>
306+# Author: Manuel de la Pena<manuel@canonical.com>
307+#
308+# Copyright 2011 Canonical Ltd.
309+#
310+# This program is free software: you can redistribute it and/or modify it
311+# under the terms of the GNU General Public License version 3, as published
312+# by the Free Software Foundation.
313+#
314+# This program is distributed in the hope that it will be useful, but
315+# WITHOUT ANY WARRANTY; without even the implied warranties of
316+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
317+# PURPOSE. See the GNU General Public License for more details.
318+#
319+# You should have received a copy of the GNU General Public License along
320+# with this program. If not, see <http://www.gnu.org/licenses/>.
321+"""Common code for the credentials management."""
322+
323+import os
324+
325+from twisted.internet import defer
326+
327+from ubuntuone.logger import (basic_formatter, logging,
328+ CustomRotatingFileHandler, LOGFOLDER)
329+from ubuntuone.platform import get_creds_proxy
330+
331+LOG_LEVEL = logging.DEBUG
332+path = os.path.join(LOGFOLDER, 'credentials.log')
333+MAIN_HANDLER = CustomRotatingFileHandler(path)
334+MAIN_HANDLER.setFormatter(basic_formatter)
335+MAIN_HANDLER.setLevel(LOG_LEVEL)
336+
337+logger = logging.getLogger("ubuntuone.credentials")
338+logger.setLevel(LOG_LEVEL)
339+logger.addHandler(MAIN_HANDLER)
340+
341+
342+class CredentialsError(Exception):
343+ """A general exception when hadling credentilas."""
344+
345+
346+class CredentialsManagementTool(object):
347+ """Wrapper to CredentialsManagement.
348+
349+ The goal of this class is to abstract the caller from calling the DBus
350+ service implemented in the class CredentialsManagement.
351+
352+ """
353+
354+ def __init__(self):
355+ self._cleanup_signals = []
356+
357+ def cleanup(self, _):
358+ """Disconnect all the DBus signals."""
359+ for sig in self._cleanup_signals:
360+ logger.debug('cleanup: removing signal match %r', sig)
361+ sig.remove()
362+
363+ return _
364+
365+ @defer.inlineCallbacks
366+ def find_credentials(self):
367+ """Find credentials for Ubuntu One.
368+
369+ Return a deferred that, when fired, will return the credentials for
370+ Ubuntu One for the current logged in user.
371+
372+ The credentials is a dictionary with both string keys and values. The
373+ dictionary may be either empty if there are no credentials for the
374+ user, or will hold five items as follow:
375+
376+ - "name"
377+ - "token"
378+ - "token_secret"
379+ - "consumer_key"
380+ - "consumer_secret"
381+
382+ """
383+ d = defer.Deferred()
384+ d.addBoth(self.cleanup)
385+
386+ proxy = get_creds_proxy()
387+
388+ sig = proxy.register_to_credentials_found(d.callback)
389+ self._cleanup_signals.append(sig)
390+
391+ sig = proxy.register_to_credentials_not_found(lambda: d.callback({}))
392+ self._cleanup_signals.append(sig)
393+
394+ sig = proxy.register_to_credentials_error(
395+ lambda error_dict: d.errback(CredentialsError(error_dict)))
396+ self._cleanup_signals.append(sig)
397+
398+ done = defer.Deferred()
399+ proxy.find_credentials(reply_handler=lambda: done.callback(None),
400+ error_handler=lambda *a: done.errback(a))
401+
402+ yield done
403+
404+ result = yield d
405+ defer.returnValue(result)
406+
407+ @defer.inlineCallbacks
408+ def clear_credentials(self):
409+ """Clear credentials for Ubuntu One.
410+
411+ Return a deferred that, when fired, will return no result but will
412+ indicate that the Ubuntu One credentials for the current user were
413+ removed from the local keyring.
414+
415+ """
416+ d = defer.Deferred()
417+ d.addBoth(self.cleanup)
418+
419+ proxy = get_creds_proxy()
420+ sig = proxy.register_to_credentials_cleared(lambda: d.callback(None))
421+ self._cleanup_signals.append(sig)
422+
423+ sig = proxy.register_to_credentials_error(
424+ lambda error_dict: d.errback(CredentialsError(error_dict)))
425+ self._cleanup_signals.append(sig)
426+
427+ done = defer.Deferred()
428+ proxy.clear_credentials(reply_handler=lambda: done.callback(None),
429+ error_handler=lambda *a: done.errback(a))
430+
431+ yield done
432+
433+ yield d
434+
435+ @defer.inlineCallbacks
436+ def store_credentials(self, token):
437+ """Store credentials for Ubuntu One.
438+
439+ The parameter 'token' should be a dictionary that matches the
440+ description of the result of 'find_credentials'.
441+
442+ Return a deferred that, when fired, will return no result but will
443+ indicate that 'token' was stored in the local keyring as the new Ubuntu
444+ One credentials for the current user.
445+
446+ """
447+ d = defer.Deferred()
448+ d.addBoth(self.cleanup)
449+
450+ proxy = get_creds_proxy()
451+ sig = proxy.register_to_credentials_stored(lambda: d.callback(None))
452+ self._cleanup_signals.append(sig)
453+
454+ sig = proxy.register_to_credentials_error(
455+ lambda error_dict: d.errback(CredentialsError(error_dict)))
456+ self._cleanup_signals.append(sig)
457+
458+ done = defer.Deferred()
459+ proxy.store_credentials(token,
460+ reply_handler=lambda: done.callback(None),
461+ error_handler=lambda *a: done.errback(a))
462+
463+ yield done
464+
465+ yield d
466+
467+ @defer.inlineCallbacks
468+ def register(self, window_id=0):
469+ """Register to Ubuntu One.
470+
471+ Return a deferred that, when fired, will return the credentials for
472+ Ubuntu One for the current logged in user.
473+
474+ If there are no credentials for the current user, a GTK UI will be
475+ opened to invite the user to register to Ubuntu One. This UI provides
476+ options to either register (main screen) or login (secondary screen).
477+
478+ You can pass an optional 'window_id' parameter that will be used by the
479+ GTK UI to be set transient for it.
480+
481+ The returned credentials will be either a non-empty dictionary like the
482+ one described in 'find_credentials', or None. The latter indicates that
483+ there were no credentials for the user in the local keyring and that
484+ the user refused to register to Ubuntu One.
485+
486+ """
487+ d = defer.Deferred()
488+ d.addBoth(self.cleanup)
489+
490+ proxy = get_creds_proxy()
491+
492+ sig = proxy.register_to_credentials_found(d.callback)
493+ self._cleanup_signals.append(sig)
494+
495+ sig = proxy.register_to_authorization_denied(lambda: d.callback(None))
496+ self._cleanup_signals.append(sig)
497+
498+ sig = proxy.register_to_credentials_error(
499+ lambda error_dict: d.errback(CredentialsError(error_dict)))
500+ self._cleanup_signals.append(sig)
501+
502+ done = defer.Deferred()
503+ proxy.register({'window_id': str(window_id)},
504+ reply_handler=lambda: done.callback(None),
505+ error_handler=lambda *a: done.errback(a))
506+
507+ yield done
508+
509+ result = yield d
510+ defer.returnValue(result)
511+
512+ @defer.inlineCallbacks
513+ def login(self, window_id=0):
514+ """Login to Ubuntu One.
515+
516+ Return a deferred that, when fired, will return the credentials for
517+ Ubuntu One for the current logged in user.
518+
519+ If there are no credentials for the current user, a GTK UI will be
520+ opened to invite the user to login to Ubuntu One. This UI provides
521+ options to either login (main screen) or retrieve password (secondary
522+ screen).
523+
524+ You can pass an optional 'window_id' parameter that will be used by the
525+ GTK UI to be set transient for it.
526+
527+ The returned credentials will be either a non-empty dictionary like the
528+ one described in 'find_credentials', or None. The latter indicates that
529+ there were no credentials for the user in the local keyring and that
530+ the user refused to login to Ubuntu One.
531+
532+ """
533+ d = defer.Deferred()
534+ d.addBoth(self.cleanup)
535+
536+ proxy = get_creds_proxy()
537+
538+ sig = proxy.register_to_credentials_found(d.callback)
539+ self._cleanup_signals.append(sig)
540+
541+ sig = proxy.register_to_authorization_denied(lambda: d.callback(None))
542+ self._cleanup_signals.append(sig)
543+
544+ sig = proxy.register_to_credentials_error(
545+ lambda error_dict: d.errback(CredentialsError(error_dict)))
546+ self._cleanup_signals.append(sig)
547+
548+ done = defer.Deferred()
549+ proxy.login({'window_id': str(window_id)},
550+ reply_handler=lambda: done.callback(None),
551+ error_handler=lambda *a: done.errback(a))
552+
553+ yield done
554+
555+ result = yield d
556+ defer.returnValue(result)
557
558=== modified file 'ubuntuone/platform/linux/__init__.py'
559--- ubuntuone/platform/linux/__init__.py 2011-03-30 16:17:37 +0000
560+++ ubuntuone/platform/linux/__init__.py 2011-05-03 09:17:06 +0000
561@@ -51,7 +51,7 @@
562 get_udf_path,
563 VMMetadataUpgraderMixIn
564 )
565-from ubuntuone.platform.linux.credentials import CredentialsManagement
566+from ubuntuone.platform.linux.credentials import get_creds_proxy
567 from ubuntuone.platform.linux.logger import setup_filesystem_logging, get_filesystem_logger
568 from ubuntuone.platform.linux.filesystem_notifications import FilesystemMonitor
569 from ubuntuone.platform.linux.notification import Notification
570
571=== modified file 'ubuntuone/platform/linux/credentials.py'
572--- ubuntuone/platform/linux/credentials.py 2011-02-24 14:07:32 +0000
573+++ ubuntuone/platform/linux/credentials.py 2011-05-03 09:17:06 +0000
574@@ -15,7 +15,6 @@
575 #
576 # You should have received a copy of the GNU General Public License along
577 # with this program. If not, see <http://www.gnu.org/licenses/>.
578-
579 """Ubuntu One credentials management dbus service."""
580
581 import os
582@@ -24,7 +23,6 @@
583 import gettext
584 import ubuntu_sso
585
586-from twisted.internet import defer
587 from ubuntu_sso.credentials import HELP_TEXT_KEY, PING_URL_KEY, TC_URL_KEY
588
589 from ubuntuone.logger import (basic_formatter, logging,
590@@ -238,237 +236,71 @@
591 reply_handler=reply_handler, error_handler=error_handler)
592
593
594-class CredentialsError(Exception):
595- """A general exception when hadling credentilas."""
596-
597-
598-class CredentialsManagementTool(object):
599- """Wrapper to CredentialsManagement.
600-
601- The goal of this class is to abstract the caller from calling the DBus
602- service implemented in the class CredentialsManagement.
603-
604+class CredentialsManagementProxy(object):
605+ """Proxy that allows to work with the dbus api.
606+
607+ This proxy has been added to hide the exact details of
608+ how the signals are connected. This allows the reuse of
609+ the CredentialsManagementTool in diff platforms.
610 """
611
612 def __init__(self):
613- self._cleanup_signals = []
614-
615- def _get_creds_proxy(self):
616- """Get the CredentialsManagement dbus proxy."""
617+ """Create a new instance."""
618 bus = dbus.SessionBus()
619 try:
620 obj = bus.get_object(DBUS_BUS_NAME,
621 DBUS_CREDENTIALS_PATH,
622 follow_name_owner_changes=True)
623- proxy = dbus.Interface(obj, DBUS_CREDENTIALS_IFACE)
624+ self.proxy = dbus.Interface(obj, DBUS_CREDENTIALS_IFACE)
625 except:
626 logger.exception('get_creds_proxy:')
627 raise
628
629- return proxy
630-
631- def cleanup(self, _):
632- """Disconnect all the DBus signals."""
633- for sig in self._cleanup_signals:
634- logger.debug('cleanup: removing signal match %r', sig)
635- sig.remove()
636-
637- return _
638-
639- @defer.inlineCallbacks
640- def find_credentials(self):
641- """Find credentials for Ubuntu One.
642-
643- Return a deferred that, when fired, will return the credentials for
644- Ubuntu One for the current logged in user.
645-
646- The credentials is a dictionary with both string keys and values. The
647- dictionary may be either empty if there are no credentials for the
648- user, or will hold five items as follow:
649-
650- - "name"
651- - "token"
652- - "token_secret"
653- - "consumer_key"
654- - "consumer_secret"
655-
656- """
657- d = defer.Deferred()
658- d.addBoth(self.cleanup)
659-
660- proxy = self._get_creds_proxy()
661-
662- sig = proxy.connect_to_signal('CredentialsFound', d.callback)
663- self._cleanup_signals.append(sig)
664-
665- sig = proxy.connect_to_signal('CredentialsNotFound',
666- lambda: d.callback({}))
667- self._cleanup_signals.append(sig)
668-
669- sig = proxy.connect_to_signal('CredentialsError',
670- lambda error_dict: d.errback(CredentialsError(error_dict)))
671- self._cleanup_signals.append(sig)
672-
673- done = defer.Deferred()
674- proxy.find_credentials(reply_handler=lambda: done.callback(None),
675- error_handler=lambda *a: done.errback(a))
676-
677- yield done
678-
679- result = yield d
680- defer.returnValue(result)
681-
682- @defer.inlineCallbacks
683- def clear_credentials(self):
684- """Clear credentials for Ubuntu One.
685-
686- Return a deferred that, when fired, will return no result but will
687- indicate that the Ubuntu One credentials for the current user were
688- removed from the local keyring.
689-
690- """
691- d = defer.Deferred()
692- d.addBoth(self.cleanup)
693-
694- proxy = self._get_creds_proxy()
695- sig = proxy.connect_to_signal('CredentialsCleared',
696- lambda: d.callback(None))
697- self._cleanup_signals.append(sig)
698-
699- sig = proxy.connect_to_signal('CredentialsError',
700- lambda error_dict: d.errback(CredentialsError(error_dict)))
701- self._cleanup_signals.append(sig)
702-
703- done = defer.Deferred()
704- proxy.clear_credentials(reply_handler=lambda: done.callback(None),
705- error_handler=lambda *a: done.errback(a))
706-
707- yield done
708-
709- yield d
710-
711- @defer.inlineCallbacks
712- def store_credentials(self, token):
713- """Store credentials for Ubuntu One.
714-
715- The parameter 'token' should be a dictionary that matches the
716- description of the result of 'find_credentials'.
717-
718- Return a deferred that, when fired, will return no result but will
719- indicate that 'token' was stored in the local keyring as the new Ubuntu
720- One credentials for the current user.
721-
722- """
723- d = defer.Deferred()
724- d.addBoth(self.cleanup)
725-
726- proxy = self._get_creds_proxy()
727- sig = proxy.connect_to_signal('CredentialsStored',
728- lambda: d.callback(None))
729- self._cleanup_signals.append(sig)
730-
731- sig = proxy.connect_to_signal('CredentialsError',
732- lambda error_dict: d.errback(CredentialsError(error_dict)))
733- self._cleanup_signals.append(sig)
734-
735- done = defer.Deferred()
736- proxy.store_credentials(token,
737- reply_handler=lambda: done.callback(None),
738- error_handler=lambda *a: done.errback(a))
739-
740- yield done
741-
742- yield d
743-
744- @defer.inlineCallbacks
745- def register(self, window_id=0):
746- """Register to Ubuntu One.
747-
748- Return a deferred that, when fired, will return the credentials for
749- Ubuntu One for the current logged in user.
750-
751- If there are no credentials for the current user, a GTK UI will be
752- opened to invite the user to register to Ubuntu One. This UI provides
753- options to either register (main screen) or login (secondary screen).
754-
755- You can pass an optional 'window_id' parameter that will be used by the
756- GTK UI to be set transient for it.
757-
758- The returned credentials will be either a non-empty dictionary like the
759- one described in 'find_credentials', or None. The latter indicates that
760- there were no credentials for the user in the local keyring and that
761- the user refused to register to Ubuntu One.
762-
763- """
764- d = defer.Deferred()
765- d.addBoth(self.cleanup)
766-
767- proxy = self._get_creds_proxy()
768-
769- sig = proxy.connect_to_signal('CredentialsFound', d.callback)
770- self._cleanup_signals.append(sig)
771-
772- sig = proxy.connect_to_signal('AuthorizationDenied',
773- lambda: d.callback(None))
774- self._cleanup_signals.append(sig)
775-
776- sig = proxy.connect_to_signal('CredentialsError',
777- lambda error_dict: d.errback(CredentialsError(error_dict)))
778- self._cleanup_signals.append(sig)
779-
780- done = defer.Deferred()
781- proxy.register({'window_id': str(window_id)},
782- reply_handler=lambda: done.callback(None),
783- error_handler=lambda *a: done.errback(a))
784-
785- yield done
786-
787- result = yield d
788- defer.returnValue(result)
789-
790- @defer.inlineCallbacks
791- def login(self, window_id=0):
792- """Login to Ubuntu One.
793-
794- Return a deferred that, when fired, will return the credentials for
795- Ubuntu One for the current logged in user.
796-
797- If there are no credentials for the current user, a GTK UI will be
798- opened to invite the user to login to Ubuntu One. This UI provides
799- options to either login (main screen) or retrieve password (secondary
800- screen).
801-
802- You can pass an optional 'window_id' parameter that will be used by the
803- GTK UI to be set transient for it.
804-
805- The returned credentials will be either a non-empty dictionary like the
806- one described in 'find_credentials', or None. The latter indicates that
807- there were no credentials for the user in the local keyring and that
808- the user refused to login to Ubuntu One.
809-
810- """
811- d = defer.Deferred()
812- d.addBoth(self.cleanup)
813-
814- proxy = self._get_creds_proxy()
815-
816- sig = proxy.connect_to_signal('CredentialsFound', d.callback)
817- self._cleanup_signals.append(sig)
818-
819- sig = proxy.connect_to_signal('AuthorizationDenied',
820- lambda: d.callback(None))
821- self._cleanup_signals.append(sig)
822-
823- sig = proxy.connect_to_signal('CredentialsError',
824- lambda error_dict: d.errback(CredentialsError(error_dict)))
825- self._cleanup_signals.append(sig)
826-
827- done = defer.Deferred()
828- proxy.login({'window_id': str(window_id)},
829- reply_handler=lambda: done.callback(None),
830- error_handler=lambda *a: done.errback(a))
831-
832- yield done
833-
834- result = yield d
835- defer.returnValue(result)
836+ def find_credentials(self, *args, **kwargs):
837+ """Relay the find_credentials method."""
838+ return self.proxy.find_credentials(*args, **kwargs)
839+
840+ def clear_credentials(self, *args, **kwargs):
841+ """Relay the clear_credentials method."""
842+ return self.proxy.clear_credentials(*args, **kwargs)
843+
844+ def store_credentials(self, *args, **kwargs):
845+ """Relay the store_credentials method."""
846+ return self.proxy.store_credentials(*args, **kwargs)
847+
848+ def register(self, *args, **kwargs):
849+ """Relay the register method."""
850+ return self.proxy.register(*args, **kwargs)
851+
852+ def login(self, *args, **kwargs):
853+ """Relay the login method."""
854+ return self.proxy.login(*args, **kwargs)
855+
856+ def register_to_credentials_stored(self, callback):
857+ """Register to the CredentialsStored dbus signal."""
858+ return self.proxy.connect_to_signal('CredentialsStored', callback)
859+
860+ def register_to_credentials_cleared(self, callback):
861+ """Register to the CredentialsCleared dbus signal."""
862+ return self.proxy.connect_to_signal('CredentialsCleared', callback)
863+
864+ def register_to_credentials_found(self, callback):
865+ """Register to the CredentialsFound dbus signal."""
866+ return self.proxy.connect_to_signal('CredentialsFound', callback)
867+
868+ def register_to_credentials_not_found(self, callback):
869+ """Register to the CredentialsFound dbus signal."""
870+ return self.proxy.connect_to_signal('CredentialsNotFound', callback)
871+
872+ def register_to_authorization_denied(self, callback):
873+ """Register to the AuthorizationDenied dbus signal."""
874+ return self.proxy.connect_to_signal('AuthorizationDenied', callback)
875+
876+ def register_to_credentials_error(self, callback):
877+ """Register to the CredentialsError dbus signal."""
878+ return self.proxy.connect_to_signal('CredentialsError', callback)
879+
880+
881+def get_creds_proxy():
882+ """Get the CredentialsManagement dbus proxy."""
883+ return CredentialsManagementProxy()
884
885=== added file 'ubuntuone/platform/windows/credentials.py'
886--- ubuntuone/platform/windows/credentials.py 1970-01-01 00:00:00 +0000
887+++ ubuntuone/platform/windows/credentials.py 2011-05-03 09:17:06 +0000
888@@ -0,0 +1,131 @@
889+#!/usr/bin/env python
890+# -*- coding: utf-8 -*-
891+#
892+# Author: Manuel de la Pena<manuel@canonical.com>
893+#
894+# Copyright 2011 Canonical Ltd.
895+#
896+# This program is free software: you can redistribute it and/or modify it
897+# under the terms of the GNU General Public License version 3, as published
898+# by the Free Software Foundation.
899+#
900+# This program is distributed in the hope that it will be useful, but
901+# WITHOUT ANY WARRANTY; without even the implied warranties of
902+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
903+# PURPOSE. See the GNU General Public License for more details.
904+#
905+# You should have received a copy of the GNU General Public License along
906+# with this program. If not, see <http://www.gnu.org/licenses/>.
907+"""Ubuntu One credentials management IPC service."""
908+
909+import os
910+
911+import gettext
912+
913+from ubuntu_sso.main.windows import UbuntuSSOClient
914+from ubuntu_sso.credentials import HELP_TEXT_KEY, PING_URL_KEY, TC_URL_KEY
915+from twisted.internet import defer
916+
917+from ubuntuone.logger import (basic_formatter, logging,
918+ CustomRotatingFileHandler, LOGFOLDER)
919+from ubuntuone.clientdefs import GETTEXT_PACKAGE
920+
921+
922+Q_ = lambda string: gettext.dgettext(GETTEXT_PACKAGE, string)
923+NO_OP = lambda *args, **kwargs: None
924+
925+LOG_LEVEL = logging.DEBUG
926+path = os.path.join(LOGFOLDER, 'credentials.log')
927+MAIN_HANDLER = CustomRotatingFileHandler(path)
928+MAIN_HANDLER.setFormatter(basic_formatter)
929+MAIN_HANDLER.setLevel(LOG_LEVEL)
930+
931+logger = logging.getLogger("ubuntuone.credentials")
932+logger.setLevel(LOG_LEVEL)
933+logger.addHandler(MAIN_HANDLER)
934+
935+APP_NAME = "Ubuntu One"
936+TC_URL = "https://one.ubuntu.com/terms/"
937+PING_URL = "https://one.ubuntu.com/oauth/sso-finished-so-get-tokens/"
938+DESCRIPTION = Q_('Ubuntu One requires an Ubuntu Single Sign On (SSO) account. '
939+ 'This process will allow you to create a new account, '
940+ 'if you do not yet have one.')
941+
942+
943+class CredentialsManagement(object):
944+ """Object that manages Ubuntu One credentials."""
945+
946+ def __init__(self, proxy, *args, **kwargs):
947+ super(CredentialsManagement, self).__init__(*args, **kwargs)
948+ self.sso_proxy = proxy
949+
950+ def find_credentials(self, reply_handler=NO_OP, error_handler=NO_OP):
951+ """Ask the Ubuntu One credentials."""
952+ self.sso_proxy.find_credentials(APP_NAME, {},
953+ reply_handler=reply_handler, error_handler=error_handler)
954+
955+
956+ def clear_credentials(self, reply_handler=NO_OP, error_handler=NO_OP):
957+ """Clear the Ubuntu One credentials."""
958+ self.sso_proxy.clear_credentials(APP_NAME, {},
959+ reply_handler=reply_handler, error_handler=error_handler)
960+
961+ def store_credentials(self, credentials,
962+ reply_handler=NO_OP, error_handler=NO_OP):
963+ """Store the token for Ubuntu One application."""
964+ self.sso_proxy.store_credentials(APP_NAME, credentials,
965+ reply_handler=reply_handler, error_handler=error_handler)
966+
967+ def register(self, args, reply_handler=NO_OP, error_handler=NO_OP):
968+ """Get credentials if found else prompt to register to Ubuntu One."""
969+ params = {HELP_TEXT_KEY: DESCRIPTION, TC_URL_KEY: TC_URL,
970+ PING_URL_KEY: PING_URL}
971+ params.update(args)
972+ self.sso_proxy.register(APP_NAME, params,
973+ reply_handler=reply_handler, error_handler=error_handler)
974+
975+ def login(self, args, reply_handler=NO_OP, error_handler=NO_OP):
976+ """Get credentials if found else prompt to login to Ubuntu One."""
977+ params = {HELP_TEXT_KEY: DESCRIPTION, TC_URL_KEY: TC_URL,
978+ PING_URL_KEY: PING_URL}
979+ params.update(args)
980+ self.sso_proxy.login(APP_NAME, params,
981+ reply_handler=reply_handler, error_handler=error_handler)
982+
983+ def register_to_credentials_stored(self, callback):
984+ """Register to the CredentialsStored dbus signal."""
985+ self.sso_proxy.on_credentials_stored_cb = callback
986+ return self.sso_proxy.on_credentials_stored_cb
987+
988+ def register_to_credentials_cleared(self, callback):
989+ """Register to the CredentialsCleared dbus signal."""
990+ self.sso_proxy.on_credentials_cleared_cb = callback
991+ return self.sso_proxy.on_credentials_cleared_cb
992+
993+ def register_to_credentials_found(self, callback):
994+ """Register to the CredentialsFound dbus signal."""
995+ self.sso_proxy.on_credentials_found_cb = callback
996+ return self.sso_proxy.on_credentials_found_cb
997+
998+ def register_to_credentials_not_found(self, callback):
999+ """Register to the CredentialsFound dbus signal."""
1000+ self.sso_proxy.on_credentials_not_found_cb = callback
1001+ return self.sso_proxy.on_credentials_not_found_cb
1002+
1003+ def register_to_authorization_denied(self, callback):
1004+ """Register to the AuthorizationDenied dbus signal."""
1005+ self.sso_proxy.on_authorization_denied_cb = callback
1006+ return self.sso_proxy.on_authorization_denied_cb
1007+
1008+ def register_to_credentials_error(self, callback):
1009+ """Register to the CredentialsError dbus signal."""
1010+ self.sso_proxy.on_credentials_error_cb = callback
1011+ return self.sso_proxy.on_credentials_error_cb
1012+
1013+
1014+@defer.inlineCallbacks
1015+def get_creds_proxy():
1016+ """Get the CredentialsManagement dbus proxy."""
1017+ client = UbuntuSSOClient()
1018+ client = yield client.connect()
1019+ defer.returnValue(CredentialsManagement(client.cred_management))

Subscribers

People subscribed via source and target branches