Merge lp:~nataliabidart/ubuntu/maverick/ubuntu-sso-client/ubuntu-sso-client-0.99.1 into lp:ubuntu/maverick/ubuntu-sso-client
- Maverick (10.10)
- ubuntu-sso-client-0.99.1
- Merge into maverick
Proposed by
Natalia Bidart
on 2010-08-19
| Status: | Merged |
|---|---|
| Merged at revision: | 5 |
| Proposed branch: | lp:~nataliabidart/ubuntu/maverick/ubuntu-sso-client/ubuntu-sso-client-0.99.1 |
| Merge into: | lp:ubuntu/maverick/ubuntu-sso-client |
| Diff against target: |
725 lines (+321/-154) 12 files modified
PKG-INFO (+1/-1) bin/ubuntu-sso-login-gui (+2/-2) data/ui.glade (+2/-0) debian/changelog (+10/-0) debian/control (+1/-1) run-tests (+5/-3) setup.py (+1/-1) ubuntu_sso/gui.py (+38/-23) ubuntu_sso/keyring.py (+112/-111) ubuntu_sso/main.py (+4/-4) ubuntu_sso/tests/test_gui.py (+30/-8) ubuntu_sso/tests/test_keyring.py (+115/-0) |
| To merge this branch: | bzr merge lp:~nataliabidart/ubuntu/maverick/ubuntu-sso-client/ubuntu-sso-client-0.99.1 |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Ubuntu branches | 2010-08-19 | Pending | |
|
Review via email:
|
|||
Commit Message
Description of the Change
Critical bug fixes for v0.99.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
| 1 | === modified file 'PKG-INFO' |
| 2 | --- PKG-INFO 2010-08-12 00:00:08 +0000 |
| 3 | +++ PKG-INFO 2010-08-19 17:58:43 +0000 |
| 4 | @@ -1,6 +1,6 @@ |
| 5 | Metadata-Version: 1.0 |
| 6 | Name: ubuntu-sso-client |
| 7 | -Version: 0.99 |
| 8 | +Version: 0.99.1 |
| 9 | Summary: Ubuntu Single Sign-On client |
| 10 | Home-page: https://launchpad.net/ubuntu-sso-client |
| 11 | Author: Natalia Bidart |
| 12 | |
| 13 | === modified file 'bin/ubuntu-sso-login-gui' |
| 14 | --- bin/ubuntu-sso-login-gui 2010-08-12 00:00:08 +0000 |
| 15 | +++ bin/ubuntu-sso-login-gui 2010-08-19 17:58:43 +0000 |
| 16 | @@ -25,8 +25,8 @@ |
| 17 | from ubuntu_sso.gui import UbuntuSSOClientGUI |
| 18 | |
| 19 | |
| 20 | -APP_NAME = 'Super Testing App' |
| 21 | -TC_URI = 'http://ubuntu.com' |
| 22 | +APP_NAME = 'Ubuntu' |
| 23 | +TC_URI = 'http://one.ubuntu.com/terms' |
| 24 | HELP_TEXT = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. ' \ |
| 25 | 'Nam sed lorem nibh. Suspendisse gravida nulla non nunc suscipit ' \ |
| 26 | 'pulvinar tempus ut augue.' |
| 27 | |
| 28 | === modified file 'data/ui.glade' |
| 29 | --- data/ui.glade 2010-08-12 00:00:08 +0000 |
| 30 | +++ data/ui.glade 2010-08-19 17:58:43 +0000 |
| 31 | @@ -349,6 +349,8 @@ |
| 32 | </object> |
| 33 | <object class="GtkVBox" id="tc_browser_vbox"> |
| 34 | <property name="visible">True</property> |
| 35 | + <signal name="hide" handler="on_tc_browser_vbox_hide"/> |
| 36 | + <signal name="show" handler="on_tc_browser_vbox_show"/> |
| 37 | <child> |
| 38 | <object class="GtkScrolledWindow" id="tc_browser_window"> |
| 39 | <property name="visible">True</property> |
| 40 | |
| 41 | === modified file 'debian/changelog' |
| 42 | --- debian/changelog 2010-08-12 09:38:17 +0000 |
| 43 | +++ debian/changelog 2010-08-19 17:58:43 +0000 |
| 44 | @@ -1,3 +1,13 @@ |
| 45 | +ubuntu-sso-client (0.99.1-0ubuntu1) UNRELEASED; urgency=low |
| 46 | + |
| 47 | + * New upstream release: |
| 48 | + - Delayed opening the webkit browser to the latest possible. (LP: #617041) |
| 49 | + (nataliabidart) |
| 50 | + - Use a proper dictionary with different attributes for each key so old |
| 51 | + keys are not overwritten nor deleted. (LP: #617347) (alecu) |
| 52 | + |
| 53 | + -- Natalia Bidart (nessita) <nataliabidart@gmail.com> Thu, 19 Aug 2010 13:02:10 -0300 |
| 54 | + |
| 55 | ubuntu-sso-client (0.99-0ubuntu1) maverick; urgency=low |
| 56 | |
| 57 | * New upstream release. |
| 58 | |
| 59 | === modified file 'debian/control' |
| 60 | --- debian/control 2010-08-11 16:18:28 +0000 |
| 61 | +++ debian/control 2010-08-19 17:58:43 +0000 |
| 62 | @@ -7,7 +7,7 @@ |
| 63 | python-support (>= 0.6.4), |
| 64 | python-distutils-extra (>= 2.10) |
| 65 | Maintainer: Natalia Bidart <natalia.bidart@canonical.com> |
| 66 | -Standards-Version: 3.8.4 |
| 67 | +Standards-Version: 3.9.1 |
| 68 | XS-Python-Version: current |
| 69 | |
| 70 | Package: ubuntu-sso-client |
| 71 | |
| 72 | === modified file 'run-tests' |
| 73 | --- run-tests 2010-08-11 17:03:11 +0000 |
| 74 | +++ run-tests 2010-08-19 17:58:43 +0000 |
| 75 | @@ -18,9 +18,11 @@ |
| 76 | `which xvfb-run` ./contrib/test $@ |
| 77 | pyflakes bin ubuntu_sso |
| 78 | if [ -x `which pep8` ]; then |
| 79 | - pep8 --repeat bin ubuntu_sso/gui.py ubuntu_sso/main.py \ |
| 80 | - ubuntu_sso/tests/test_gui.py ubuntu_sso/tests/test_main.py contrib/ |
| 81 | + pep8 --repeat bin/ contrib/ \ |
| 82 | + ubuntu_sso/gui.py ubuntu_sso/main.py ubuntu_sso/keyring.py \ |
| 83 | + ubuntu_sso/tests/test_gui.py ubuntu_sso/tests/test_main.py \ |
| 84 | + ubuntu_sso/tests/test_keyring.py |
| 85 | else |
| 86 | echo "Please install the 'pep8' package." |
| 87 | fi |
| 88 | -rm -rf _trial_temp/ |
| 89 | \ No newline at end of file |
| 90 | +rm -rf _trial_temp/ |
| 91 | |
| 92 | === modified file 'setup.py' |
| 93 | --- setup.py 2010-08-12 00:00:08 +0000 |
| 94 | +++ setup.py 2010-08-19 17:58:43 +0000 |
| 95 | @@ -72,7 +72,7 @@ |
| 96 | |
| 97 | setup( |
| 98 | name='ubuntu-sso-client', |
| 99 | - version='0.99', |
| 100 | + version='0.99.1', |
| 101 | license='GPL v3', |
| 102 | author='Natalia Bidart', |
| 103 | author_email='natalia.bidart@canonical.com', |
| 104 | |
| 105 | === modified file 'ubuntu_sso/gui.py' |
| 106 | --- ubuntu_sso/gui.py 2010-08-12 00:00:08 +0000 |
| 107 | +++ ubuntu_sso/gui.py 2010-08-19 17:58:43 +0000 |
| 108 | @@ -153,8 +153,8 @@ |
| 109 | """Ubuntu single sign on GUI.""" |
| 110 | |
| 111 | CAPTCHA_SOLUTION_ENTRY = _('Type the characters above') |
| 112 | - CONNECT_HELP_LABEL = _('To connect this computer to') + ' %s ' + \ |
| 113 | - _('enter your details below.') |
| 114 | + CONNECT_HELP_LABEL = _('To connect this computer to %(app_name)s ' \ |
| 115 | + 'enter your details below.') |
| 116 | EMAIL1_ENTRY = _('Email address') |
| 117 | EMAIL2_ENTRY = _('Re-type Email address') |
| 118 | EMAIL_MISMATCH = _('The email addresses don\'t match, please double check ' |
| 119 | @@ -163,11 +163,11 @@ |
| 120 | EMAIL_TOKEN_ENTRY = _('Enter code verification here') |
| 121 | FIELD_REQUIRED = _('This field is required.') |
| 122 | FORGOTTEN_PASSWORD_BUTTON = _('I\'ve forgotten my password') |
| 123 | - JOIN_HEADER_LABEL = _('Create') + ' %s ' + _('account') |
| 124 | + JOIN_HEADER_LABEL = _('Create %(app_name)s account') |
| 125 | LOADING = _('Loading...') |
| 126 | LOGIN_BUTTON_LABEL = _('Already have an account? Click here to sign in') |
| 127 | LOGIN_EMAIL_ENTRY = _('Email address') |
| 128 | - LOGIN_HEADER_LABEL = _('Connect to') + ' %s' |
| 129 | + LOGIN_HEADER_LABEL = _('Connect to %(app_name)s') |
| 130 | LOGIN_PASSWORD_ENTRY = _('Password') |
| 131 | NAME_ENTRY = _('Name') |
| 132 | NEXT = _('Next') |
| 133 | @@ -185,9 +185,9 @@ |
| 134 | RESET_PASSWORD = _('Reset Password') |
| 135 | RESET_CODE_ENTRY = _('Reset code') |
| 136 | RESET_EMAIL_ENTRY = _('Email address') |
| 137 | - SET_NEW_PASSWORD_LABEL = _('A password reset code has been sent to %s.\n' \ |
| 138 | - 'Please enter the code below along with your ' \ |
| 139 | - 'new password.') |
| 140 | + SET_NEW_PASSWORD_LABEL = _('A password reset code has been sent to ' \ |
| 141 | + '%(email)s.\nPlease enter the code below ' \ |
| 142 | + 'along with your new password.') |
| 143 | SUCCESS = _('The process finished successfully. Congratulations!') |
| 144 | TC = _('Terms & Conditions') |
| 145 | TC_NOT_ACCEPTED = _('Agreeing to the Ubuntu One Terms & Conditions is ' |
| 146 | @@ -198,8 +198,8 @@ |
| 147 | |
| 148 | A verification code has just been sent to your email address. |
| 149 | Please enter your code from the email. An example is shown below.""") |
| 150 | - YES_TO_TC = _('I agree with the') |
| 151 | - YES_TO_UPDATES = _('Yes! Email me tips and updates.') |
| 152 | + YES_TO_TC = _('I agree with the %(app_name)s ') # Terms&Conditions button |
| 153 | + YES_TO_UPDATES = _('Yes! Email me %(app_name)s tips and updates.') |
| 154 | |
| 155 | def __init__(self, app_name, tc_uri, help_text, |
| 156 | window_id=0, login_only=False, close_callback=None): |
| 157 | @@ -211,7 +211,7 @@ |
| 158 | self._signals_receivers = {} |
| 159 | |
| 160 | self.app_name = app_name |
| 161 | - self.app_label = '<b>%s</b>' % app_name |
| 162 | + self.app_label = '<b>%s</b>' % self.app_name |
| 163 | self.tc_uri = tc_uri |
| 164 | self.help_text = help_text |
| 165 | self.close_callback = close_callback |
| 166 | @@ -437,8 +437,8 @@ |
| 167 | |
| 168 | def _build_enter_details_page(self): |
| 169 | """Build the enter details page.""" |
| 170 | - self.enter_details_vbox.header = (self.JOIN_HEADER_LABEL % |
| 171 | - self.app_label) |
| 172 | + d = {'app_name': self.app_label} |
| 173 | + self.enter_details_vbox.header = self.JOIN_HEADER_LABEL % d |
| 174 | self.enter_details_vbox.help_text = self.help_text |
| 175 | |
| 176 | self.enter_details_vbox.pack_start(self.name_entry, expand=False) |
| 177 | @@ -461,8 +461,10 @@ |
| 178 | else: |
| 179 | self._set_captcha_image() |
| 180 | |
| 181 | - self.yes_to_updates_checkbutton.set_label(self.YES_TO_UPDATES) |
| 182 | - self.yes_to_tc_checkbutton.set_label(self.YES_TO_TC) |
| 183 | + msg = self.YES_TO_UPDATES % {'app_name': self.app_name} |
| 184 | + self.yes_to_updates_checkbutton.set_label(msg) |
| 185 | + msg = self.YES_TO_TC % {'app_name': self.app_name} |
| 186 | + self.yes_to_tc_checkbutton.set_label(msg) |
| 187 | self.tc_button.set_label(self.TC) |
| 188 | self.login_button.set_label(self.LOGIN_BUTTON_LABEL) |
| 189 | |
| 190 | @@ -476,11 +478,6 @@ |
| 191 | |
| 192 | def _build_tc_page(self): |
| 193 | """Build the Terms & Conditions page.""" |
| 194 | - self.tc_browser = webkit.WebView() |
| 195 | - self.tc_browser.open(self.tc_uri) |
| 196 | - self.tc_browser.show() |
| 197 | - self.tc_browser_window.add(self.tc_browser) |
| 198 | - |
| 199 | return self.tc_browser_vbox |
| 200 | |
| 201 | def _build_processing_page(self): |
| 202 | @@ -510,8 +507,9 @@ |
| 203 | |
| 204 | def _build_login_page(self): |
| 205 | """Build the login page.""" |
| 206 | - self.login_vbox.header = self.LOGIN_HEADER_LABEL % self.app_label |
| 207 | - self.login_vbox.help_text = self.CONNECT_HELP_LABEL % self.app_label |
| 208 | + d = {'app_name': self.app_label} |
| 209 | + self.login_vbox.header = self.LOGIN_HEADER_LABEL % d |
| 210 | + self.login_vbox.help_text = self.CONNECT_HELP_LABEL % d |
| 211 | |
| 212 | self.login_details_vbox.pack_start(self.login_email_entry) |
| 213 | self.login_details_vbox.reorder_child(self.login_email_entry, 0) |
| 214 | @@ -777,6 +775,22 @@ |
| 215 | |
| 216 | self._set_current_page(self.processing_vbox) |
| 217 | |
| 218 | + def on_tc_browser_vbox_show(self, *args, **kwargs): |
| 219 | + """The T&C page is being shown.""" |
| 220 | + browser = webkit.WebView() |
| 221 | + browser.open(self.tc_uri) |
| 222 | + browser.show() |
| 223 | + self.tc_browser_window.add(browser) |
| 224 | + |
| 225 | + def on_tc_browser_vbox_hide(self, *args, **kwargs): |
| 226 | + """The T&C page is no longer being shown.""" |
| 227 | + children = self.tc_browser_window.get_children() |
| 228 | + if len(children) > 0: |
| 229 | + browser = children[0] |
| 230 | + self.tc_browser_window.remove(browser) |
| 231 | + browser.destroy() |
| 232 | + del browser |
| 233 | + |
| 234 | # backend callbacks |
| 235 | |
| 236 | def on_captcha_generated(self, captcha_id, *args, **kwargs): |
| 237 | @@ -836,8 +850,9 @@ |
| 238 | |
| 239 | def on_password_reset_token_sent(self, email, *args, **kwargs): |
| 240 | """Password reset token was successfully sent.""" |
| 241 | - e = self.reset_email_entry.get_text() |
| 242 | - self.set_new_password_vbox.help_text = self.SET_NEW_PASSWORD_LABEL % e |
| 243 | + email = self.reset_email_entry.get_text() |
| 244 | + msg = self.SET_NEW_PASSWORD_LABEL % {'email': email} |
| 245 | + self.set_new_password_vbox.help_text = msg |
| 246 | self._set_current_page(self.set_new_password_vbox) |
| 247 | |
| 248 | def on_password_reset_error(self, *args, **kwargs): |
| 249 | |
| 250 | === modified file 'ubuntu_sso/keyring.py' |
| 251 | --- ubuntu_sso/keyring.py 2010-08-11 17:03:11 +0000 |
| 252 | +++ ubuntu_sso/keyring.py 2010-08-19 17:58:43 +0000 |
| 253 | @@ -1,111 +1,112 @@ |
| 254 | -# Copyright (C) 2010 Canonical |
| 255 | -# |
| 256 | -# Authors: |
| 257 | -# Andrew Higginson |
| 258 | -# |
| 259 | -# This program is free software; you can redistribute it and/or modify it under |
| 260 | -# the terms of the GNU General Public License as published by the Free Software |
| 261 | -# Foundation; version 3. |
| 262 | -# |
| 263 | -# This program is distributed in the hope that it will be useful, but WITHOUT |
| 264 | -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 265 | -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| 266 | -# details. |
| 267 | -# |
| 268 | -# You should have received a copy of the GNU General Public License along with |
| 269 | -# this program; if not, write to the Free Software Foundation, Inc., |
| 270 | -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 271 | - |
| 272 | -import gnomekeyring |
| 273 | - |
| 274 | -from urllib import urlencode |
| 275 | -from urlparse import parse_qsl |
| 276 | - |
| 277 | -class Keyring(object): |
| 278 | - |
| 279 | - KEYRING_NAME = "login" |
| 280 | - |
| 281 | - def __init__(self, app_name): |
| 282 | - |
| 283 | - if not gnomekeyring.is_available(): |
| 284 | - raise gnomekeyring.NoKeyringDaemonError |
| 285 | - self.app_name = app_name |
| 286 | - |
| 287 | - def _create_keyring(self, name): |
| 288 | - """ |
| 289 | - Creates a keyring, if it already exists, |
| 290 | - it does nothing |
| 291 | - """ |
| 292 | - keyring_names = gnomekeyring.list_keyring_names_sync() |
| 293 | - if not name in keyring_names: |
| 294 | - gnomekeyring.create_sync(name) |
| 295 | - |
| 296 | - def _item_exists(self, sync, name): |
| 297 | - """ |
| 298 | - Returns whether a named item exists in a |
| 299 | - named keyring |
| 300 | - """ |
| 301 | - return self._get_item_id_from_name(sync, name) != None |
| 302 | - |
| 303 | - def _get_item_id_from_name(self, sync, name): |
| 304 | - """ |
| 305 | - Returns the ID for a named item |
| 306 | - """ |
| 307 | - for item_id in gnomekeyring.list_item_ids_sync(sync): |
| 308 | - item_info = gnomekeyring.item_get_info_sync(sync, item_id) |
| 309 | - display_name = item_info.get_display_name() |
| 310 | - if display_name == name: |
| 311 | - return item_id |
| 312 | - return None |
| 313 | - |
| 314 | - def _get_item_info_from_name(self, sync, name): |
| 315 | - """ |
| 316 | - Returns the ID for a named item |
| 317 | - """ |
| 318 | - for item_id in gnomekeyring.list_item_ids_sync(sync): |
| 319 | - item_info = gnomekeyring.item_get_info_sync(sync, item_id) |
| 320 | - display_name = item_info.get_display_name() |
| 321 | - if display_name == name: |
| 322 | - return item_info |
| 323 | - return None |
| 324 | - |
| 325 | - def set_ubuntusso_attr(self, attr): |
| 326 | - """ |
| 327 | - Sets the attributes of the Ubuntu SSO item |
| 328 | - """ |
| 329 | - # Creates the secret from the attributes |
| 330 | - secret = urlencode(attr) |
| 331 | - |
| 332 | - # Create the keyring |
| 333 | - self._create_keyring(self.KEYRING_NAME) |
| 334 | - |
| 335 | - # If the item already exists, delete it |
| 336 | - if self._item_exists(self.KEYRING_NAME, self.app_name): |
| 337 | - item_id = self._get_item_id_from_name(self.KEYRING_NAME, |
| 338 | - self.app_name) |
| 339 | - gnomekeyring.item_delete_sync(self.KEYRING_NAME, item_id) |
| 340 | - |
| 341 | - # Add our SSO item |
| 342 | - gnomekeyring.item_create_sync(self.KEYRING_NAME, |
| 343 | - gnomekeyring.ITEM_GENERIC_SECRET, self.app_name, {}, |
| 344 | - secret, True) |
| 345 | - |
| 346 | - def get_ubuntusso_attr(self): |
| 347 | - """ |
| 348 | - Returns the secret of the SSO item in a dictionary |
| 349 | - """ |
| 350 | - # If we have no attributes, return None |
| 351 | - if self._get_item_info_from_name(self.KEYRING_NAME, |
| 352 | - self.app_name) == None: |
| 353 | - return None |
| 354 | - secret = self._get_item_info_from_name(self.KEYRING_NAME, |
| 355 | - self.app_name).get_secret() |
| 356 | - return dict(parse_qsl(secret)) |
| 357 | - |
| 358 | -if __name__ == "__main__": |
| 359 | - SSO_ITEM_NAME = "Software Center UbuntuSSO token" |
| 360 | - keyring = Keyring(SSO_ITEM_NAME) |
| 361 | - keyring.set_ubuntusso_attr({"ha":"hehddddeff", "hi":"hggehes", "ho":"he"}) |
| 362 | - print keyring.get_ubuntusso_attr() |
| 363 | - |
| 364 | - |
| 365 | +# Copyright (C) 2010 Canonical |
| 366 | +# |
| 367 | +# Authors: |
| 368 | +# Andrew Higginson |
| 369 | +# Alejandro J. Cura <alecu@canonical.com> |
| 370 | +# |
| 371 | +# This program is free software; you can redistribute it and/or modify it under |
| 372 | +# the terms of the GNU General Public License as published by the Free Software |
| 373 | +# Foundation; version 3. |
| 374 | +# |
| 375 | +# This program is distributed in the hope that it will be useful, but WITHOUT |
| 376 | +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 377 | +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| 378 | +# details. |
| 379 | +# |
| 380 | +# You should have received a copy of the GNU General Public License along with |
| 381 | +# this program; if not, write to the Free Software Foundation, Inc., |
| 382 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 383 | + |
| 384 | +"""Handle keys in the gnome kerying.""" |
| 385 | + |
| 386 | +import gnomekeyring |
| 387 | + |
| 388 | +from urllib import urlencode |
| 389 | +from urlparse import parse_qsl |
| 390 | + |
| 391 | + |
| 392 | +class Keyring(object): |
| 393 | + |
| 394 | + KEYRING_NAME = "login" |
| 395 | + |
| 396 | + def __init__(self, app_name): |
| 397 | + if not gnomekeyring.is_available(): |
| 398 | + raise gnomekeyring.NoKeyringDaemonError |
| 399 | + self.app_name = app_name |
| 400 | + |
| 401 | + def _create_keyring(self, name): |
| 402 | + """Creates a keyring, if it already exists, do nothing.""" |
| 403 | + keyring_names = gnomekeyring.list_keyring_names_sync() |
| 404 | + if not name in keyring_names: |
| 405 | + gnomekeyring.create_sync(name) |
| 406 | + |
| 407 | + def _get_item_id_from_name(self, sync, name): |
| 408 | + """Return the ID for a named item.""" |
| 409 | + for item_id in gnomekeyring.list_item_ids_sync(sync): |
| 410 | + item_info = gnomekeyring.item_get_info_sync(sync, item_id) |
| 411 | + display_name = item_info.get_display_name() |
| 412 | + if display_name == name: |
| 413 | + return item_id |
| 414 | + |
| 415 | + def _get_item_info_from_name(self, sync, name): |
| 416 | + """Return the ID for a named item.""" |
| 417 | + for item_id in gnomekeyring.list_item_ids_sync(sync): |
| 418 | + item_info = gnomekeyring.item_get_info_sync(sync, item_id) |
| 419 | + display_name = item_info.get_display_name() |
| 420 | + if display_name == name: |
| 421 | + return item_info |
| 422 | + |
| 423 | + def set_ubuntusso_attr(self, cred): |
| 424 | + """Set the credentials of the Ubuntu SSO item.""" |
| 425 | + # Creates the secret from the credentials |
| 426 | + secret = urlencode(cred) |
| 427 | + |
| 428 | + # Create the keyring |
| 429 | + self._create_keyring(self.KEYRING_NAME) |
| 430 | + |
| 431 | + # No need to delete the item if it already exists |
| 432 | + |
| 433 | + # A set of attributes for this credentials |
| 434 | + attr = {"key-type": "Ubuntu SSO credentials", |
| 435 | + "token-name": cred["name"].encode("utf8")} |
| 436 | + |
| 437 | + # Add our SSO credentials to the keyring |
| 438 | + gnomekeyring.item_create_sync(self.KEYRING_NAME, |
| 439 | + gnomekeyring.ITEM_GENERIC_SECRET, self.app_name, attr, |
| 440 | + secret, True) |
| 441 | + |
| 442 | + def get_ubuntusso_attr(self): |
| 443 | + """Return the secret of the SSO item in a dictionary.""" |
| 444 | + # If we have no attributes, return None |
| 445 | + exist = self._get_item_info_from_name(self.KEYRING_NAME, self.app_name) |
| 446 | + if exist is not None: |
| 447 | + secret = self._get_item_info_from_name(self.KEYRING_NAME, |
| 448 | + self.app_name).get_secret() |
| 449 | + return dict(parse_qsl(secret)) |
| 450 | + |
| 451 | + def delete_ubuntusso_attr(self): |
| 452 | + """Delete a set of credentials from the keyring.""" |
| 453 | + item_id = self._get_item_id_from_name(self.KEYRING_NAME, |
| 454 | + self.app_name) |
| 455 | + if item_id is not None: |
| 456 | + gnomekeyring.item_delete_sync(self.KEYRING_NAME, item_id) |
| 457 | + |
| 458 | + |
| 459 | +if __name__ == "__main__": |
| 460 | + kr1 = Keyring("Test key 1") |
| 461 | + kr2 = Keyring("Test key 2") |
| 462 | + |
| 463 | + kr1.delete_ubuntusso_attr() |
| 464 | + kr2.delete_ubuntusso_attr() |
| 465 | + |
| 466 | + d1 = {"name": "test-1", "ha": "hehddddeff", "hi": "hggehes", "ho": "he"} |
| 467 | + d2 = {"name": "test-2", "hi": "ho", "let's": "go"} |
| 468 | + |
| 469 | + kr1.set_ubuntusso_attr(d1) |
| 470 | + kr2.set_ubuntusso_attr(d2) |
| 471 | + |
| 472 | + r1 = kr1.get_ubuntusso_attr() |
| 473 | + r2 = kr2.get_ubuntusso_attr() |
| 474 | + |
| 475 | + assert r1 == d1 |
| 476 | + assert r2 == d2 |
| 477 | |
| 478 | === modified file 'ubuntu_sso/main.py' |
| 479 | --- ubuntu_sso/main.py 2010-08-12 00:00:08 +0000 |
| 480 | +++ ubuntu_sso/main.py 2010-08-19 17:58:43 +0000 |
| 481 | @@ -199,8 +199,8 @@ |
| 482 | logger.exception('login failed with:') |
| 483 | raise AuthenticationError() |
| 484 | |
| 485 | - logger.debug('login: authentication successful! consumer_key: %r', |
| 486 | - credentials['consumer_key']) |
| 487 | + logger.debug('login: authentication successful! consumer_key: %r, ' \ |
| 488 | + 'token_name: %r', credentials['consumer_key'], token_name) |
| 489 | keyring_store_credentials(app_name, credentials) |
| 490 | return credentials |
| 491 | |
| 492 | @@ -413,8 +413,8 @@ |
| 493 | class SSOCredentials(dbus.service.Object): |
| 494 | """DBus object that gets credentials, and login/registers if needed.""" |
| 495 | |
| 496 | - @dbus.service.signal(DBUS_IFACE_CRED_NAME, signature="s") |
| 497 | - def AuthorizationDenied(self, app_name): |
| 498 | + @dbus.service.signal(DBUS_IFACE_CRED_NAME, signature="") |
| 499 | + def AuthorizationDenied(self): |
| 500 | """Signal thrown when the user denies the authorization.""" |
| 501 | |
| 502 | @dbus.service.signal(DBUS_IFACE_CRED_NAME, signature="a{ss}") |
| 503 | |
| 504 | === modified file 'ubuntu_sso/tests/test_gui.py' |
| 505 | --- ubuntu_sso/tests/test_gui.py 2010-08-12 00:00:08 +0000 |
| 506 | +++ ubuntu_sso/tests/test_gui.py 2010-08-19 17:58:43 +0000 |
| 507 | @@ -22,10 +22,10 @@ |
| 508 | import itertools |
| 509 | import logging |
| 510 | import os |
| 511 | -import socket |
| 512 | |
| 513 | import dbus |
| 514 | import gtk |
| 515 | +import webkit |
| 516 | |
| 517 | from twisted.trial.unittest import TestCase |
| 518 | |
| 519 | @@ -300,7 +300,6 @@ |
| 520 | super(UbuntuSSOClientTestCase, self).setUp() |
| 521 | self.patch(dbus, 'SessionBus', FakedSessionBus) |
| 522 | self.patch(dbus, 'Interface', FakedSSOBackend) |
| 523 | - self.patch(socket, 'gethostname', lambda: TOKEN_NAME) |
| 524 | self.pages = ('enter_details', 'processing', 'verify_email', 'success', |
| 525 | 'tc_browser', 'login', 'request_password_token', |
| 526 | 'set_new_password') |
| 527 | @@ -562,7 +561,7 @@ |
| 528 | def test_initial_text_for_header_label(self): |
| 529 | """The header must have the correct text at startup.""" |
| 530 | msg = 'Text for the header must be "%s" (got "%s" instead).' |
| 531 | - expected = self.ui.JOIN_HEADER_LABEL % APP_NAME |
| 532 | + expected = self.ui.JOIN_HEADER_LABEL % {'app_name': APP_NAME} |
| 533 | actual = self.ui.header_label.get_text() |
| 534 | # text content is correct |
| 535 | self.assertEqual(expected, actual, msg % (expected, actual)) |
| 536 | @@ -583,11 +582,11 @@ |
| 537 | def test_initial_texts_for_checkbuttons(self): |
| 538 | """Check buttons have the correct text at startup.""" |
| 539 | msg = 'Text for "%s" must be "%s" (got "%s" instead).' |
| 540 | - expected = self.ui.YES_TO_UPDATES |
| 541 | + expected = self.ui.YES_TO_UPDATES % {'app_name': APP_NAME} |
| 542 | actual = self.ui.yes_to_updates_checkbutton.get_label() |
| 543 | self.assertEqual(expected, actual, msg % ('yes_to_updates_checkbutton', |
| 544 | expected, actual)) |
| 545 | - expected = self.ui.YES_TO_TC |
| 546 | + expected = self.ui.YES_TO_TC % {'app_name': APP_NAME} |
| 547 | actual = self.ui.yes_to_tc_checkbutton.get_label() |
| 548 | self.assertEqual(expected, actual, |
| 549 | msg % ('yes_to_tc_checkbutton', expected, actual)) |
| 550 | @@ -731,6 +730,29 @@ |
| 551 | class TermsAndConditionsTestCase(UbuntuSSOClientTestCase): |
| 552 | """Test suite for the user registration (terms & conditions page).""" |
| 553 | |
| 554 | + def test_tc_browser_is_created_when_tc_page_is_shown(self): |
| 555 | + """The webkit browser is created when the TC page is shown.""" |
| 556 | + self.ui.tc_browser_vbox.show() |
| 557 | + |
| 558 | + children = self.ui.tc_browser_window.get_children() |
| 559 | + self.assertEqual(1, len(children)) |
| 560 | + browser = children[0] |
| 561 | + self.assertIsInstance(browser, webkit.WebView) |
| 562 | + self.assertTrue(browser.get_property('visible')) |
| 563 | + |
| 564 | + self.ui.tc_browser_vbox.hide() |
| 565 | + |
| 566 | + def test_tc_browser_is_destroyed_when_tc_page_is_hid(self): |
| 567 | + """The webkit browser is destroyed when the TC page is hid.""" |
| 568 | + self.ui.tc_browser_vbox.show() |
| 569 | + browser = self.ui.tc_browser_window.get_children()[0] |
| 570 | + self.patch(browser, 'destroy', self._set_called) |
| 571 | + self.ui.tc_browser_vbox.hide() |
| 572 | + |
| 573 | + children = self.ui.tc_browser_window.get_children() |
| 574 | + self.assertEqual(0, len(children)) |
| 575 | + self.assertEqual(self._called, ((), {})) |
| 576 | + |
| 577 | def test_tc_button_clicked_morphs_into_tc_browser_vbox(self): |
| 578 | """Terms & Conditions morphs to a browser window.""" |
| 579 | self.ui.tc_button.clicked() |
| 580 | @@ -1001,14 +1023,14 @@ |
| 581 | def test_initial_text_for_header_label(self): |
| 582 | """The header must have the correct text when logging in.""" |
| 583 | msg = 'Text for the header must be "%s" (got "%s" instead).' |
| 584 | - expected = self.ui.LOGIN_HEADER_LABEL % APP_NAME |
| 585 | + expected = self.ui.LOGIN_HEADER_LABEL % {'app_name': APP_NAME} |
| 586 | actual = self.ui.header_label.get_text() |
| 587 | self.assertEqual(expected, actual, msg % (expected, actual)) |
| 588 | |
| 589 | def test_initial_text_for_help_label(self): |
| 590 | """The help must have the correct text at startup.""" |
| 591 | msg = 'Text for the help must be "%s" (got "%s" instead).' |
| 592 | - expected = self.ui.CONNECT_HELP_LABEL % APP_NAME |
| 593 | + expected = self.ui.CONNECT_HELP_LABEL % {'app_name': APP_NAME} |
| 594 | actual = self.ui.help_label.get_text() |
| 595 | self.assertEqual(expected, actual, msg % (expected, actual)) |
| 596 | |
| 597 | @@ -1225,7 +1247,7 @@ |
| 598 | self.ui.on_password_reset_token_sent(email=EMAIL) |
| 599 | |
| 600 | self.assertEqual(self.ui.help_label.get_text(), |
| 601 | - self.ui.SET_NEW_PASSWORD_LABEL % EMAIL) |
| 602 | + self.ui.SET_NEW_PASSWORD_LABEL % {'email': EMAIL}) |
| 603 | |
| 604 | def test_on_password_reset_token_sent_ok_button(self): |
| 605 | """After request_password_token_ok_button the ok button is updated.""" |
| 606 | |
| 607 | === added file 'ubuntu_sso/tests/test_keyring.py' |
| 608 | --- ubuntu_sso/tests/test_keyring.py 1970-01-01 00:00:00 +0000 |
| 609 | +++ ubuntu_sso/tests/test_keyring.py 2010-08-19 17:58:43 +0000 |
| 610 | @@ -0,0 +1,115 @@ |
| 611 | +# test_keyring - tests for ubuntu_sso.keyring |
| 612 | +# |
| 613 | +# Author: Alejandro J. Cura <alecu@canonical.com> |
| 614 | +# |
| 615 | +# Copyright 2010 Canonical Ltd. |
| 616 | +# |
| 617 | +# This program is free software: you can redistribute it and/or modify it |
| 618 | +# under the terms of the GNU General Public License version 3, as published |
| 619 | +# by the Free Software Foundation. |
| 620 | +# |
| 621 | +# This program is distributed in the hope that it will be useful, but |
| 622 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
| 623 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
| 624 | +# PURPOSE. See the GNU General Public License for more details. |
| 625 | +# |
| 626 | +# You should have received a copy of the GNU General Public License along |
| 627 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
| 628 | +"""Tests for the keyring.py module.""" |
| 629 | + |
| 630 | +import gnomekeyring |
| 631 | +from twisted.trial.unittest import TestCase |
| 632 | + |
| 633 | +from ubuntu_sso import keyring |
| 634 | + |
| 635 | + |
| 636 | +class MockInfoSync(object): |
| 637 | + """A mock object that represents a fake key.""" |
| 638 | + |
| 639 | + def __init__(self, (key, key_name, secret)): |
| 640 | + """Initialize this instance.""" |
| 641 | + self.key = key |
| 642 | + self.key_name = key_name |
| 643 | + self.secret = secret |
| 644 | + |
| 645 | + def get_display_name(self): |
| 646 | + """Return info on the mocked object.""" |
| 647 | + return self.key_name |
| 648 | + |
| 649 | + |
| 650 | +class MockGnomeKeyring(object): |
| 651 | + """A mock keyring that stores keys according to a given attr.""" |
| 652 | + |
| 653 | + def __init__(self): |
| 654 | + """Initialize this instance.""" |
| 655 | + self.keyrings = set() |
| 656 | + self.store = [] |
| 657 | + self.deleted = [] |
| 658 | + |
| 659 | + def item_create_sync(self, keyring_name, item_type, key_name, attr, |
| 660 | + secret, update_if_exists): |
| 661 | + """Sets a value in the keyring.""" |
| 662 | + # we'll use the attr as the dict key, so make it a tuple |
| 663 | + key = tuple(attr.items()) |
| 664 | + self.store.append((key, key_name, secret)) |
| 665 | + |
| 666 | + def item_delete_sync(self, keyring_name, item_id): |
| 667 | + """Makes a list of deleted items.""" |
| 668 | + key, key_name, secret = self.store.pop(item_id) |
| 669 | + self.deleted.append(key_name) |
| 670 | + |
| 671 | + def list_item_ids_sync(self, keyring_name): |
| 672 | + """Return a list of ids for all the items.""" |
| 673 | + return [n for n, v in enumerate(self.store)] |
| 674 | + |
| 675 | + def item_get_info_sync(self, keyring_name, item_id): |
| 676 | + """Return an info sync object for the item.""" |
| 677 | + return MockInfoSync(self.store[item_id]) |
| 678 | + |
| 679 | + def list_keyring_names_sync(self): |
| 680 | + """The keyring you are looking for may be here.""" |
| 681 | + return self.keyrings |
| 682 | + |
| 683 | + def create_sync(self, name): |
| 684 | + """Thanks, I'll create that keyring for you.""" |
| 685 | + self.keyrings.add(name) |
| 686 | + |
| 687 | + def is_available(self): |
| 688 | + """A very available keyring.""" |
| 689 | + return True |
| 690 | + |
| 691 | + |
| 692 | +class TestKeyring(TestCase): |
| 693 | + """Test the gnome keyring related functions.""" |
| 694 | + def setUp(self): |
| 695 | + """Initialize the mock used in these tests.""" |
| 696 | + self.mgk = MockGnomeKeyring() |
| 697 | + self.patch(gnomekeyring, "item_create_sync", self.mgk.item_create_sync) |
| 698 | + self.patch(gnomekeyring, "is_available", self.mgk.is_available) |
| 699 | + self.patch(gnomekeyring, "create_sync", self.mgk.create_sync) |
| 700 | + self.patch(gnomekeyring, "list_keyring_names_sync", |
| 701 | + self.mgk.list_keyring_names_sync) |
| 702 | + self.patch(gnomekeyring, "list_item_ids_sync", |
| 703 | + self.mgk.list_item_ids_sync) |
| 704 | + self.patch(gnomekeyring, "item_get_info_sync", |
| 705 | + self.mgk.item_get_info_sync) |
| 706 | + self.patch(gnomekeyring, "item_delete_sync", self.mgk.item_delete_sync) |
| 707 | + |
| 708 | + def test_set_ubuntusso(self): |
| 709 | + """Test that the set method does not erase previous keys.""" |
| 710 | + sample_creds = {"name": "sample creds name"} |
| 711 | + sample_creds2 = {"name": "sample creds name 2"} |
| 712 | + keyring.Keyring("appname").set_ubuntusso_attr(sample_creds) |
| 713 | + keyring.Keyring("appname").set_ubuntusso_attr(sample_creds2) |
| 714 | + |
| 715 | + self.assertEqual(len(self.mgk.store), 2) |
| 716 | + self.assertEqual(len(self.mgk.deleted), 0) |
| 717 | + |
| 718 | + def test_delete_ubuntusso(self): |
| 719 | + """Test that a given key is deleted.""" |
| 720 | + sample_creds = {"name": "sample creds name"} |
| 721 | + keyring.Keyring("appname").set_ubuntusso_attr(sample_creds) |
| 722 | + keyring.Keyring("appname").delete_ubuntusso_attr() |
| 723 | + |
| 724 | + self.assertEqual(len(self.mgk.store), 0) |
| 725 | + self.assertEqual(len(self.mgk.deleted), 1) |

