From ad16a72f60ecc84524c22e8912df4eb8a48a2a42 Mon Sep 17 00:00:00 2001 From: kali Date: Tue, 6 Nov 2012 16:26:10 +0900 Subject: split wizard into separate files so we don't go nuts yet. --- src/leap/gui/firstrun/register.py | 211 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 src/leap/gui/firstrun/register.py (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py new file mode 100644 index 00000000..b04844bf --- /dev/null +++ b/src/leap/gui/firstrun/register.py @@ -0,0 +1,211 @@ +""" +Register User Page, used in First Run Wizard +""" +import json +import logging +import socket + +import requests + +from PyQt4 import QtCore +from PyQt4 import QtGui + +from leap.base import auth +from leap.gui.firstrun.mixins import UserFormMixIn + +logger = logging.getLogger(__name__) + +from leap.gui.constants import APP_LOGO, BARE_USERNAME_REGEX +from leap.gui.styles import ErrorLabelStyleSheet + + +class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): + setSigningUpStatus = QtCore.pyqtSignal([]) + + def __init__(self, parent=None): + super(RegisterUserPage, self).__init__(parent) + + # bind wizard page signals + self.setSigningUpStatus.connect( + lambda: self.set_validation_status( + 'validating')) + + self.setTitle("Sign Up") + + self.setPixmap( + QtGui.QWizard.LogoPixmap, + QtGui.QPixmap(APP_LOGO)) + + userNameLabel = QtGui.QLabel("User &name:") + userNameLineEdit = QtGui.QLineEdit() + userNameLineEdit.cursorPositionChanged.connect( + self.reset_validation_status) + userNameLabel.setBuddy(userNameLineEdit) + + # let's add regex validator + usernameRe = QtCore.QRegExp(BARE_USERNAME_REGEX) + userNameLineEdit.setValidator( + QtGui.QRegExpValidator(usernameRe, self)) + self.userNameLineEdit = userNameLineEdit + + userPasswordLabel = QtGui.QLabel("&Password:") + self.userPasswordLineEdit = QtGui.QLineEdit() + self.userPasswordLineEdit.setEchoMode( + QtGui.QLineEdit.Password) + userPasswordLabel.setBuddy(self.userPasswordLineEdit) + + userPassword2Label = QtGui.QLabel("Password (again):") + self.userPassword2LineEdit = QtGui.QLineEdit() + self.userPassword2LineEdit.setEchoMode( + QtGui.QLineEdit.Password) + userPassword2Label.setBuddy(self.userPassword2LineEdit) + + rememberPasswordCheckBox = QtGui.QCheckBox( + "&Remember username and password.") + rememberPasswordCheckBox.setChecked(True) + + self.registerField('userName*', self.userNameLineEdit) + self.registerField('userPassword*', self.userPasswordLineEdit) + + # XXX missing password confirmation + # XXX validator! + + self.registerField('rememberPassword', rememberPasswordCheckBox) + + layout = QtGui.QGridLayout() + layout.setColumnMinimumWidth(0, 20) + + validationMsg = QtGui.QLabel("") + validationMsg.setStyleSheet(ErrorLabelStyleSheet) + + self.validationMsg = validationMsg + + layout.addWidget(validationMsg, 0, 3) + layout.addWidget(userNameLabel, 1, 0) + layout.addWidget(self.userNameLineEdit, 1, 3) + layout.addWidget(userPasswordLabel, 2, 0) + layout.addWidget(userPassword2Label, 3, 0) + layout.addWidget(self.userPasswordLineEdit, 2, 3) + layout.addWidget(self.userPassword2LineEdit, 3, 3) + layout.addWidget(rememberPasswordCheckBox, 4, 3, 4, 4) + self.setLayout(layout) + + # overwritten methods + + def initializePage(self): + """ + inits wizard page + """ + provider = self.field('provider_domain') + self.setSubTitle( + "Register a new user with provider %s." % + provider) + self.validationMsg.setText('') + + def validatePage(self): + """ + validation + we initialize the srp protocol register + and try to register user. if error + returned we write validation error msg + above the form. + """ + # the slot for this signal is not doing + # what's expected. Investigate why, + # right now we're not giving any feedback + # to the user re. what's going on. The only + # thing I can see as a workaround is setting + # a low timeout. + wizard = self.wizard() + + self.setSigningUpStatus.emit() + + username = self.userNameLineEdit.text() + password = self.userPasswordLineEdit.text() + password2 = self.userPassword2LineEdit.text() + + # have some call to a password checker... + + if password != password2: + self.set_validation_status('Password does not match.') + return False + + if len(password) < 6: + self.set_validation_status('Password too short.') + return False + + if password == "123456": + # joking + self.set_validation_status('Password too obvious.') + return False + + domain = self.field('provider_domain') + + if wizard and wizard.debug_server: + # We're debugging + dbgsrv = wizard.debug_server + schema = dbgsrv.scheme + netloc = dbgsrv.netloc + port = None + netloc_split = netloc.split(':') + if len(netloc_split) > 1: + provider, port = netloc_split + else: + provider = netloc + + signup = auth.LeapSRPRegister( + scheme=schema, + provider=provider, + port=port) + + else: + # this is the real thing + signup = auth.LeapSRPRegister( + # XXX FIXME 0 Force HTTPS + #schema="https", + schema="http", + provider=domain) + try: + ok, req = signup.register_user(username, password) + except socket.timeout: + self.set_validation_status( + "Error connecting to provider (timeout)") + return False + + except requests.exceptions.ConnectionError as exc: + logger.error(exc) + self.set_validation_status( + "Error connecting to provider " + "(connection error)") + return False + + if ok: + return True + + # something went wrong. + # not registered, let's catch what. + # get timeout + # ... + if req.status_code == 500: + self.set_validation_status( + "Error during registration (500)") + return False + + validation_msgs = json.loads(req.content) + logger.debug('validation errors: %s' % validation_msgs) + errors = validation_msgs.get('errors', None) + if errors and errors.get('login', None): + # XXX this sometimes catch the blank username + # but we're not allowing that (soon) + self.set_validation_status( + 'Username not available.') + else: + self.set_validation_status( + "Error during sign up") + return False + + def nextId(self): + wizard = self.wizard() + if not wizard: + return + return wizard.get_page_index('connecting') -- cgit v1.2.3 From 00009f8a7de957c4d53c10855cae1396108203c3 Mon Sep 17 00:00:00 2001 From: kali Date: Tue, 6 Nov 2012 16:35:48 +0900 Subject: add 404 catch to register --- src/leap/gui/firstrun/register.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py index b04844bf..b169f45b 100644 --- a/src/leap/gui/firstrun/register.py +++ b/src/leap/gui/firstrun/register.py @@ -101,6 +101,7 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): "Register a new user with provider %s." % provider) self.validationMsg.setText('') + self.userPassword2LineEdit.setText('') def validatePage(self): """ @@ -110,12 +111,6 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): returned we write validation error msg above the form. """ - # the slot for this signal is not doing - # what's expected. Investigate why, - # right now we're not giving any feedback - # to the user re. what's going on. The only - # thing I can see as a workaround is setting - # a low timeout. wizard = self.wizard() self.setSigningUpStatus.emit() @@ -124,7 +119,9 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): password = self.userPasswordLineEdit.text() password2 = self.userPassword2LineEdit.text() - # have some call to a password checker... + # we better have here + # some call to a password checker... + # to assess strenght and avoid silly stuff. if password != password2: self.set_validation_status('Password does not match.') @@ -161,7 +158,9 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): else: # this is the real thing signup = auth.LeapSRPRegister( - # XXX FIXME 0 Force HTTPS + # XXX FIXME FIXME FIXME FIXME + # XXX FIXME 0 Force HTTPS !!! + # XXX FIXME FIXME FIXME FIXME #schema="https", schema="http", provider=domain) @@ -191,6 +190,11 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): "Error during registration (500)") return False + if req.status_code == 404: + self.set_validation_status( + "Error during registration (404)") + return False + validation_msgs = json.loads(req.content) logger.debug('validation errors: %s' % validation_msgs) errors = validation_msgs.get('errors', None) -- cgit v1.2.3 From b3c0634dc6e01656422a6c70297fc46d808f303f Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 8 Nov 2012 06:02:36 +0900 Subject: selectprovider rename + fix onComplete function for provider entry --- src/leap/gui/firstrun/register.py | 95 +++++---------------------------------- 1 file changed, 11 insertions(+), 84 deletions(-) (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py index b169f45b..d7e8db0e 100644 --- a/src/leap/gui/firstrun/register.py +++ b/src/leap/gui/firstrun/register.py @@ -1,16 +1,12 @@ """ Register User Page, used in First Run Wizard """ -import json import logging -import socket -import requests from PyQt4 import QtCore from PyQt4 import QtGui -from leap.base import auth from leap.gui.firstrun.mixins import UserFormMixIn logger = logging.getLogger(__name__) @@ -20,9 +16,11 @@ from leap.gui.styles import ErrorLabelStyleSheet class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): + setSigningUpStatus = QtCore.pyqtSignal([]) def __init__(self, parent=None): + super(RegisterUserPage, self).__init__(parent) # bind wizard page signals @@ -105,17 +103,16 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): def validatePage(self): """ - validation - we initialize the srp protocol register - and try to register user. if error - returned we write validation error msg - above the form. + we only pre-validate here password weakness + stuff, or any other client side validation + that we think of. + real server validation is made on next page, + and if any errors are thrown there we come back + and re-display the validation label. """ - wizard = self.wizard() - self.setSigningUpStatus.emit() - username = self.userNameLineEdit.text() + #username = self.userNameLineEdit.text() password = self.userPasswordLineEdit.text() password2 = self.userPassword2LineEdit.text() @@ -136,80 +133,10 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): self.set_validation_status('Password too obvious.') return False - domain = self.field('provider_domain') - - if wizard and wizard.debug_server: - # We're debugging - dbgsrv = wizard.debug_server - schema = dbgsrv.scheme - netloc = dbgsrv.netloc - port = None - netloc_split = netloc.split(':') - if len(netloc_split) > 1: - provider, port = netloc_split - else: - provider = netloc - - signup = auth.LeapSRPRegister( - scheme=schema, - provider=provider, - port=port) - - else: - # this is the real thing - signup = auth.LeapSRPRegister( - # XXX FIXME FIXME FIXME FIXME - # XXX FIXME 0 Force HTTPS !!! - # XXX FIXME FIXME FIXME FIXME - #schema="https", - schema="http", - provider=domain) - try: - ok, req = signup.register_user(username, password) - except socket.timeout: - self.set_validation_status( - "Error connecting to provider (timeout)") - return False - - except requests.exceptions.ConnectionError as exc: - logger.error(exc) - self.set_validation_status( - "Error connecting to provider " - "(connection error)") - return False - - if ok: - return True - - # something went wrong. - # not registered, let's catch what. - # get timeout - # ... - if req.status_code == 500: - self.set_validation_status( - "Error during registration (500)") - return False - - if req.status_code == 404: - self.set_validation_status( - "Error during registration (404)") - return False - - validation_msgs = json.loads(req.content) - logger.debug('validation errors: %s' % validation_msgs) - errors = validation_msgs.get('errors', None) - if errors and errors.get('login', None): - # XXX this sometimes catch the blank username - # but we're not allowing that (soon) - self.set_validation_status( - 'Username not available.') - else: - self.set_validation_status( - "Error during sign up") - return False + return True def nextId(self): wizard = self.wizard() if not wizard: return - return wizard.get_page_index('connecting') + return wizard.get_page_index('signupvalidation') -- cgit v1.2.3 From 8118056a244ca74d16380ad26a70e3da40e7e401 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 9 Nov 2012 11:21:40 +0900 Subject: connect page merged into regvalidation. Flow nearly working with fake provider, except for authentication. --- src/leap/gui/firstrun/register.py | 49 +++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 17 deletions(-) (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py index d7e8db0e..0a7ba34b 100644 --- a/src/leap/gui/firstrun/register.py +++ b/src/leap/gui/firstrun/register.py @@ -17,23 +17,18 @@ from leap.gui.styles import ErrorLabelStyleSheet class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): - setSigningUpStatus = QtCore.pyqtSignal([]) - def __init__(self, parent=None): super(RegisterUserPage, self).__init__(parent) - # bind wizard page signals - self.setSigningUpStatus.connect( - lambda: self.set_validation_status( - 'validating')) - self.setTitle("Sign Up") self.setPixmap( QtGui.QWizard.LogoPixmap, QtGui.QPixmap(APP_LOGO)) + self.current_page = "signup" + userNameLabel = QtGui.QLabel("User &name:") userNameLineEdit = QtGui.QLineEdit() userNameLineEdit.cursorPositionChanged.connect( @@ -88,18 +83,28 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): layout.addWidget(rememberPasswordCheckBox, 4, 3, 4, 4) self.setLayout(layout) - # overwritten methods + # pagewizard methods - def initializePage(self): + def populateErrors(self): + # XXX could move this to ValidationMixin + + #logger.debug('getting errors') + errors = self.wizard().get_validation_error( + self.current_page) + if errors: + #logger.debug('errors! -> %s', errors) + self.validationMsg.setText(errors) + + def paintEvent(self, event): """ - inits wizard page + we hook our populate errors + on paintEvent because we need it to catch + when user enters the page coming from next, + and initializePage does not cover that case. + Maybe there's a better event to hook upon. """ - provider = self.field('provider_domain') - self.setSubTitle( - "Register a new user with provider %s." % - provider) - self.validationMsg.setText('') - self.userPassword2LineEdit.setText('') + super(RegisterUserPage, self).paintEvent(event) + self.populateErrors() def validatePage(self): """ @@ -110,7 +115,6 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): and if any errors are thrown there we come back and re-display the validation label. """ - self.setSigningUpStatus.emit() #username = self.userNameLineEdit.text() password = self.userPasswordLineEdit.text() @@ -135,6 +139,17 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): return True + def initializePage(self): + """ + inits wizard page + """ + provider = self.field('provider_domain') + self.setSubTitle( + "Register a new user with provider %s." % + provider) + self.validationMsg.setText('') + self.userPassword2LineEdit.setText('') + def nextId(self): wizard = self.wizard() if not wizard: -- cgit v1.2.3 From fe16e62fa83c24d2ef379a3f9e102d336e527656 Mon Sep 17 00:00:00 2001 From: kali Date: Mon, 12 Nov 2012 12:25:11 +0900 Subject: cleanup errors on page init and on field change --- src/leap/gui/firstrun/register.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py index 0a7ba34b..6d15c156 100644 --- a/src/leap/gui/firstrun/register.py +++ b/src/leap/gui/firstrun/register.py @@ -87,13 +87,25 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): def populateErrors(self): # XXX could move this to ValidationMixin + # used in providerselect too - #logger.debug('getting errors') errors = self.wizard().get_validation_error( self.current_page) if errors: - #logger.debug('errors! -> %s', errors) - self.validationMsg.setText(errors) + bad_str = getattr(self, 'bad_string', None) + cur_str = self.userNameLineEdit.text() + showerr = self.validationMsg.setText + if bad_str is None: + # first time we fall here. + # save the current bad_string value + self.bad_string = cur_str + showerr(errors) + else: + # not the first time + if cur_str == bad_str: + showerr(errors) + else: + showerr('') def paintEvent(self, event): """ -- cgit v1.2.3 From 42ba228eecb5726506848bd08758bd1f925905cc Mon Sep 17 00:00:00 2001 From: kali Date: Mon, 12 Nov 2012 12:45:37 +0900 Subject: fix prevalidation error showing in register page. --- src/leap/gui/firstrun/register.py | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py index 6d15c156..b46dd4cd 100644 --- a/src/leap/gui/firstrun/register.py +++ b/src/leap/gui/firstrun/register.py @@ -95,18 +95,30 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): bad_str = getattr(self, 'bad_string', None) cur_str = self.userNameLineEdit.text() showerr = self.validationMsg.setText + prev_er = getattr(self, 'prevalidation_error', None) + if bad_str is None: # first time we fall here. # save the current bad_string value self.bad_string = cur_str showerr(errors) else: + if prev_er: + showerr(prev_er) + return # not the first time if cur_str == bad_str: showerr(errors) else: showerr('') + def cleanup_errormsg(self): + """ + we reset bad_string to None + should be called before leaving the page + """ + self.bad_string = None + def paintEvent(self, event): """ we hook our populate errors @@ -118,6 +130,9 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): super(RegisterUserPage, self).paintEvent(event) self.populateErrors() + def set_prevalidation_error(self, error): + self.prevalidation_error = error + def validatePage(self): """ we only pre-validate here password weakness @@ -137,18 +152,22 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): # to assess strenght and avoid silly stuff. if password != password2: - self.set_validation_status('Password does not match.') + self.set_prevalidation_error('Password does not match.') return False if len(password) < 6: - self.set_validation_status('Password too short.') + self.set_prevalidation_error('Password too short.') return False if password == "123456": - # joking - self.set_validation_status('Password too obvious.') + # joking, but not too much. + self.set_prevalidation_error('Password too obvious.') return False + # some cleanup before we leave the page + self.cleanup_errormsg() + + # go return True def initializePage(self): -- cgit v1.2.3 From 4153bee65d2541b99d4e41aaaf2fd6b2b71b2cc3 Mon Sep 17 00:00:00 2001 From: kali Date: Mon, 19 Nov 2012 23:15:36 +0900 Subject: disable "next" button during validation and wait for user to click it. Closes #973 --- src/leap/gui/firstrun/register.py | 1 + 1 file changed, 1 insertion(+) (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py index b46dd4cd..e1a8149c 100644 --- a/src/leap/gui/firstrun/register.py +++ b/src/leap/gui/firstrun/register.py @@ -59,6 +59,7 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): self.registerField('userName*', self.userNameLineEdit) self.registerField('userPassword*', self.userPasswordLineEdit) + self.registerField('userPassword2*', self.userPassword2LineEdit) # XXX missing password confirmation # XXX validator! -- cgit v1.2.3 From 7ab2ea1adb82d8c1c6bbae4dc58a157326f579a2 Mon Sep 17 00:00:00 2001 From: kali Date: Mon, 19 Nov 2012 23:23:50 +0900 Subject: set commit page (no back button after validation) --- src/leap/gui/firstrun/register.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py index e1a8149c..f872a127 100644 --- a/src/leap/gui/firstrun/register.py +++ b/src/leap/gui/firstrun/register.py @@ -29,6 +29,13 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): self.current_page = "signup" + # commit page means there's no way back after this... + # XXX should change the text on the "commit" button... + self.setCommitPage(True) + + self.initUI() + + def initUI(self): userNameLabel = QtGui.QLabel("User &name:") userNameLineEdit = QtGui.QLineEdit() userNameLineEdit.cursorPositionChanged.connect( -- cgit v1.2.3 From 7a263b8ee74cc92ba39796cd9ad48395adfa7450 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 23 Nov 2012 05:13:36 +0900 Subject: refactor validation mixin; progress until register page --- src/leap/gui/firstrun/register.py | 158 ++++++++++++++++++++++++++++++-------- 1 file changed, 127 insertions(+), 31 deletions(-) (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py index f872a127..ddfcd1c5 100644 --- a/src/leap/gui/firstrun/register.py +++ b/src/leap/gui/firstrun/register.py @@ -2,7 +2,9 @@ Register User Page, used in First Run Wizard """ import logging +import socket +import requests from PyQt4 import QtCore from PyQt4 import QtGui @@ -11,31 +13,34 @@ from leap.gui.firstrun.mixins import UserFormMixIn logger = logging.getLogger(__name__) +from leap.base import auth from leap.gui.constants import APP_LOGO, BARE_USERNAME_REGEX +from leap.gui.progress import InlineValidationPage from leap.gui.styles import ErrorLabelStyleSheet -class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): +class RegisterUserPage(InlineValidationPage, UserFormMixIn): def __init__(self, parent=None): super(RegisterUserPage, self).__init__(parent) + self.current_page = "signup" - self.setTitle("Sign Up") + self.setTitle(self.tr("Sign Up")) + # subtitle is set in the initializePage self.setPixmap( QtGui.QWizard.LogoPixmap, QtGui.QPixmap(APP_LOGO)) - self.current_page = "signup" - # commit page means there's no way back after this... # XXX should change the text on the "commit" button... self.setCommitPage(True) - self.initUI() + self.setupSteps() + self.setupUI() - def initUI(self): + def setupUI(self): userNameLabel = QtGui.QLabel("User &name:") userNameLineEdit = QtGui.QLineEdit() userNameLineEdit.cursorPositionChanged.connect( @@ -89,8 +94,18 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): layout.addWidget(self.userPasswordLineEdit, 2, 3) layout.addWidget(self.userPassword2LineEdit, 3, 3) layout.addWidget(rememberPasswordCheckBox, 4, 3, 4, 4) + + # add validation frame + self.setupValidationFrame() + layout.addWidget(self.valFrame, 5, 2, 5, 2) + self.valFrame.hide() + self.setLayout(layout) + # change "commit" button text + self.setButtonText( + QtGui.QWizard.CommitButton, "Sign up!") + # pagewizard methods def populateErrors(self): @@ -138,9 +153,6 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): super(RegisterUserPage, self).paintEvent(event) self.populateErrors() - def set_prevalidation_error(self, error): - self.prevalidation_error = error - def validatePage(self): """ we only pre-validate here password weakness @@ -150,33 +162,117 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): and if any errors are thrown there we come back and re-display the validation label. """ + # calls checks, which after successful + # execution will call on_checks_validation_ready + self.do_checks() + return self.is_done() + + def _do_checks(self): + """ + generator that yields actual checks + that are executed in a separate thread + """ + wizard = self.wizard() + curpage = self.current_page + senderr = lambda err: wizard.set_validation_error(curpage, err) - #username = self.userNameLineEdit.text() + provider = self.field('provider_domain') + username = self.userNameLineEdit.text() password = self.userPasswordLineEdit.text() password2 = self.userPassword2LineEdit.text() - # we better have here - # some call to a password checker... - # to assess strenght and avoid silly stuff. - - if password != password2: - self.set_prevalidation_error('Password does not match.') + def fail(): + self.set_undone() return False - if len(password) < 6: - self.set_prevalidation_error('Password too short.') - return False - - if password == "123456": - # joking, but not too much. - self.set_prevalidation_error('Password too obvious.') - return False - - # some cleanup before we leave the page - self.cleanup_errormsg() - - # go - return True + def checkpass(): + # we better have here + # some call to a password checker... + # to assess strenght and avoid silly stuff. + + if password != password2: + msg = self.tr('Password does not match..') + senderr(msg) + return fail() + + if len(password) < 6: + #self.set_prevalidation_error('Password too short.') + msg = self.tr('Password too short.') + senderr(msg) + return fail() + + if password == "123456": + # joking, but not too much. + #self.set_prevalidation_error('Password too obvious.') + msg = self.tr('Password too obvious.') + senderr(msg) + return fail() + + # go + return True + + yield(("head_sentinel", 0), checkpass) + + # XXX should emit signal for .show the frame! + # XXX HERE! + + ################################################## + # 1) register user + ################################################## + + def register(): + # XXX FIXME! + verify = False + + signup = auth.LeapSRPRegister( + schema="https", + provider=provider, + verify=verify) + try: + ok, req = signup.register_user( + username, password) + + except socket.timeout: + msg = self.tr("Error connecting to provider (timeout)") + senderr(msg) + return fail() + + except requests.exceptions.ConnectionError as exc: + logger.error(exc.message) + msg = self.tr('Error Connecting to provider (connerr).') + senderr(msg) + return fail() + + # XXX check for != OK instead??? + + if req.status_code in (404, 500): + msg = self.tr( + "Error during registration (%s)") % req.status_code + return fail() + + validation_msgs = json.loads(req.content) + errors = validation_msgs.get('errors', None) + logger.debug('validation errors: %s' % validation_msgs) + + if errors and errors.get('login', None): + # XXX this sometimes catch the blank username + # but we're not allowing that (soon) + msg = self.tr('Username not available.') + senderr(msg) + return fail() + + logger.debug('registering user') + yield(("registering with provider", 40), register) + + # set_done?? + self.set_done() + yield(("end_sentinel", 0), lambda: None) + + def on_checks_validation_ready(self): + + if self.is_done(): + self.cleanup_errormsg() + self.go_next() def initializePage(self): """ @@ -184,7 +280,7 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): """ provider = self.field('provider_domain') self.setSubTitle( - "Register a new user with provider %s." % + self.tr("Register a new user with provider %s.") % provider) self.validationMsg.setText('') self.userPassword2LineEdit.setText('') -- cgit v1.2.3 From d5136a5f3b2aa8b16e8341f2eb99d05993028acf Mon Sep 17 00:00:00 2001 From: kali Date: Tue, 27 Nov 2012 00:12:22 +0900 Subject: inline validation at register page. inline widget and focus and red marks and whistles. --- src/leap/gui/firstrun/register.py | 179 +++++++++++++++++++++++++++----------- 1 file changed, 129 insertions(+), 50 deletions(-) (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py index ddfcd1c5..7ce74892 100644 --- a/src/leap/gui/firstrun/register.py +++ b/src/leap/gui/firstrun/register.py @@ -1,6 +1,7 @@ """ Register User Page, used in First Run Wizard """ +import json import logging import socket @@ -14,6 +15,7 @@ from leap.gui.firstrun.mixins import UserFormMixIn logger = logging.getLogger(__name__) from leap.base import auth +from leap.gui import styles from leap.gui.constants import APP_LOGO, BARE_USERNAME_REGEX from leap.gui.progress import InlineValidationPage from leap.gui.styles import ErrorLabelStyleSheet @@ -39,6 +41,8 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): self.setupSteps() self.setupUI() + self.do_confirm_next = False + self.focused_field = False def setupUI(self): userNameLabel = QtGui.QLabel("User &name:") @@ -101,23 +105,64 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): self.valFrame.hide() self.setLayout(layout) + self.commitText("Sign up!") + # commit button + + def commitText(self, text): # change "commit" button text self.setButtonText( - QtGui.QWizard.CommitButton, "Sign up!") + QtGui.QWizard.CommitButton, text) - # pagewizard methods + @property + def commitButton(self): + return self.wizard().button(QtGui.QWizard.CommitButton) + + def commitFocus(self): + self.commitButton.setFocus() + + def disableCommitButton(self): + self.commitButton.setDisabled(True) + + def disableFields(self): + for field in (self.userNameLineEdit, + self.userPasswordLineEdit, + self.userPassword2LineEdit): + field.setDisabled(True) + + # error painting + + def markRedAndGetFocus(self, field): + field.setStyleSheet(styles.ErrorLineEdit) + if not self.focused_field: + self.focused_field = True + field.setFocus(QtCore.Qt.OtherFocusReason) + + def markRegular(self, field): + field.setStyleSheet(styles.RegularLineEdit) def populateErrors(self): - # XXX could move this to ValidationMixin - # used in providerselect too + def showerr(text): + self.validationMsg.setText(text) + err_lower = text.lower() + if "username" in err_lower: + self.markRedAndGetFocus( + self.userNameLineEdit) + if "password" in err_lower: + self.markRedAndGetFocus( + self.userPasswordLineEdit) + + def unmarkred(): + for field in (self.userNameLineEdit, + self.userPasswordLineEdit, + self.userPassword2LineEdit): + self.markRegular(field) errors = self.wizard().get_validation_error( self.current_page) if errors: bad_str = getattr(self, 'bad_string', None) cur_str = self.userNameLineEdit.text() - showerr = self.validationMsg.setText prev_er = getattr(self, 'prevalidation_error', None) if bad_str is None: @@ -133,7 +178,13 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): if cur_str == bad_str: showerr(errors) else: + self.focused_field = False showerr('') + unmarkred() + else: + # no errors + self.focused_field = False + unmarkred() def cleanup_errormsg(self): """ @@ -153,60 +204,32 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): super(RegisterUserPage, self).paintEvent(event) self.populateErrors() - def validatePage(self): - """ - we only pre-validate here password weakness - stuff, or any other client side validation - that we think of. - real server validation is made on next page, - and if any errors are thrown there we come back - and re-display the validation label. - """ - # calls checks, which after successful - # execution will call on_checks_validation_ready - self.do_checks() - return self.is_done() - def _do_checks(self): """ generator that yields actual checks that are executed in a separate thread """ - wizard = self.wizard() - curpage = self.current_page - senderr = lambda err: wizard.set_validation_error(curpage, err) - provider = self.field('provider_domain') username = self.userNameLineEdit.text() password = self.userPasswordLineEdit.text() password2 = self.userPassword2LineEdit.text() - def fail(): - self.set_undone() - return False - def checkpass(): # we better have here # some call to a password checker... # to assess strenght and avoid silly stuff. if password != password2: - msg = self.tr('Password does not match..') - senderr(msg) - return fail() + return self.fail(self.tr('Password does not match..')) if len(password) < 6: #self.set_prevalidation_error('Password too short.') - msg = self.tr('Password too short.') - senderr(msg) - return fail() + return self.fail(self.tr('Password too short.')) if password == "123456": # joking, but not too much. #self.set_prevalidation_error('Password too obvious.') - msg = self.tr('Password too obvious.') - senderr(msg) - return fail() + return self.fail(self.tr('Password too obvious.')) # go return True @@ -220,6 +243,10 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): # 1) register user ################################################## + # show the frame before going on... + QtCore.QMetaObject.invokeMethod( + self, "showStepsFrame") + def register(): # XXX FIXME! verify = False @@ -233,22 +260,22 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): username, password) except socket.timeout: - msg = self.tr("Error connecting to provider (timeout)") - senderr(msg) - return fail() + return self.fail( + self.tr("Error connecting to provider (timeout)")) except requests.exceptions.ConnectionError as exc: logger.error(exc.message) - msg = self.tr('Error Connecting to provider (connerr).') - senderr(msg) - return fail() + return self.fail( + self.tr('Error Connecting to provider (connerr).')) + except Exception as exc: + return self.fail(exc.message) # XXX check for != OK instead??? if req.status_code in (404, 500): - msg = self.tr( - "Error during registration (%s)") % req.status_code - return fail() + return self.fail( + self.tr( + "Error during registration (%s)") % req.status_code) validation_msgs = json.loads(req.content) errors = validation_msgs.get('errors', None) @@ -257,9 +284,8 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): if errors and errors.get('login', None): # XXX this sometimes catch the blank username # but we're not allowing that (soon) - msg = self.tr('Username not available.') - senderr(msg) - return fail() + return self.fail( + self.tr('Username not available.')) logger.debug('registering user') yield(("registering with provider", 40), register) @@ -269,10 +295,61 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): yield(("end_sentinel", 0), lambda: None) def on_checks_validation_ready(self): - + """ + after checks + """ if self.is_done(): + # XXX should disable + # all entry forms + self.disableFields() self.cleanup_errormsg() - self.go_next() + self.clean_wizard_errors(self.current_page) + # make the user confirm the transition + # to next page. + self.commitText('Connect!') + self.commitFocus() + self.green_validation_status() + self.do_confirm_next = True + + def green_validation_status(self): + val = self.validationMsg + val.setText(self.tr('Registration succeeded!')) + val.setStyleSheet(styles.GreenLineEdit) + + def reset_validation_status(self): + """ + empty the validation msg + and clean the inline validation widget. + """ + self.validationMsg.setText('') + self.steps.removeAllSteps() + self.clearTable() + + # pagewizard methods + + def validatePage(self): + """ + if not register done, do checks. + if done, wait for click. + """ + self.disableCommitButton() + self.cleanup_errormsg() + self.clean_wizard_errors(self.current_page) + + # After a successful validation + # (ie, success register with server) + # we change the commit button text + # and set this flag to True. + if self.do_confirm_next: + return True + + if not self.is_done(): + # calls checks, which after successful + # execution will call on_checks_validation_ready + self.reset_validation_status() + self.do_checks() + + return self.is_done() def initializePage(self): """ @@ -284,9 +361,11 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): provider) self.validationMsg.setText('') self.userPassword2LineEdit.setText('') + self.valFrame.hide() def nextId(self): wizard = self.wizard() if not wizard: return + # XXX this should be called connect return wizard.get_page_index('signupvalidation') -- cgit v1.2.3 From 1bb7e85425f2f427401cd02726c55922874a59a0 Mon Sep 17 00:00:00 2001 From: kali Date: Tue, 27 Nov 2012 03:34:08 +0900 Subject: login validation inline --- src/leap/gui/firstrun/register.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py index 7ce74892..e85723cb 100644 --- a/src/leap/gui/firstrun/register.py +++ b/src/leap/gui/firstrun/register.py @@ -163,7 +163,7 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): if errors: bad_str = getattr(self, 'bad_string', None) cur_str = self.userNameLineEdit.text() - prev_er = getattr(self, 'prevalidation_error', None) + #prev_er = getattr(self, 'prevalidation_error', None) if bad_str is None: # first time we fall here. @@ -171,9 +171,9 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): self.bad_string = cur_str showerr(errors) else: - if prev_er: - showerr(prev_er) - return + #if prev_er: + #showerr(prev_er) + #return # not the first time if cur_str == bad_str: showerr(errors) @@ -290,7 +290,6 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): logger.debug('registering user') yield(("registering with provider", 40), register) - # set_done?? self.set_done() yield(("end_sentinel", 0), lambda: None) @@ -299,8 +298,6 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): after checks """ if self.is_done(): - # XXX should disable - # all entry forms self.disableFields() self.cleanup_errormsg() self.clean_wizard_errors(self.current_page) -- cgit v1.2.3 From f40bfa7b674418f9903e826d20ad943efcc47807 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 7 Dec 2012 02:16:25 +0900 Subject: register tests --- src/leap/gui/firstrun/register.py | 82 +++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 30 deletions(-) (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py index e85723cb..7fd5c574 100644 --- a/src/leap/gui/firstrun/register.py +++ b/src/leap/gui/firstrun/register.py @@ -131,6 +131,16 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): field.setDisabled(True) # error painting + def paintEvent(self, event): + """ + we hook our populate errors + on paintEvent because we need it to catch + when user enters the page coming from next, + and initializePage does not cover that case. + Maybe there's a better event to hook upon. + """ + super(RegisterUserPage, self).paintEvent(event) + self.populateErrors() def markRedAndGetFocus(self, field): field.setStyleSheet(styles.ErrorLineEdit) @@ -193,16 +203,21 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): """ self.bad_string = None - def paintEvent(self, event): + def green_validation_status(self): + val = self.validationMsg + val.setText(self.tr('Registration succeeded!')) + val.setStyleSheet(styles.GreenLineEdit) + + def reset_validation_status(self): """ - we hook our populate errors - on paintEvent because we need it to catch - when user enters the page coming from next, - and initializePage does not cover that case. - Maybe there's a better event to hook upon. + empty the validation msg + and clean the inline validation widget. """ - super(RegisterUserPage, self).paintEvent(event) - self.populateErrors() + self.validationMsg.setText('') + self.steps.removeAllSteps() + self.clearTable() + + # actual checks def _do_checks(self): """ @@ -255,6 +270,7 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): schema="https", provider=provider, verify=verify) + #import ipdb;ipdb.set_trace() try: ok, req = signup.register_user( username, password) @@ -277,9 +293,15 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): self.tr( "Error during registration (%s)") % req.status_code) - validation_msgs = json.loads(req.content) - errors = validation_msgs.get('errors', None) - logger.debug('validation errors: %s' % validation_msgs) + try: + validation_msgs = json.loads(req.content) + errors = validation_msgs.get('errors', None) + logger.debug('validation errors: %s' % validation_msgs) + except ValueError: + # probably bad json returned + return self.fail( + self.tr( + "Could not register (bad response)")) if errors and errors.get('login', None): # XXX this sometimes catch the blank username @@ -287,11 +309,13 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): return self.fail( self.tr('Username not available.')) + return True + logger.debug('registering user') yield(("registering with provider", 40), register) self.set_done() - yield(("end_sentinel", 0), lambda: None) + yield(("end_sentinel", 100), lambda: None) def on_checks_validation_ready(self): """ @@ -308,20 +332,6 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): self.green_validation_status() self.do_confirm_next = True - def green_validation_status(self): - val = self.validationMsg - val.setText(self.tr('Registration succeeded!')) - val.setStyleSheet(styles.GreenLineEdit) - - def reset_validation_status(self): - """ - empty the validation msg - and clean the inline validation widget. - """ - self.validationMsg.setText('') - self.steps.removeAllSteps() - self.clearTable() - # pagewizard methods def validatePage(self): @@ -352,10 +362,22 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): """ inits wizard page """ - provider = self.field('provider_domain') - self.setSubTitle( - self.tr("Register a new user with provider %s.") % - provider) + provider = unicode(self.field('provider_domain')) + # hack. don't get why I'm getting a QVariant there, + # making segfault in tests. + provider = QtCore.QString(provider) + if provider: + # here we should have provider + # but in tests we might not. + + # XXX this error causes a segfault on free() + # that we might want to get fixed ... + #self.setSubTitle( + #self.tr("Register a new user with provider %s.") % + #provider) + self.setSubTitle( + self.tr("Register a new user with provider %s." % + provider)) self.validationMsg.setText('') self.userPassword2LineEdit.setText('') self.valFrame.hide() -- cgit v1.2.3 From 5a335cd560846fbcfa74f013c170a3bd32c7b85b Mon Sep 17 00:00:00 2001 From: kali Date: Mon, 10 Dec 2012 17:07:12 +0900 Subject: login tests --- src/leap/gui/firstrun/register.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py index 7fd5c574..4c811093 100644 --- a/src/leap/gui/firstrun/register.py +++ b/src/leap/gui/firstrun/register.py @@ -363,9 +363,6 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): inits wizard page """ provider = unicode(self.field('provider_domain')) - # hack. don't get why I'm getting a QVariant there, - # making segfault in tests. - provider = QtCore.QString(provider) if provider: # here we should have provider # but in tests we might not. @@ -384,7 +381,7 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): def nextId(self): wizard = self.wizard() - if not wizard: - return + #if not wizard: + #return # XXX this should be called connect return wizard.get_page_index('signupvalidation') -- cgit v1.2.3 From 8e6a15e2f2d35c606aa0c1a2102c28ceccc23b78 Mon Sep 17 00:00:00 2001 From: antialias Date: Mon, 7 Jan 2013 16:50:52 -0400 Subject: this should be the complete list of userfacing strings. see #665. --- src/leap/gui/firstrun/register.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py index 4c811093..b04638e0 100644 --- a/src/leap/gui/firstrun/register.py +++ b/src/leap/gui/firstrun/register.py @@ -45,7 +45,7 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): self.focused_field = False def setupUI(self): - userNameLabel = QtGui.QLabel("User &name:") + userNameLabel = QtGui.QLabel(self.tr("User &name:")) userNameLineEdit = QtGui.QLineEdit() userNameLineEdit.cursorPositionChanged.connect( self.reset_validation_status) @@ -57,20 +57,20 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): QtGui.QRegExpValidator(usernameRe, self)) self.userNameLineEdit = userNameLineEdit - userPasswordLabel = QtGui.QLabel("&Password:") + userPasswordLabel = QtGui.QLabel(self.tr("&Password:")) self.userPasswordLineEdit = QtGui.QLineEdit() self.userPasswordLineEdit.setEchoMode( QtGui.QLineEdit.Password) userPasswordLabel.setBuddy(self.userPasswordLineEdit) - userPassword2Label = QtGui.QLabel("Password (again):") + userPassword2Label = QtGui.QLabel(self.tr("Password (again):")) self.userPassword2LineEdit = QtGui.QLineEdit() self.userPassword2LineEdit.setEchoMode( QtGui.QLineEdit.Password) userPassword2Label.setBuddy(self.userPassword2LineEdit) rememberPasswordCheckBox = QtGui.QCheckBox( - "&Remember username and password.") + self.tr("&Remember username and password.")) rememberPasswordCheckBox.setChecked(True) self.registerField('userName*', self.userNameLineEdit) -- cgit v1.2.3 From 6d85c97ddcc8a151b157919e9a7322fba151a551 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 11 Jan 2013 03:00:41 +0900 Subject: all calls except the first one are made to api uri we also parse the port number --- src/leap/gui/firstrun/register.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py index b04638e0..741b9267 100644 --- a/src/leap/gui/firstrun/register.py +++ b/src/leap/gui/firstrun/register.py @@ -224,11 +224,17 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): generator that yields actual checks that are executed in a separate thread """ + wizard = self.wizard() + provider = self.field('provider_domain') username = self.userNameLineEdit.text() password = self.userPasswordLineEdit.text() password2 = self.userPassword2LineEdit.text() + pconfig = wizard.eipconfigchecker(domain=provider) + pconfig.defaultprovider.load() + pconfig.set_api_domain() + def checkpass(): # we better have here # some call to a password checker... @@ -263,14 +269,11 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): self, "showStepsFrame") def register(): - # XXX FIXME! - verify = False signup = auth.LeapSRPRegister( schema="https", - provider=provider, - verify=verify) - #import ipdb;ipdb.set_trace() + provider=pconfig.apidomain, + verify=pconfig.cacert) try: ok, req = signup.register_user( username, password) @@ -381,7 +384,4 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): def nextId(self): wizard = self.wizard() - #if not wizard: - #return - # XXX this should be called connect - return wizard.get_page_index('signupvalidation') + return wizard.get_page_index('connect') -- cgit v1.2.3 From ff59da55ef9a176b36cef19d67e7ec363bf5d739 Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 24 Jan 2013 02:30:00 +0900 Subject: wizard rephrasing & punctuation --- src/leap/gui/firstrun/register.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/gui/firstrun/register.py') diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py index 741b9267..15278330 100644 --- a/src/leap/gui/firstrun/register.py +++ b/src/leap/gui/firstrun/register.py @@ -315,7 +315,7 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): return True logger.debug('registering user') - yield(("registering with provider", 40), register) + yield(("Registering username", 40), register) self.set_done() yield(("end_sentinel", 100), lambda: None) @@ -376,7 +376,7 @@ class RegisterUserPage(InlineValidationPage, UserFormMixIn): #self.tr("Register a new user with provider %s.") % #provider) self.setSubTitle( - self.tr("Register a new user with provider %s." % + self.tr("Register a new user with provider %s" % provider)) self.validationMsg.setText('') self.userPassword2LineEdit.setText('') -- cgit v1.2.3