1
# -*- coding: utf-8 -*-
3
# Author: Natalia B. Bidart <natalia.bidart@canonical.com>
5
# Copyright 2010 Canonical Ltd.
7
# This program is free software: you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License version 3, as published
9
# by the Free Software Foundation.
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranties of
13
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14
# PURPOSE. See the GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License along
17
# with this program. If not, see <http://www.gnu.org/licenses/>.
19
"""Ubuntu One credentials management dbus service."""
28
from ubuntu_sso.credentials import (HELP_TEXT_KEY, PING_URL_KEY, TC_URL_KEY,
31
from ubuntuone.logger import (basic_formatter, logging,
32
CustomRotatingFileHandler, LOGFOLDER)
33
from ubuntuone.clientdefs import GETTEXT_PACKAGE
36
Q_ = lambda string: gettext.dgettext(GETTEXT_PACKAGE, string)
37
NO_OP = lambda *args, **kwargs: None
38
TIMEOUT_INTERVAL = 500
40
LOG_LEVEL = logging.DEBUG
41
path = os.path.join(LOGFOLDER, 'credentials.log')
42
MAIN_HANDLER = CustomRotatingFileHandler(path)
43
MAIN_HANDLER.setFormatter(basic_formatter)
44
MAIN_HANDLER.setLevel(LOG_LEVEL)
46
logger = logging.getLogger("ubuntuone.credentials")
47
logger.setLevel(LOG_LEVEL)
48
logger.addHandler(MAIN_HANDLER)
50
if os.environ.get('DEBUG'):
51
debug_handler = logging.StreamHandler(sys.stderr)
52
debug_handler.setFormatter(basic_formatter)
53
debug_handler.setLevel(LOG_LEVEL)
54
logger.addHandler(debug_handler)
57
DBUS_BUS_NAME = "com.ubuntuone.Credentials"
58
DBUS_CREDENTIALS_PATH = "/credentials"
59
DBUS_CREDENTIALS_IFACE = "com.ubuntuone.CredentialsManagement"
61
APP_NAME = "Ubuntu One"
62
TC_URL = "https://one.ubuntu.com/terms/"
63
PING_URL = "https://one.ubuntu.com/oauth/sso-finished-so-get-tokens/"
64
DESCRIPTION = Q_('Ubuntu One requires an Ubuntu Single Sign On (SSO) account. '
65
'This process will allow you to create a new account, '
66
'if you do not yet have one.')
69
class CredentialsManagement(dbus.service.Object):
70
"""DBus object that manages Ubuntu One credentials."""
72
def __init__(self, timeout_func=lambda *a: None,
73
shutdown_func=lambda *a: None, *args, **kwargs):
74
super(CredentialsManagement, self).__init__(*args, **kwargs)
76
self.timeout_func = timeout_func
77
self.shutdown_func = shutdown_func
80
self.sso_proxy = self._get_sso_proxy()
82
def _signal_handler(self, *args, **kwargs):
83
"""Generic signal handler."""
84
member = kwargs.get('member', None)
85
app_name = args[0] if len(args) > 0 else None
86
logger.debug('Handling DBus signal for member: %r, app_name: %r.',
89
if app_name != APP_NAME:
90
logger.info('Received %r but app_name %r does not match %r, ' \
91
'exiting.', member, app_name, APP_NAME)
94
sig = getattr(self, member)
96
if member in ('CredentialsFound', 'CredentialsError'):
97
# this are the only signals that will forward the parameter
98
logger.info('%r', member)
104
def _get_sso_proxy(self):
105
"""Get the SSO dbus proxy."""
106
bus = dbus.SessionBus()
107
# register signal handlers for each kind of error
108
self.sso_match = bus.add_signal_receiver(self._signal_handler,
109
member_keyword='member',
110
dbus_interface=ubuntu_sso.DBUS_CREDENTIALS_IFACE)
112
obj = bus.get_object(ubuntu_sso.DBUS_BUS_NAME,
113
ubuntu_sso.DBUS_CREDENTIALS_PATH,
114
follow_name_owner_changes=True)
115
proxy = dbus.Interface(obj, ubuntu_sso.DBUS_CREDENTIALS_IFACE)
117
logger.exception('get_sso_proxy:')
122
def _get_ref_count(self):
123
"""Get value of ref_count."""
124
logger.debug('ref_count is %r.', self._ref_count)
125
return self._ref_count
127
def _set_ref_count(self, new_value):
128
"""Set a new value to ref_count."""
129
logger.debug('ref_count is %r, changing value to %r.',
130
self._ref_count, new_value)
133
msg = 'Attempting to decrease ref_count to a negative value (%r).'
134
logger.warning(msg, new_value)
136
self._ref_count = new_value
138
if self._ref_count == 0:
139
self.timeout_func(TIMEOUT_INTERVAL, self.shutdown_func)
141
ref_count = property(fget=_get_ref_count, fset=_set_ref_count)
143
# Operator not preceded by a space (fails with dbus decorators)
144
# pylint: disable=C0322
146
@dbus.service.signal(DBUS_CREDENTIALS_IFACE)
147
def AuthorizationDenied(self):
148
"""Signal thrown when the user denies the authorization."""
150
logger.info('%s: emitting AuthorizationDenied.',
151
self.__class__.__name__)
153
@dbus.service.signal(DBUS_CREDENTIALS_IFACE, signature='a{ss}')
154
def CredentialsFound(self, credentials):
155
"""Signal thrown when the credentials are found."""
157
logger.info('%s: emitting CredentialsFound.',
158
self.__class__.__name__)
160
@dbus.service.signal(DBUS_CREDENTIALS_IFACE)
161
def CredentialsNotFound(self):
162
"""Signal thrown when the credentials are not found."""
164
logger.info('%s: emitting CredentialsNotFound.',
165
self.__class__.__name__)
167
@dbus.service.signal(DBUS_CREDENTIALS_IFACE)
168
def CredentialsCleared(self):
169
"""Signal thrown when the credentials were cleared."""
171
logger.info('%s: emitting CredentialsCleared.',
172
self.__class__.__name__)
174
@dbus.service.signal(DBUS_CREDENTIALS_IFACE)
175
def CredentialsStored(self):
176
"""Signal thrown when the credentials were cleared."""
178
logger.info('%s: emitting CredentialsStored.',
179
self.__class__.__name__)
181
@dbus.service.signal(DBUS_CREDENTIALS_IFACE, signature='a{ss}')
182
def CredentialsError(self, error_dict):
183
"""Signal thrown when there is a problem getting the credentials."""
185
logger.error('%s: emitting CredentialsError with error_dict %r.',
186
self.__class__.__name__, error_dict)
188
@dbus.service.method(dbus_interface=DBUS_CREDENTIALS_IFACE,
189
async_callbacks=("reply_handler", "error_handler"))
190
def find_credentials(self, reply_handler=NO_OP, error_handler=NO_OP):
191
"""Ask the Ubuntu One credentials."""
193
self.sso_proxy.find_credentials(APP_NAME, {},
194
reply_handler=reply_handler, error_handler=error_handler)
197
@dbus.service.method(dbus_interface=DBUS_CREDENTIALS_IFACE,
198
async_callbacks=("reply_handler", "error_handler"))
199
def clear_credentials(self, reply_handler=NO_OP, error_handler=NO_OP):
200
"""Clear the Ubuntu One credentials."""
202
self.sso_proxy.clear_credentials(APP_NAME, {},
203
reply_handler=reply_handler, error_handler=error_handler)
205
@dbus.service.method(dbus_interface=DBUS_CREDENTIALS_IFACE,
206
in_signature='a{ss}',
207
async_callbacks=("reply_handler", "error_handler"))
208
def store_credentials(self, credentials,
209
reply_handler=NO_OP, error_handler=NO_OP):
210
"""Store the token for Ubuntu One application."""
212
self.sso_proxy.store_credentials(APP_NAME, credentials,
213
reply_handler=reply_handler, error_handler=error_handler)
215
@dbus.service.method(dbus_interface=DBUS_CREDENTIALS_IFACE,
216
async_callbacks=("reply_handler", "error_handler"))
217
def register(self, reply_handler=NO_OP, error_handler=NO_OP):
218
"""Get credentials if found else prompt to register to Ubuntu One."""
220
params = {HELP_TEXT_KEY: DESCRIPTION, TC_URL_KEY: TC_URL,
221
PING_URL_KEY: PING_URL, WINDOW_ID_KEY: '0'}
222
self.sso_proxy.register(APP_NAME, params,
223
reply_handler=reply_handler, error_handler=error_handler)
225
@dbus.service.method(dbus_interface=DBUS_CREDENTIALS_IFACE,
226
async_callbacks=("reply_handler", "error_handler"))
227
def login(self, reply_handler=NO_OP, error_handler=NO_OP):
228
"""Get credentials if found else prompt to login to Ubuntu One."""
229
self.register(reply_handler, error_handler)
231
@dbus.service.method(dbus_interface=DBUS_CREDENTIALS_IFACE,
232
async_callbacks=("reply_handler", "error_handler"))
233
def shutdown(self, reply_handler=NO_OP, error_handler=NO_OP):
234
"""Disconnect signals from SSO backend."""
235
bus = dbus.SessionBus()
237
bus.remove_signal_receiver(self.sso_match, member_keyword='member',
238
dbus_interface=ubuntu_sso.DBUS_CREDENTIALS_IFACE)