diff options
author | kali <kali@leap.se> | 2012-11-23 05:13:36 +0900 |
---|---|---|
committer | kali <kali@leap.se> | 2012-11-23 05:13:36 +0900 |
commit | 7a263b8ee74cc92ba39796cd9ad48395adfa7450 (patch) | |
tree | c3837025c602897729c23e298f93ce237776d9c1 /src/leap/gui/firstrun | |
parent | 60ae69dd79fc4a17e54e9f898b04c7130d8b9f6e (diff) |
refactor validation mixin; progress until register page
Diffstat (limited to 'src/leap/gui/firstrun')
-rw-r--r-- | src/leap/gui/firstrun/login.py | 67 | ||||
-rw-r--r-- | src/leap/gui/firstrun/providerselect.py | 8 | ||||
-rw-r--r-- | src/leap/gui/firstrun/providersetup.py | 158 | ||||
-rw-r--r-- | src/leap/gui/firstrun/register.py | 158 | ||||
-rw-r--r-- | src/leap/gui/firstrun/regvalidation.py | 79 | ||||
-rwxr-xr-x | src/leap/gui/firstrun/wizard.py | 1 |
6 files changed, 283 insertions, 188 deletions
diff --git a/src/leap/gui/firstrun/login.py b/src/leap/gui/firstrun/login.py index 004fa7d4..3a6ec089 100644 --- a/src/leap/gui/firstrun/login.py +++ b/src/leap/gui/firstrun/login.py @@ -6,14 +6,17 @@ from PyQt4 import QtGui #import requests +from leap.base import auth from leap.gui.firstrun.mixins import UserFormMixIn from leap.gui.constants import APP_LOGO, FULL_USERNAME_REGEX from leap.gui.styles import ErrorLabelStyleSheet -class LogInPage(QtGui.QWizardPage, UserFormMixIn): +class LogInPage(QtGui.QWizardPage, UserFormMixIn): # InlineValidationPage + def __init__(self, parent=None): + super(LogInPage, self).__init__(parent) self.setTitle("Log In") @@ -24,6 +27,9 @@ class LogInPage(QtGui.QWizardPage, UserFormMixIn): QtGui.QWizard.LogoPixmap, QtGui.QPixmap(APP_LOGO)) + self.setupUI() + + def setupUI(self): userNameLabel = QtGui.QLabel("User &name:") userNameLineEdit = QtGui.QLineEdit() userNameLineEdit.cursorPositionChanged.connect( @@ -149,6 +155,7 @@ class LogInPage(QtGui.QWizardPage, UserFormMixIn): #wizard = self.wizard() #eipconfigchecker = wizard.eipconfigchecker() + # XXX should move to _do_checks full_username = self.userNameLineEdit.text() password = self.userPasswordLineEdit.text() if full_username.count('@') != 1: @@ -191,3 +198,61 @@ class LogInPage(QtGui.QWizardPage, UserFormMixIn): self.cleanup_errormsg() return True + + def _do_checks(self): + # XXX convert this to inline + + full_username = self.userNameLineEdit.text() + password = self.userPasswordLineEdit.text() + username, domain = full_username.split('@') + # We try a call to an authenticated + # page here as a mean to catch + # srp authentication errors while + wizard = self.wizard() + pCertChecker = wizard.providercertchecker( + domain=domain) + + curpage = "login" + + def fail(): + self.is_done = False + return False + + ######################## + # 1) try name resolution + ######################## + # XXX + # bring here from validation above... + + ######################## + # 2) do authentication + ######################## + + unamek = 'login_userName' + passwk = 'login_userPassword' + + username = self.field(unamek) + password = self.field(passwk) + credentials = username, password + + def validate_credentials(): + ################# + # FIXME #BUG #638 + verify = False + + try: + pCertChecker.download_new_client_cert( + credentials=credentials, + verify=verify) + + except auth.SRPAuthenticationError as exc: + wizard.set_validation_error( + curpage, "Authentication error: %s" % exc.usermessage) + return fail() + + except Exception as exc: + wizard.set_validation_error( + curpage, "%s" % exc.message) + return fail() + + yield(('Validating credentials', 20), lambda: None) diff --git a/src/leap/gui/firstrun/providerselect.py b/src/leap/gui/firstrun/providerselect.py index d029b1db..dffde040 100644 --- a/src/leap/gui/firstrun/providerselect.py +++ b/src/leap/gui/firstrun/providerselect.py @@ -1,7 +1,6 @@ """ Select Provider Page, used in First Run Wizard """ -from functools import partial import logging import requests @@ -20,10 +19,9 @@ from leap.util.web import get_https_domain_and_port logger = logging.getLogger(__name__) -# XXX check newer version in progress... - def delay(obj, method_str): + # XXX check newer version in progress.py... """ this is a hack to get responsiveness in the ui """ @@ -40,6 +38,7 @@ class SelectProviderPage(InlineValidationPage): def __init__(self, parent=None, providers=None): super(SelectProviderPage, self).__init__(parent) + self.current_page = 'providerselection' self.setTitle(self.tr("Enter Provider")) self.setSubTitle(self.tr( @@ -51,7 +50,6 @@ class SelectProviderPage(InlineValidationPage): QtGui.QPixmap(APP_LOGO)) self.did_cert_check = False - self.current_page = 'providerselection' self.is_done = False @@ -346,7 +344,7 @@ class SelectProviderPage(InlineValidationPage): self.is_done = True yield(("end_sentinel", 100), lambda: None) - def _inline_validation_ready(self): + def on_checks_validation_ready(self): """ called after _do_checks has finished. """ diff --git a/src/leap/gui/firstrun/providersetup.py b/src/leap/gui/firstrun/providersetup.py index 042d117c..7904538d 100644 --- a/src/leap/gui/firstrun/providersetup.py +++ b/src/leap/gui/firstrun/providersetup.py @@ -6,10 +6,10 @@ import logging from PyQt4 import QtGui -from leap.base import auth +from leap.base import exceptions as baseexceptions from leap.gui.progress import ValidationPage -from leap.gui.constants import APP_LOGO, pause_for_user +from leap.gui.constants import APP_LOGO logger = logging.getLogger(__name__) @@ -20,18 +20,21 @@ class ProviderSetupValidationPage(ValidationPage): is_signup = self.field("is_signup") self.is_signup = is_signup - self.setTitle("Provider setup") + self.setTitle(self.tr("Provider setup")) self.setSubTitle( - "Doing autoconfig.") + self.tr("Doing autoconfig.")) self.setPixmap( QtGui.QWizard.LogoPixmap, QtGui.QPixmap(APP_LOGO)) - def _do_checks(self, update_signal=None): + def _do_checks(self): """ - executes actual checks in a separate thread + generator that yields actual checks + that are executed in a separate thread """ + curpage = "providersetupvalidation" + full_domain = self.field('provider_domain') wizard = self.wizard() pconfig = wizard.providerconfig @@ -41,68 +44,56 @@ class ProviderSetupValidationPage(ValidationPage): pCertChecker = wizard.providercertchecker( domain=full_domain) - update_signal.emit('head_sentinel', 0) - - ###################################### - if not self.is_signup: - # We come from login page. - # We try a call to an authenticated - # page here as a mean to catch - # srp authentication errors while - # we are still at one page's reach - # of the login credentials input page. - # (so we're able to go back an correct) + def fail(): + self.is_done = False + return False - step = "fetch_eipcert" - update_signal.emit('Validating credentials', 20) + yield(("head_sentinel", 0), lambda: None) - unamek = 'login_userName' - passwk = 'login_userPassword' + ######################## + # 1) fetch ca cert + ######################## - username = self.field(unamek) - password = self.field(passwk) - credentials = username, password - - ################# - # FIXME #BUG #638 - verify = False + def fetchcacert(): + if pconfig: + ca_cert_uri = pconfig.get('ca_cert_uri').geturl() + else: + ca_cert_uri = None + # XXX check scheme == "https" + # XXX passing verify == False because + # we have trusted right before. + # We should check it's the same domain!!! + # (Check with the trusted fingerprints dict + # or something smart) try: - pCertChecker.download_new_client_cert( - credentials=credentials, - verify=verify) + pCertChecker.download_ca_cert( + uri=ca_cert_uri, + verify=False) - except auth.SRPAuthenticationError as exc: - self.set_error( - step, - "Authentication error: %s" % exc.message) - return False + except baseexceptions.LeapException as exc: + logger.error(exc.message) + wizard.set_validation_error( + curpage, exc.usermessage) + return fail() - #pause_for_user() + except Exception as exc: + wizard.set_validation_error( + curpage, exc.message) + return fail() - ####################################### + else: + return True - update_signal.emit('Fetching CA certificate', 30) - #pause_for_user() + yield(('Fetching CA certificate', 30), fetchcacert) - if pconfig: - ca_cert_uri = pconfig.get('ca_cert_uri').geturl() - else: - ca_cert_uri = None + ######################### + # 2) check CA fingerprint + ######################### - # XXX check scheme == "https" - # XXX passing verify == False because - # we have trusted right before. - # We should check it's the same domain!!! - # (Check with the trusted fingerprints dict - # or something smart) - - pCertChecker.download_ca_cert( - uri=ca_cert_uri, - verify=False) - #pause_for_user() - - update_signal.emit('Checking CA fingerprint', 66) + def checkcafingerprint(): + # XXX get the real thing!!! + pass #ca_cert_fingerprint = pconfig.get('ca_cert_fingerprint', None) # XXX get fingerprint dict (types) @@ -115,33 +106,40 @@ class ProviderSetupValidationPage(ValidationPage): # should catch exception #return False - update_signal.emit('Validating api certificate', 90) - - #api_uri = pconfig.get('api_uri', None) - #try: - #api_cert_verified = pCertChecker.verify_api_https(api_uri) - #except requests.exceptions.SSLError as exc: - #logger.error('BUG #638. %s' % exc.message) - # XXX RAISE! See #638 - # bypassing until the hostname is fixed. - # We probably should raise yet-another-warning - # here saying user that the hostname "XX.XX.XX.XX' does not - # match 'foo.bar.baz' - #api_cert_verified = True - - #if not api_cert_verified: - # XXX update validationMsg - # should catch exception - #return False + yield((self.tr("Checking CA fingerprint"), 60), checkcafingerprint) + + ######################### + # 2) check CA fingerprint + ######################### + + def validatecacert(): + pass + #api_uri = pconfig.get('api_uri', None) + #try: + #api_cert_verified = pCertChecker.verify_api_https(api_uri) + #except requests.exceptions.SSLError as exc: + #logger.error('BUG #638. %s' % exc.message) + # XXX RAISE! See #638 + # bypassing until the hostname is fixed. + # We probably should raise yet-another-warning + # here saying user that the hostname "XX.XX.XX.XX' does not + # match 'foo.bar.baz' + #api_cert_verified = True + + #if not api_cert_verified: + # XXX update validationMsg + # should catch exception + #return False + + #??? + #ca_cert_path = checker.ca_cert_path - #pause_for_user() - #ca_cert_path = checker.ca_cert_path + yield((self.tr('Validating api certificate'), 90), validatecacert) self.set_done() - update_signal.emit('end_sentinel', 100) - #pause_for_user() + yield(('end_sentinel', 100), lambda: None) - def _do_validation(self): + def on_checks_validation_ready(self): """ called after _do_checks has finished (connected to checker thread finished signal) 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('') diff --git a/src/leap/gui/firstrun/regvalidation.py b/src/leap/gui/firstrun/regvalidation.py index 6db2bf6e..79971944 100644 --- a/src/leap/gui/firstrun/regvalidation.py +++ b/src/leap/gui/firstrun/regvalidation.py @@ -20,7 +20,7 @@ from leap.gui.progress import ValidationPage from leap.util.web import get_https_domain_and_port from leap.base import auth -from leap.gui.constants import APP_LOGO, pause_for_user +from leap.gui.constants import APP_LOGO logger = logging.getLogger(__name__) @@ -77,79 +77,9 @@ class RegisterUserValidationPage(ValidationPage): pCertChecker = wizard.providercertchecker( domain=full_domain) - ########################################### - # only if from signup - # MOVE TO SIGNUP PAGE... - if is_signup: - signup = auth.LeapSRPRegister( - schema="https", - provider=full_domain, - verify=verify) - update_signal.emit("head_sentinel", 0) ################################################## - # 1) register user - ################################################## - # only if from signup. - # XXX MOVE THIS STEP TO SIGNUP-IN-PLACE VALIDATION - # WIDGET.......................................... - - if is_signup: - - step = "register" - update_signal.emit("checking availability", 20) - update_signal.emit("registering with provider", 40) - logger.debug('registering user') - - try: - ok, req = signup.register_user( - username, password) - - except socket.timeout: - self.set_error( - step, - "Error connecting to provider (timeout)") - #pause_for_user() - return False - - except requests.exceptions.ConnectionError as exc: - logger.error(exc.message) - self.set_error( - step, - "Error connecting to provider " - "(connection error)") - # XXX we should signal a BAD step - #pause_for_user() - update_signal.emit("connection error!", 50) - #pause_for_user() - return False - - # XXX check for != OK instead??? - - if req.status_code in (404, 500): - self.set_error( - step, - "Error during registration (%s)" % req.status_code) - pause_for_user() - return False - - 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) - self.set_error( - step, - 'Username not available.') - #pause_for_user() - return False - - #pause_for_user() - - ################################################## # 2) fetching eip service config ################################################## @@ -202,6 +132,13 @@ class RegisterUserValidationPage(ValidationPage): # this should be called CONNECT PAGE AGAIN. self.run_eip_checks_for_provider_and_connect(_domain) + def on_checks_validation_ready(self): + """ + called after _do_checks has finished + (connected to checker thread finished signal) + """ + pass + def run_eip_checks_for_provider_and_connect(self, domain): wizard = self.wizard() conductor = wizard.conductor diff --git a/src/leap/gui/firstrun/wizard.py b/src/leap/gui/firstrun/wizard.py index 4a72177e..2ee1947a 100755 --- a/src/leap/gui/firstrun/wizard.py +++ b/src/leap/gui/firstrun/wizard.py @@ -139,6 +139,7 @@ class FirstRunWizard(QtGui.QWizard): # set options self.setOption(QtGui.QWizard.IndependentPages, on=False) + self.setOption(QtGui.QWizard.NoBackButtonOnStartPage, on=True) self.setWindowTitle("First Run Wizard") |