~nataliabidart/ubuntu/natty/ubuntu-sso-client/ubuntu-sso-client-1.1.8

« back to all changes in this revision

Viewing changes to ubuntu_sso/gui.py

  • Committer: Sebastien Bacher
  • Date: 2010-11-05 16:43:51 UTC
  • mfrom: (18.1.2 ubuntu-sso-client-1.1.2)
  • Revision ID: seb128@ubuntu.com-20101105164351-m8gs1szkk21hefzx
Tags: 1.1.2-0ubuntu1
releasing version 1.1.2-0ubuntu1

Show diffs side-by-side

added added

removed removed

Lines of Context:
205
205
    """Ubuntu single sign on GUI."""
206
206
 
207
207
    CAPTCHA_SOLUTION_ENTRY = _('Type the characters above')
 
208
    CAPTCHA_LOAD_ERROR = _('There was a problem getting the captcha, '
 
209
                           'reloading...')
208
210
    CONNECT_HELP_LABEL = _('To connect this computer to %(app_name)s ' \
209
211
                           'enter your details below.')
210
212
    EMAIL1_ENTRY = _('Email address')
213
215
                       'and try entering them again.')
214
216
    EMAIL_INVALID = _('The email must be a valid email address.')
215
217
    EMAIL_TOKEN_ENTRY = _('Enter code verification here')
 
218
    ERROR = _('The process did not finish successfully.')
216
219
    FIELD_REQUIRED = _('This field is required.')
217
220
    FORGOTTEN_PASSWORD_BUTTON = _('I\'ve forgotten my password')
218
221
    JOIN_HEADER_LABEL = _('Create %(app_name)s account')
256
259
    YES_TO_UPDATES = _('Yes! Email me %(app_name)s tips and updates.')
257
260
    CAPTCHA_RELOAD_TOOLTIP = _('Reload')
258
261
 
259
 
    def __init__(self, app_name, tc_url, help_text,
 
262
    def __init__(self, app_name, tc_url='', help_text='',
260
263
                 window_id=0, login_only=False, close_callback=None):
261
264
        """Create the GUI and initialize widgets."""
262
265
        gtk.link_button_set_uri_hook(NO_OP)
264
267
        self._captcha_filename = tempfile.mktemp()
265
268
        self._captcha_id = None
266
269
        self._signals_receivers = {}
 
270
        self._done = False  # whether the whole process was completed or not
267
271
 
268
272
        self.app_name = app_name
269
273
        self.app_label = '<b>%s</b>' % self.app_name
270
274
        self.tc_url = tc_url
271
275
        self.help_text = help_text
272
276
        self.close_callback = close_callback
 
277
        self.user_email = None
 
278
        self.user_password = None
273
279
 
274
280
        ui_filename = get_data_file('ui.glade')
275
281
        builder = gtk.Builder()
325
331
        logger.debug('UbuntuSSOClientGUI: backend created: %r', self.backend)
326
332
 
327
333
        self.pages = (self.enter_details_vbox, self.processing_vbox,
328
 
                      self.verify_email_vbox, self.success_vbox,
 
334
                      self.verify_email_vbox, self.finish_vbox,
329
335
                      self.tc_browser_vbox, self.login_vbox,
330
336
                      self.request_password_token_vbox,
331
337
                      self.set_new_password_vbox)
332
338
 
333
339
        self._append_page(self._build_processing_page())
334
 
        self._append_page(self._build_success_page())
 
340
        self._append_page(self._build_finish_page())
335
341
        self._append_page(self._build_login_page())
336
342
        self._append_page(self._build_request_password_token_page())
337
343
        self._append_page(self._build_set_new_password_page())
 
344
        self._append_page(self._build_verify_email_page())
338
345
 
339
346
        window_size = None
340
347
        if not login_only:
341
348
            window_size = (550, 500)
342
349
            self._append_page(self._build_enter_details_page())
343
350
            self._append_page(self._build_tc_page())
344
 
            self._append_page(self._build_verify_email_page())
345
351
            self.login_button.grab_focus()
346
352
            self._set_current_page(self.enter_details_vbox)
347
353
        else:
373
379
             self._filter_by_app_name(self.on_logged_in),
374
380
            'LoginError':
375
381
             self._filter_by_app_name(self.on_login_error),
 
382
            'UserNotValidated':
 
383
             self._filter_by_app_name(self.on_user_not_validated),
376
384
            'PasswordResetTokenSent':
377
385
             self._filter_by_app_name(self.on_password_reset_token_sent),
378
386
            'PasswordResetError':
383
391
             self._filter_by_app_name(self.on_password_change_error),
384
392
        }
385
393
        self._setup_signals()
386
 
        self._gtk_signal_log = []
387
394
 
388
395
        if window_id != 0:
389
396
            # be as robust as possible:
405
412
 
406
413
        self.window.show()
407
414
 
 
415
    @property
 
416
    def success_vbox(self):
 
417
        """The success page."""
 
418
        self.finish_vbox.label.set_markup('<span size="x-large">%s</span>' %
 
419
                                          self.SUCCESS)
 
420
        return self.finish_vbox
 
421
 
 
422
    @property
 
423
    def error_vbox(self):
 
424
        """The error page."""
 
425
        self.finish_vbox.label.set_markup('<span size="x-large">%s</span>' %
 
426
                                          self.ERROR)
 
427
        return self.finish_vbox
 
428
 
 
429
    # helpers
 
430
 
408
431
    def _filter_by_app_name(self, f):
409
432
        """Excecute the decorated function only for 'self.app_name'."""
410
433
 
460
483
        alignment.add(hbox)
461
484
        alignment.show_all()
462
485
 
 
486
        # remove children to avoid:
 
487
        # GtkWarning: Attempting to add a widget with type GtkAlignment to a
 
488
        # GtkEventBox, but as a GtkBin subclass a GtkEventBox can only contain
 
489
        # one widget at a time
 
490
        for child in container.get_children():
 
491
            container.remove(child)
463
492
        container.add(alignment)
464
493
 
465
 
    # helpers
466
 
 
467
494
    def _set_warning_message(self, widget, message):
468
495
        """Set 'message' as text for 'widget'."""
469
496
        widget.set_text(message)
600
627
        self.verify_email_vbox.default_widget = self.verify_token_button
601
628
        self.verify_email_vbox.default_widget.set_flags(gtk.CAN_DEFAULT)
602
629
 
603
 
        self.verify_email_vbox.pack_start(self.email_token_entry, expand=False)
604
 
        self.verify_email_vbox.reorder_child(self.email_token_entry, 0)
 
630
        self.verify_email_details_vbox.pack_start(self.email_token_entry,
 
631
                                                  expand=False)
605
632
 
606
633
        return self.verify_email_vbox
607
634
 
608
 
    def _build_success_page(self):
 
635
    def _build_finish_page(self):
609
636
        """Build the success page."""
610
 
        self.success_vbox.default_widget = self.success_close_button
611
 
        self.success_vbox.default_widget.set_flags(gtk.CAN_DEFAULT)
612
 
 
613
 
        self.success_label.set_markup('<span size="x-large">%s</span>' %
614
 
                                      self.SUCCESS)
615
 
        return self.success_vbox
 
637
        self.finish_vbox.default_widget = self.finish_close_button
 
638
        self.finish_vbox.default_widget.set_flags(gtk.CAN_DEFAULT)
 
639
        self.finish_vbox.label = self.finish_label
 
640
        return self.finish_vbox
616
641
 
617
642
    def _build_login_page(self):
618
643
        """Build the login page."""
716
741
                     signal_name, handler, args, kwargs)
717
742
        self.window.connect(signal_name, handler, *args, **kwargs)
718
743
 
 
744
    def emit(self, *args, **kwargs):
 
745
        """Emit a signal proxing the main window."""
 
746
        logger.debug('emit: args  %r, kwargs, %r', args, kwargs)
 
747
        self.window.emit(*args, **kwargs)
 
748
 
 
749
    def finish_success(self):
 
750
        """The whole process was completed succesfully. Show success page."""
 
751
        self._done = True
 
752
        self._set_current_page(self.success_vbox)
 
753
 
 
754
    def finish_error(self, error):
 
755
        """The whole process was not completed succesfully. Show error page."""
 
756
        self._done = True
 
757
        self._set_current_page(self.error_vbox)
 
758
 
719
759
    def on_close_clicked(self, *args, **kwargs):
720
760
        """Call self.close_callback if defined."""
721
761
        if os.path.exists(self._captcha_filename):
737
777
        while gtk.events_pending():
738
778
            gtk.main_iteration()
739
779
 
740
 
        if len(args) > 0 and args[0] in self.cancels:
741
 
            self.window.emit(SIG_USER_CANCELATION, self.app_name)
742
 
        elif len(self._gtk_signal_log) > 0:
743
 
            signal = self._gtk_signal_log[-1][0]
744
 
            args = self._gtk_signal_log[-1][1:]
745
 
            logger.info('emitting %r with args %r.', signal, args)
746
 
            self.window.emit(signal, *args)
747
 
        else:
748
 
            self.window.emit(SIG_USER_CANCELATION, self.app_name)
 
780
        if not self._done:
 
781
            self.emit(SIG_USER_CANCELATION, self.app_name)
749
782
 
750
783
        # call user defined callback
751
784
        if self.close_callback is not None:
805
838
            return
806
839
 
807
840
        self._set_current_page(self.processing_vbox)
 
841
        self.user_email = email1
 
842
        self.user_password = password1
808
843
 
809
844
        logger.info('Calling register_user with email %r, password <hidden>,' \
810
845
                    ' captcha_id %r and captcha_solution %r.', email1,
825
860
            self.email_token_entry.set_warning(self.FIELD_REQUIRED)
826
861
            return
827
862
 
828
 
        email = self.email1_entry.get_text()
829
 
        password = self.password1_entry.get_text()
 
863
        email = self.user_email
 
864
        password = self.user_password
830
865
        f = self.backend.validate_email
831
866
        logger.info('Calling validate_email with email %r, password <hidden>' \
832
867
                    ', app_name %r and email_token %r.', email, self.app_name,
864
899
          reply_handler=NO_OP, error_handler=NO_OP)
865
900
 
866
901
        self._set_current_page(self.processing_vbox)
 
902
        self.user_email = email
 
903
        self.user_password = password
867
904
 
868
905
    def on_login_back_button_clicked(self, *args, **kwargs):
869
906
        """User wants to go to the previous page."""
1025
1062
            result = msg1 if msg1 is not None else msg2
1026
1063
        return result
1027
1064
 
1028
 
    def _append_error_signal(self, signal, error):
1029
 
        """Append 'signal' to the log with a formatted version of 'error'.
1030
 
 
1031
 
        Format DBus dict 'error' into a nice string.
1032
 
 
1033
 
        """
1034
 
        msg = '\n'.join('%s: %s' % i for i in error.iteritems())
1035
 
        self._gtk_signal_log.append((signal, self.app_name, msg))
1036
 
 
1037
1065
    @log_call
1038
1066
    def on_captcha_generated(self, app_name, captcha_id, *args, **kwargs):
1039
1067
        """Captcha image has been generated and is available to be shown."""
1046
1074
    @log_call
1047
1075
    def on_captcha_generation_error(self, app_name, error, *args, **kwargs):
1048
1076
        """Captcha image generation failed."""
 
1077
        self._set_warning_message(self.warning_label, self.CAPTCHA_LOAD_ERROR)
 
1078
        self._generate_captcha()
1049
1079
 
1050
1080
    @log_call
1051
1081
    def on_user_registered(self, app_name, email, *args, **kwargs):
1069
1099
            self.password2_entry.set_warning(msg)
1070
1100
 
1071
1101
        msg = self._build_general_error_message(error)
 
1102
        self._generate_captcha()
1072
1103
        self._set_current_page(self.enter_details_vbox, warning_text=msg)
1073
 
        self._append_error_signal(SIG_REGISTRATION_FAILED, error)
1074
1104
 
1075
1105
    @log_call
1076
1106
    def on_email_validated(self, app_name, email, *args, **kwargs):
1077
1107
        """User email was successfully verified."""
1078
 
        self._set_current_page(self.success_vbox)
1079
 
        self._gtk_signal_log.append((SIG_REGISTRATION_SUCCEEDED, self.app_name,
1080
 
                                    email))
 
1108
        self._done = True
 
1109
        self.emit(SIG_REGISTRATION_SUCCEEDED, self.app_name, email)
1081
1110
 
1082
1111
    @log_call
1083
1112
    def on_email_validation_error(self, app_name, error, *args, **kwargs):
1088
1117
 
1089
1118
        msg = self._build_general_error_message(error)
1090
1119
        self._set_current_page(self.verify_email_vbox, warning_text=msg)
1091
 
        self._append_error_signal(SIG_REGISTRATION_FAILED, error)
1092
1120
 
1093
1121
    @log_call
1094
1122
    def on_logged_in(self, app_name, email, *args, **kwargs):
1095
1123
        """User was successfully logged in."""
1096
 
        self._set_current_page(self.success_vbox)
1097
 
        self._gtk_signal_log.append((SIG_LOGIN_SUCCEEDED, self.app_name,
1098
 
                                    email))
 
1124
        self._done = True
 
1125
        self.emit(SIG_LOGIN_SUCCEEDED, self.app_name, email)
1099
1126
 
1100
1127
    @log_call
1101
1128
    def on_login_error(self, app_name, error, *args, **kwargs):
1102
1129
        """User was not successfully logged in."""
1103
1130
        msg = self._build_general_error_message(error)
1104
1131
        self._set_current_page(self.login_vbox, warning_text=msg)
1105
 
        self._append_error_signal(SIG_LOGIN_FAILED, error)
 
1132
 
 
1133
    @log_call
 
1134
    def on_user_not_validated(self, app_name, email, *args, **kwargs):
 
1135
        """User was not validated."""
 
1136
        self.on_user_registered(app_name, email)
1106
1137
 
1107
1138
    @log_call
1108
1139
    def on_password_reset_token_sent(self, app_name, email, *args, **kwargs):