summaryrefslogtreecommitdiff
path: root/src/leap/gui/firstrun
diff options
context:
space:
mode:
authorkali <kali@leap.se>2012-11-28 01:11:05 +0900
committerkali <kali@leap.se>2012-11-28 01:11:05 +0900
commit16f19a225a922dd77f3f6c75c94194ebd229fc67 (patch)
treed77ba10cdad970b5025e75daa2b3be24e35ce0c7 /src/leap/gui/firstrun
parent862014f68fce37318f77309a8f8f9782dabc60d2 (diff)
parent3ea766452e3c4708c724509d03001c0a0314fcf6 (diff)
Merge branch 'feature/wizard-usability' into develop
Diffstat (limited to 'src/leap/gui/firstrun')
-rw-r--r--src/leap/gui/firstrun/last.py2
-rw-r--r--src/leap/gui/firstrun/login.py244
-rw-r--r--src/leap/gui/firstrun/providerinfo.py178
-rw-r--r--src/leap/gui/firstrun/providerselect.py334
-rw-r--r--src/leap/gui/firstrun/providersetup.py177
-rw-r--r--src/leap/gui/firstrun/register.py260
-rw-r--r--src/leap/gui/firstrun/regvalidation.py179
-rwxr-xr-xsrc/leap/gui/firstrun/wizard.py11
8 files changed, 899 insertions, 486 deletions
diff --git a/src/leap/gui/firstrun/last.py b/src/leap/gui/firstrun/last.py
index 13b2f548..d33d2e77 100644
--- a/src/leap/gui/firstrun/last.py
+++ b/src/leap/gui/firstrun/last.py
@@ -78,6 +78,8 @@ class LastPage(QtGui.QWizardPage):
break
except GeneratorExit:
pass
+ except StopIteration:
+ pass
def initializePage(self):
wizard = self.wizard()
diff --git a/src/leap/gui/firstrun/login.py b/src/leap/gui/firstrun/login.py
index 4271c774..02bace86 100644
--- a/src/leap/gui/firstrun/login.py
+++ b/src/leap/gui/firstrun/login.py
@@ -4,17 +4,22 @@ LogIn Page, used inf First Run Wizard
from PyQt4 import QtCore
from PyQt4 import QtGui
-#import requests
+import requests
+from leap.base import auth
from leap.gui.firstrun.mixins import UserFormMixIn
+from leap.gui.progress import InlineValidationPage
+from leap.gui import styles
from leap.gui.constants import APP_LOGO, FULL_USERNAME_REGEX
-from leap.gui.styles import ErrorLabelStyleSheet
-class LogInPage(QtGui.QWizardPage, UserFormMixIn):
+class LogInPage(InlineValidationPage, UserFormMixIn): # InlineValidationPage
+
def __init__(self, parent=None):
+
super(LogInPage, self).__init__(parent)
+ self.current_page = "login"
self.setTitle("Log In")
self.setSubTitle("Log in with your credentials.")
@@ -24,6 +29,12 @@ class LogInPage(QtGui.QWizardPage, UserFormMixIn):
QtGui.QWizard.LogoPixmap,
QtGui.QPixmap(APP_LOGO))
+ self.setupSteps()
+ self.setupUI()
+
+ self.do_confirm_next = False
+
+ def setupUI(self):
userNameLabel = QtGui.QLabel("User &name:")
userNameLineEdit = QtGui.QLineEdit()
userNameLineEdit.cursorPositionChanged.connect(
@@ -34,6 +45,9 @@ class LogInPage(QtGui.QWizardPage, UserFormMixIn):
usernameRe = QtCore.QRegExp(FULL_USERNAME_REGEX)
userNameLineEdit.setValidator(
QtGui.QRegExpValidator(usernameRe, self))
+
+ #userNameLineEdit.setPlaceholderText(
+ #'username@provider.example.org')
self.userNameLineEdit = userNameLineEdit
userPasswordLabel = QtGui.QLabel("&Password:")
@@ -49,7 +63,7 @@ class LogInPage(QtGui.QWizardPage, UserFormMixIn):
layout.setColumnMinimumWidth(0, 20)
validationMsg = QtGui.QLabel("")
- validationMsg.setStyleSheet(ErrorLabelStyleSheet)
+ validationMsg.setStyleSheet(styles.ErrorLabelStyleSheet)
self.validationMsg = validationMsg
layout.addWidget(validationMsg, 0, 3)
@@ -58,18 +72,38 @@ class LogInPage(QtGui.QWizardPage, UserFormMixIn):
layout.addWidget(userPasswordLabel, 2, 0)
layout.addWidget(self.userPasswordLineEdit, 2, 3)
+ # add validation frame
+ self.setupValidationFrame()
+ layout.addWidget(self.valFrame, 4, 2, 4, 2)
+ self.valFrame.hide()
+
+ self.nextText("Log in")
self.setLayout(layout)
#self.registerField('is_login_wizard')
+ def nextText(self, text):
+ self.setButtonText(
+ QtGui.QWizard.NextButton, text)
+
+ def nextFocus(self):
+ self.wizard().button(
+ QtGui.QWizard.NextButton).setFocus()
+
+ def disableNextButton(self):
+ self.wizard().button(
+ QtGui.QWizard.NextButton).setDisabled(True)
+
def onUserNameEdit(self, *args):
if self.initial_username_sample:
self.userNameLineEdit.setText('')
+ # XXX set regular color
self.initial_username_sample = None
- # pagewizard methods
-
- #### begin possible refactor
+ def disableFields(self):
+ for field in (self.userNameLineEdit,
+ self.userPasswordLineEdit):
+ field.setDisabled(True)
def populateErrors(self):
# XXX could move this to ValidationMixin
@@ -77,13 +111,13 @@ class LogInPage(QtGui.QWizardPage, UserFormMixIn):
errors = self.wizard().get_validation_error(
self.current_page)
- prev_er = getattr(self, 'prevalidation_error', None)
+ #prev_er = getattr(self, 'prevalidation_error', None)
showerr = self.validationMsg.setText
- if not errors and prev_er:
- showerr(prev_er)
- return
-
+ #if not errors and prev_er:
+ #showerr(prev_er)
+ #return
+#
if errors:
bad_str = getattr(self, 'bad_string', None)
cur_str = self.userNameLineEdit.text()
@@ -94,13 +128,14 @@ class LogInPage(QtGui.QWizardPage, 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)
else:
+ self.focused_field = False
showerr('')
def cleanup_errormsg(self):
@@ -124,7 +159,7 @@ class LogInPage(QtGui.QWizardPage, UserFormMixIn):
def set_prevalidation_error(self, error):
self.prevalidation_error = error
- #### end possible refactor
+ # pagewizard methods
def nextId(self):
wizard = self.wizard()
@@ -139,54 +174,157 @@ class LogInPage(QtGui.QWizardPage, UserFormMixIn):
def initializePage(self):
super(LogInPage, self).initializePage()
- self.userNameLineEdit.setText('username@provider.example.org')
- self.userNameLineEdit.cursorPositionChanged.connect(
+ username = self.userNameLineEdit
+ username.setText('username@provider.example.org')
+ username.cursorPositionChanged.connect(
self.onUserNameEdit)
self.initial_username_sample = True
+ self.validationMsg.setText('')
+ self.valFrame.hide()
+
+ def reset_validation_status(self):
+ """
+ empty the validation msg
+ and clean the inline validation widget.
+ """
+ self.validationMsg.setText('')
+ self.steps.removeAllSteps()
+ self.clearTable()
def validatePage(self):
- #wizard = self.wizard()
- #eipconfigchecker = wizard.eipconfigchecker()
+ """
+ if not register done, do checks.
+ if done, wait for click.
+ """
+ self.disableNextButton()
+ self.cleanup_errormsg()
+ self.clean_wizard_errors(self.current_page)
+
+ if self.do_confirm_next:
+ full_username = self.userNameLineEdit.text()
+ password = self.userPasswordLineEdit.text()
+ username, domain = full_username.split('@')
+ self.setField('provider_domain', domain)
+ self.setField('login_userName', username)
+ self.setField('login_userPassword', password)
+
+ return True
+
+ if not self.is_done():
+ self.reset_validation_status()
+ self.do_checks()
+
+ return self.is_done()
+
+ def _do_checks(self):
+ # XXX convert this to inline
full_username = self.userNameLineEdit.text()
- password = self.userPasswordLineEdit.text()
- if full_username.count('@') != 1:
- self.set_prevalidation_error(
- "Username must be in the username@provider form.")
- return False
+ ###########################
+ # 0) check user@domain form
+ ###########################
+
+ def checkusername():
+ if full_username.count('@') != 1:
+ return self.fail(
+ self.tr(
+ "Username must be in the username@provider form."))
+ else:
+ return True
+
+ yield(("head_sentinel", 0), checkusername)
+
+ # XXX I think this is not needed
+ # since we're also checking for the is_signup field.
+ #self.wizard().from_login = True
username, domain = full_username.split('@')
- self.setField('provider_domain', domain)
- self.setField('login_userName', username)
- self.setField('login_userPassword', password)
-
- ####################################################
- # Validation logic:
- # move to provider setup page
- ####################################################
+ password = self.userPasswordLineEdit.text()
+
+ # We try a call to an authenticated
+ # page here as a mean to catch
+ # srp authentication errors while
+ wizard = self.wizard()
+ eipconfigchecker = wizard.eipconfigchecker()
+
+ ########################
+ # 1) try name resolution
+ ########################
+ # show the frame before going on...
+ QtCore.QMetaObject.invokeMethod(
+ self, "showStepsFrame")
+
# Able to contact domain?
# can get definition?
# two-by-one
- #try:
- #eipconfigchecker.fetch_definition(domain=domain)
-#
- # we're using requests here for all
- # the possible error cases that it catches.
- #except requests.exceptions.ConnectionError as exc:
- #self.set_validation_status(exc.message[1])
- #return False
- #except requests.exceptions.HTTPError as exc:
- #self.set_validation_status(exc.message)
- #return False
- #wizard.set_providerconfig(
- #eipconfigchecker.defaultprovider.config)
- ####################################################
+ def resolvedomain():
+ try:
+ eipconfigchecker.fetch_definition(domain=domain)
+
+ # we're using requests here for all
+ # the possible error cases that it catches.
+ except requests.exceptions.ConnectionError as exc:
+ return self.fail(exc.message[1])
+ except requests.exceptions.HTTPError as exc:
+ return self.fail(exc.message)
+ except Exception as exc:
+ # XXX get catchall error msg
+ return self.fail(
+ exc.message)
+
+ yield((self.tr("resolving domain name"), 20), resolvedomain)
+
+ wizard.set_providerconfig(
+ eipconfigchecker.defaultprovider.config)
+
+ ########################
+ # 2) do authentication
+ ########################
+ credentials = username, password
+ pCertChecker = wizard.providercertchecker(
+ domain=domain)
+
+ def validate_credentials():
+ #################
+ # FIXME #BUG #638
+ verify = False
+
+ try:
+ pCertChecker.download_new_client_cert(
+ credentials=credentials,
+ verify=verify)
+
+ except auth.SRPAuthenticationError as exc:
+ return self.fail(
+ self.tr("Authentication error: %s" % exc.message))
+
+ except Exception as exc:
+ return self.fail(exc.message)
- # XXX I think this is not needed
- # since we're also checking for the is_signup field.
- self.wizard().from_login = True
+ else:
+ return True
- # some cleanup before we leave the page
- self.cleanup_errormsg()
+ yield(('Validating credentials', 20), validate_credentials)
+
+ self.set_done()
+ yield(("end_sentinel", 0), lambda: None)
+
+ def green_validation_status(self):
+ val = self.validationMsg
+ val.setText(self.tr('Credentials validated.'))
+ val.setStyleSheet(styles.GreenLineEdit)
- return True
+ def on_checks_validation_ready(self):
+ """
+ after checks
+ """
+ if self.is_done():
+ self.disableFields()
+ self.cleanup_errormsg()
+ self.clean_wizard_errors(self.current_page)
+ # make the user confirm the transition
+ # to next page.
+ self.nextText('&Next')
+ self.nextFocus()
+ self.green_validation_status()
+ self.do_confirm_next = True
diff --git a/src/leap/gui/firstrun/providerinfo.py b/src/leap/gui/firstrun/providerinfo.py
index e642fcd0..c5b2984c 100644
--- a/src/leap/gui/firstrun/providerinfo.py
+++ b/src/leap/gui/firstrun/providerinfo.py
@@ -3,42 +3,33 @@ Provider Info Page, used in First run Wizard
"""
import logging
-from PyQt4 import QtCore
from PyQt4 import QtGui
-import requests
-
-from leap.base import exceptions as baseexceptions
-#from leap.crypto import certs
-from leap.eip import exceptions as eipexceptions
-
-from leap.gui.progress import ValidationPage
-from leap.util.web import get_https_domain_and_port
-
-from leap.gui.constants import APP_LOGO, pause_for_user
+from leap.gui.constants import APP_LOGO
logger = logging.getLogger(__name__)
-class ProviderInfoPage(ValidationPage):
+class ProviderInfoPage(QtGui.QWizardPage):
+
def __init__(self, parent=None):
super(ProviderInfoPage, self).__init__(parent)
- self.setTitle("Provider Info")
- #self.setSubTitle("Available information about chosen provider.")
+ self.setTitle(self.tr("Provider Info"))
+ self.setSubTitle(self.tr(
+ "This is what provider says."))
self.setPixmap(
QtGui.QWizard.LogoPixmap,
QtGui.QPixmap(APP_LOGO))
- self.prev_page = "providerselection"
- #self.current_page = "providerinfo"
+ self.create_info_panel()
def create_info_panel(self):
# Use stacked widget instead
# of reparenting the layout.
- self.infoWidget = QtGui.QStackedWidget()
+ infoWidget = QtGui.QStackedWidget()
info = QtGui.QWidget()
layout = QtGui.QVBoxLayout()
@@ -46,22 +37,29 @@ class ProviderInfoPage(ValidationPage):
displayName = QtGui.QLabel("")
description = QtGui.QLabel("")
enrollment_policy = QtGui.QLabel("")
+
# XXX set stylesheet...
# prettify a little bit.
# bigger fonts and so on...
+ # We could use a QFrame here
+
layout.addWidget(displayName)
layout.addWidget(description)
layout.addWidget(enrollment_policy)
layout.addStretch(1)
info.setLayout(layout)
- self.infoWidget.addWidget(info)
+ infoWidget.addWidget(info)
- self.layout.addWidget(self.infoWidget)
+ pageLayout = QtGui.QVBoxLayout()
+ pageLayout.addWidget(infoWidget)
+ self.setLayout(pageLayout)
# add refs to self to allow for
# updates.
+ # Watch out! Have to get rid of these references!
+ # this should be better handled with signals !!
self.displayName = displayName
self.description = description
self.enrollment_policy = enrollment_policy
@@ -76,8 +74,10 @@ class ProviderInfoPage(ValidationPage):
dn = pconfig.get('display_name')
display_name = dn[lang] if dn else ''
+ domain_name = self.field('provider_domain')
+
self.displayName.setText(
- "<b>%s</b>" % display_name)
+ "<b>%s</b> https://%s" % (display_name, domain_name))
desc = pconfig.get('description')
description_text = desc[lang] if desc else ''
@@ -89,142 +89,10 @@ class ProviderInfoPage(ValidationPage):
self.enrollment_policy.setText(
'enrollment policy: %s' % enroll)
- def _do_checks(self, update_signal=None):
- """
- executes actual checks in a separate thread
- """
- def pause_and_finish():
- update_signal.emit("end_sentinel", 100)
- pause_for_user()
-
- wizard = self.wizard()
- prevpage = "providerselection"
-
- full_domain = self.field('provider_domain')
-
- # we check if we have a port in the domain string.
- domain, port = get_https_domain_and_port(full_domain)
- _domain = u"%s:%s" % (domain, port) if port != 443 else unicode(domain)
-
- netchecker = wizard.netchecker()
- providercertchecker = wizard.providercertchecker()
- eipconfigchecker = wizard.eipconfigchecker(domain=_domain)
-
- update_signal.emit("head_sentinel", 0)
- pause_for_user()
-
- ########################
- # 1) try name resolution
- ########################
- update_signal.emit("Checking that server is reachable", 20)
- logger.debug('checking name resolution')
- try:
- netchecker.check_name_resolution(
- domain)
-
- except baseexceptions.LeapException as exc:
- logger.error(exc.message)
- wizard.set_validation_error(
- prevpage, exc.usermessage)
- pause_and_finish()
- return False
-
- #########################
- # 2) try https connection
- #########################
- update_signal.emit("Checking secure connection to provider", 40)
- logger.debug('checking https connection')
- try:
- providercertchecker.is_https_working(
- "https://%s" % _domain,
- verify=True)
-
- except eipexceptions.HttpsBadCertError as exc:
- logger.debug('exception')
- # XXX skipping for now...
- ##############################################
- # We had this validation logic
- # in the provider selection page before
- ##############################################
- #if self.trustProviderCertCheckBox.isChecked():
- #pass
- #else:
- wizard.set_validation_error(
- prevpage, exc.usermessage)
- #fingerprint = certs.get_cert_fingerprint(
- #domain=domain, sep=" ")
-
- # it's ok if we've trusted this fgprt before
- #trustedcrts = wizard.trusted_certs
- #if trustedcrts and fingerprint.replace(' ', '') in trustedcrts:
- #pass
- #else:
- # let your user face panick :P
- #self.add_cert_info(fingerprint)
- #self.did_cert_check = True
- #self.completeChanged.emit()
- #return False
- pause_and_finish()
- return False
-
- except baseexceptions.LeapException as exc:
- wizard.set_validation_error(
- prevpage, exc.usermessage)
- pause_and_finish()
- return False
-
- ##################################
- # 3) try download provider info...
- ##################################
-
- update_signal.emit("Downloading provider info", 70)
- try:
- # XXX we already set _domain in the initialization
- # so it should not be needed here.
- eipconfigchecker.fetch_definition(domain=_domain)
- wizard.set_providerconfig(
- eipconfigchecker.defaultprovider.config)
- except requests.exceptions.SSLError:
- # XXX we should have catched this before.
- # but cert checking is broken.
- wizard.set_validation_error(
- prevpage,
- "Could not get info from provider.")
- pause_and_finish()
- return False
- except requests.exceptions.ConnectionError:
- wizard.set_validation_error(
- prevpage,
- "Could not download provider info "
- "(refused conn.).")
- pause_and_finish()
- return False
- # XXX catch more errors...
-
- # We're done!
- pause_and_finish()
-
- def _do_validation(self):
- """
- called after _do_checks has finished
- (connected to checker thread finished signal)
- """
- print 'validation...'
- prevpage = "providerselection"
- errors = self.wizard().get_validation_error(prevpage)
-
- if not errors:
- self.progress.hide()
- self.stepsTableWidget.hide()
- self.create_info_panel()
- self.show_provider_info()
-
- else:
- logger.debug('going back with errors')
- logger.debug('ERRORS: %s' % errors)
- self.go_back()
-
def nextId(self):
wizard = self.wizard()
next_ = "providersetupvalidation"
return wizard.get_page_index(next_)
+
+ def initializePage(self):
+ self.show_provider_info()
diff --git a/src/leap/gui/firstrun/providerselect.py b/src/leap/gui/firstrun/providerselect.py
index 8d1aa869..3ffc6ff6 100644
--- a/src/leap/gui/firstrun/providerselect.py
+++ b/src/leap/gui/firstrun/providerselect.py
@@ -3,35 +3,69 @@ Select Provider Page, used in First Run Wizard
"""
import logging
+import requests
+
from PyQt4 import QtCore
from PyQt4 import QtGui
-#from leap.base import exceptions as baseexceptions
+from leap.base import exceptions as baseexceptions
#from leap.crypto import certs
-#from leap.eip import exceptions as eipexceptions
+from leap.eip import exceptions as eipexceptions
+from leap.gui.progress import InlineValidationPage
+from leap.gui import styles
+from leap.util.web import get_https_domain_and_port
from leap.gui.constants import APP_LOGO
-from leap.gui.styles import ErrorLabelStyleSheet
logger = logging.getLogger(__name__)
-class SelectProviderPage(QtGui.QWizardPage):
+def delay(obj, method_str):
+ # XXX check newer version in progress.py...
+ """
+ this is a hack to get responsiveness in the ui
+ """
+ QtCore.QTimer().singleShot(
+ 10,
+ lambda: QtCore.QMetaObject.invokeMethod(
+ obj, method_str))
+
+
+class SelectProviderPage(InlineValidationPage):
+
+ #disableCheckButton = QtCore.pyqtSignal()
+ launchChecks = QtCore.pyqtSignal()
+
def __init__(self, parent=None, providers=None):
super(SelectProviderPage, self).__init__(parent)
+ self.current_page = 'providerselection'
- self.setTitle("Enter Provider")
- self.setSubTitle(
+ self.setTitle(self.tr("Enter Provider"))
+ self.setSubTitle(self.tr(
"Please enter the domain of the provider you want "
- "to use for your connection."
+ "to use for your connection.")
)
self.setPixmap(
QtGui.QWizard.LogoPixmap,
QtGui.QPixmap(APP_LOGO))
self.did_cert_check = False
- self.current_page = 'providerselection'
+ self.is_done = False
+
+ self.setupSteps()
+ self.setupUI()
+
+ self.launchChecks.connect(
+ self.launch_checks)
+
+ self.providerNameEdit.editingFinished.connect(
+ lambda: self.providerCheckButton.setFocus(True))
+
+ def setupUI(self):
+ """
+ initializes the UI
+ """
providerNameLabel = QtGui.QLabel("h&ttps://")
# note that we expect the bare domain name
# we will add the scheme later
@@ -59,8 +93,10 @@ class SelectProviderPage(QtGui.QWizardPage):
#self.registerField('provider_name_index', providerNameSelect)
validationMsg = QtGui.QLabel("")
- validationMsg.setStyleSheet(ErrorLabelStyleSheet)
+ validationMsg.setStyleSheet(styles.ErrorLabelStyleSheet)
self.validationMsg = validationMsg
+ providerCheckButton = QtGui.QPushButton(self.tr("chec&k!"))
+ self.providerCheckButton = providerCheckButton
# cert info
@@ -69,7 +105,8 @@ class SelectProviderPage(QtGui.QWizardPage):
# tricky, since the first time came
# from the exception message.
# should get string from exception too!
- self.bad_cert_status = "Server certificate could not be verified."
+ self.bad_cert_status = self.tr(
+ "Server certificate could not be verified.")
self.certInfo = QtGui.QLabel("")
self.certInfo.setWordWrap(True)
@@ -81,25 +118,226 @@ class SelectProviderPage(QtGui.QWizardPage):
self.onTrustCheckChanged)
self.providerNameEdit.textChanged.connect(
self.onProviderChanged)
+ self.providerCheckButton.clicked.connect(
+ self.onCheckButtonClicked)
layout = QtGui.QGridLayout()
layout.addWidget(validationMsg, 0, 2)
layout.addWidget(providerNameLabel, 1, 1)
layout.addWidget(providerNameEdit, 1, 2)
+ layout.addWidget(providerCheckButton, 1, 3)
+
+ # add certinfo group
+ # XXX not shown now. should move to validation box.
+ #layout.addWidget(certinfoGroup, 4, 1, 4, 2)
+ #self.certinfoGroup = certinfoGroup
+ #self.certinfoGroup.hide()
+
+ # add validation frame
+ self.setupValidationFrame()
+ layout.addWidget(self.valFrame, 4, 2, 4, 2)
+ self.valFrame.hide()
- # XXX get a groupbox or something....
- certinfoGroup = QtGui.QGroupBox("Certificate validation")
+ self.setLayout(layout)
+
+ # certinfo
+
+ def setupCertInfoGroup(self):
+ # XXX not used now.
+ certinfoGroup = QtGui.QGroupBox(
+ self.tr("Certificate validation"))
certinfoLayout = QtGui.QVBoxLayout()
certinfoLayout.addWidget(self.certInfo)
certinfoLayout.addWidget(self.certWarning)
certinfoLayout.addWidget(self.trustProviderCertCheckBox)
certinfoGroup.setLayout(certinfoLayout)
+ self.certinfoGroup = self.certinfoGroup
- layout.addWidget(certinfoGroup, 4, 1, 4, 2)
- self.certinfoGroup = certinfoGroup
- self.certinfoGroup.hide()
+ # progress frame
- self.setLayout(layout)
+ def setupValidationFrame(self):
+ qframe = QtGui.QFrame
+ valFrame = qframe()
+ valFrame.setFrameStyle(qframe.NoFrame)
+ valframeLayout = QtGui.QVBoxLayout()
+ zeros = (0, 0, 0, 0)
+ valframeLayout.setContentsMargins(*zeros)
+
+ valframeLayout.addWidget(self.stepsTableWidget)
+ valFrame.setLayout(valframeLayout)
+ self.valFrame = valFrame
+
+ @QtCore.pyqtSlot()
+ def onDisableCheckButton(self):
+ #print 'CHECK BUTTON DISABLED!!!'
+ self.providerCheckButton.setDisabled(True)
+
+ @QtCore.pyqtSlot()
+ def launch_checks(self):
+ self.do_checks()
+
+ def onCheckButtonClicked(self):
+ QtCore.QMetaObject.invokeMethod(
+ self, "onDisableCheckButton")
+
+ QtCore.QMetaObject.invokeMethod(
+ self, "showStepsFrame")
+
+ # is this still needed?
+ # XXX can I doo delay(self, "do_checks") ?
+ delay(self, "launch_checks")
+
+ def _do_checks(self):
+ """
+ generator that yields actual checks
+ that are executed in a separate thread
+ """
+
+ wizard = self.wizard()
+ full_domain = self.providerNameEdit.text()
+
+ # we check if we have a port in the domain string.
+ domain, port = get_https_domain_and_port(full_domain)
+ _domain = u"%s:%s" % (domain, port) if port != 443 else unicode(domain)
+
+ netchecker = wizard.netchecker()
+
+ providercertchecker = wizard.providercertchecker()
+ eipconfigchecker = wizard.eipconfigchecker(domain=_domain)
+
+ yield(("head_sentinel", 0), lambda: None)
+
+ ########################
+ # 1) try name resolution
+ ########################
+
+ def namecheck():
+ """
+ in which we check if
+ we are able to name resolve
+ this domain
+ """
+ try:
+ netchecker.check_name_resolution(
+ domain)
+
+ except baseexceptions.LeapException as exc:
+ logger.error(exc.message)
+ return self.fail(exc.usermessage)
+
+ except Exception as exc:
+ return self.fail(exc.message)
+
+ else:
+ return True
+
+ logger.debug('checking name resolution')
+ yield((self.tr("checking domain name"), 20), namecheck)
+
+ #########################
+ # 2) try https connection
+ #########################
+
+ def httpscheck():
+ """
+ in which we check
+ if the provider
+ is offering service over
+ https
+ """
+ try:
+ providercertchecker.is_https_working(
+ "https://%s" % _domain,
+ verify=True)
+
+ except eipexceptions.HttpsBadCertError as exc:
+ logger.debug('exception')
+ return self.fail(exc.usermessage)
+ # XXX skipping for now...
+ ##############################################
+ # We had this validation logic
+ # in the provider selection page before
+ ##############################################
+ #if self.trustProviderCertCheckBox.isChecked():
+ #pass
+ #else:
+ #fingerprint = certs.get_cert_fingerprint(
+ #domain=domain, sep=" ")
+
+ # it's ok if we've trusted this fgprt before
+ #trustedcrts = wizard.trusted_certs
+ #if trustedcrts and \
+ # fingerprint.replace(' ', '') in trustedcrts:
+ #pass
+ #else:
+ # let your user face panick :P
+ #self.add_cert_info(fingerprint)
+ #self.did_cert_check = True
+ #self.completeChanged.emit()
+ #return False
+
+ except baseexceptions.LeapException as exc:
+ return self.fail(exc.usermessage)
+
+ except Exception as exc:
+ return self.fail(exc.message)
+
+ else:
+ return True
+
+ logger.debug('checking https connection')
+ yield((self.tr("checking https connection"), 40), httpscheck)
+
+ ##################################
+ # 3) try download provider info...
+ ##################################
+
+ def fetchinfo():
+ try:
+ # XXX we already set _domain in the initialization
+ # so it should not be needed here.
+ eipconfigchecker.fetch_definition(domain=_domain)
+ wizard.set_providerconfig(
+ eipconfigchecker.defaultprovider.config)
+ except requests.exceptions.SSLError:
+ # XXX we should have catched this before.
+ # but cert checking is broken.
+ return self.fail(self.tr(
+ "Could not get info from provider."))
+ except requests.exceptions.ConnectionError:
+ return self.fail(self.tr(
+ "Could not download provider info "
+ "(refused conn.)."))
+
+ except Exception as exc:
+ return self.fail(
+ self.tr(exc.message))
+ else:
+ return True
+
+ yield((self.tr("fetching provider info"), 80), fetchinfo)
+
+ # done!
+
+ self.is_done = True
+ yield(("end_sentinel", 100), lambda: None)
+
+ def on_checks_validation_ready(self):
+ """
+ called after _do_checks has finished.
+ """
+ self.domain_checked = True
+ self.completeChanged.emit()
+ # let's set focus...
+ if self.is_done:
+ self.wizard().clean_validation_error(self.current_page)
+ nextbutton = self.wizard().button(QtGui.QWizard.NextButton)
+ nextbutton.setFocus()
+ else:
+ self.providerNameEdit.setFocus()
+
+ # cert trust verification
+ # (disabled for now)
def is_insecure_cert_trusted(self):
return self.trustProviderCertCheckBox.isChecked()
@@ -117,38 +355,50 @@ class SelectProviderPage(QtGui.QWizardPage):
# trigger signal to redraw next button
self.completeChanged.emit()
+ def add_cert_info(self, certinfo):
+ self.certWarning.setText(
+ "Do you want to <b>trust this provider certificate?</b>")
+ self.certInfo.setText(
+ 'SHA-256 fingerprint: <i>%s</i><br>' % certinfo)
+ self.certInfo.setWordWrap(True)
+ self.certinfoGroup.show()
+
def onProviderChanged(self, text):
+ self.is_done = False
+ provider = self.providerNameEdit.text()
+ if provider:
+ self.providerCheckButton.setDisabled(False)
+ else:
+ self.providerCheckButton.setDisabled(True)
self.completeChanged.emit()
def reset_validation_status(self):
"""
empty the validation msg
+ and clean the inline validation widget.
"""
self.validationMsg.setText('')
-
- #def set_validation_status(selF, STATUS):
- #self.validationMsg.setText(status)
-
- def add_cert_info(self, certinfo):
- self.certWarning.setText(
- "Do you want to <b>trust this provider certificate?</b>")
- self.certInfo.setText(
- 'SHA-256 fingerprint: <i>%s</i><br>' % certinfo)
- self.certInfo.setWordWrap(True)
- self.certinfoGroup.show()
+ self.steps.removeAllSteps()
+ self.clearTable()
+ self.domain_checked = False
# pagewizard methods
def isComplete(self):
provider = self.providerNameEdit.text()
+ if not self.is_done:
+ return False
+
if not provider:
return False
else:
if self.is_insecure_cert_trusted():
return True
if not self.did_cert_check:
- return True
+ if self.is_done:
+ # XXX sure?
+ return True
return False
def populateErrors(self):
@@ -163,17 +413,33 @@ class SelectProviderPage(QtGui.QWizardPage):
bad_str = getattr(self, 'bad_string', None)
cur_str = self.providerNameEdit.text()
showerr = self.validationMsg.setText
+ markred = lambda: self.providerNameEdit.setStyleSheet(
+ styles.ErrorLineEdit)
+ umarkrd = lambda: self.providerNameEdit.setStyleSheet(
+ styles.RegularLineEdit)
if bad_str is None:
# first time we fall here.
# save the current bad_string value
self.bad_string = cur_str
showerr(errors)
+ markred()
else:
# not the first time
+ # XXX hey, this is getting convoluted.
+ # roll out this.
+ # but be careful about all the possibilities
+ # with going back and forth once you
+ # enter a domain.
if cur_str == bad_str:
showerr(errors)
+ markred()
else:
- showerr('')
+ if not getattr(self, 'domain_checked', None):
+ showerr('')
+ umarkrd()
+ else:
+ self.bad_string = cur_str
+ showerr(errors)
def cleanup_errormsg(self):
"""
@@ -181,6 +447,7 @@ class SelectProviderPage(QtGui.QWizardPage):
should be called before leaving the page
"""
self.bad_string = None
+ self.domain_checked = False
def paintEvent(self, event):
"""
@@ -195,7 +462,14 @@ class SelectProviderPage(QtGui.QWizardPage):
def initializePage(self):
self.validationMsg.setText('')
- self.certinfoGroup.hide()
+ if hasattr(self, 'certinfoGroup'):
+ # XXX remove ?
+ self.certinfoGroup.hide()
+ self.is_done = False
+ self.providerCheckButton.setDisabled(True)
+ self.valFrame.hide()
+ self.steps.removeAllSteps()
+ self.clearTable()
def validatePage(self):
# some cleanup before we leave the page
diff --git a/src/leap/gui/firstrun/providersetup.py b/src/leap/gui/firstrun/providersetup.py
index 3fb9a19b..1a362794 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__)
@@ -17,21 +17,26 @@ logger = logging.getLogger(__name__)
class ProviderSetupValidationPage(ValidationPage):
def __init__(self, parent=None):
super(ProviderSetupValidationPage, self).__init__(parent)
+ self.current_page = "providersetupvalidation"
+
+ # XXX needed anymore?
is_signup = self.field("is_signup")
self.is_signup = is_signup
- self.setTitle("Setting up provider")
- #self.setSubTitle(
- #"auto configuring provider...")
+ self.setTitle(self.tr("Provider setup"))
+ self.setSubTitle(
+ 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
"""
+
full_domain = self.field('provider_domain')
wizard = self.wizard()
pconfig = wizard.providerconfig
@@ -41,68 +46,50 @@ 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)
-
- 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)
-
- except auth.SRPAuthenticationError as exc:
- self.set_error(
- step,
- "Authentication error: %s" % exc.message)
- return False
-
- pause_for_user()
+ pCertChecker.download_ca_cert(
+ uri=ca_cert_uri,
+ verify=False)
- #######################################
+ except baseexceptions.LeapException as exc:
+ logger.error(exc.message)
+ # XXX this should be _ method
+ return self.fail(self.tr(exc.usermessage))
- update_signal.emit('Fetching CA certificate', 30)
- pause_for_user()
+ except Exception as exc:
+ return self.fail(exc.message)
- if pconfig:
- ca_cert_uri = pconfig.get('ca_cert_uri').geturl()
- else:
- ca_cert_uri = None
+ else:
+ return True
- # 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)
+ yield((self.tr('Fetching CA certificate'), 30),
+ fetchcacert)
- pCertChecker.download_ca_cert(
- uri=ca_cert_uri,
- verify=False)
- pause_for_user()
+ #########################
+ # 2) check CA fingerprint
+ #########################
- 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,31 +102,41 @@ 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
- pause_for_user()
- #ca_cert_path = checker.ca_cert_path
-
- update_signal.emit('end_sentinel', 100)
- pause_for_user()
-
- def _do_validation(self):
+ 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
+
+ yield((self.tr('Validating api certificate'), 90), validatecacert)
+
+ self.set_done()
+ yield(('end_sentinel', 100), lambda: None)
+
+ def on_checks_validation_ready(self):
"""
called after _do_checks has finished
(connected to checker thread finished signal)
@@ -153,10 +150,11 @@ class ProviderSetupValidationPage(ValidationPage):
wizard.set_validation_error(
prevpage,
first_error)
- self.go_back()
+ # XXX don't go back, signal error
+ #self.go_back()
else:
- logger.debug('going next')
- self.go_next()
+ logger.debug('should be going next, wait on user')
+ #self.go_next()
def nextId(self):
wizard = self.wizard()
@@ -169,3 +167,8 @@ class ProviderSetupValidationPage(ValidationPage):
# XXX bad name. change to connect again.
next_ = 'signupvalidation'
return wizard.get_page_index(next_)
+
+ def initializePage(self):
+ super(ProviderSetupValidationPage, self).initializePage()
+ self.set_undone()
+ self.completeChanged.emit()
diff --git a/src/leap/gui/firstrun/register.py b/src/leap/gui/firstrun/register.py
index b46dd4cd..e85723cb 100644
--- a/src/leap/gui/firstrun/register.py
+++ b/src/leap/gui/firstrun/register.py
@@ -1,8 +1,11 @@
"""
Register User Page, used in First Run Wizard
"""
+import json
import logging
+import socket
+import requests
from PyQt4 import QtCore
from PyQt4 import QtGui
@@ -11,24 +14,37 @@ 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
-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.setupSteps()
+ self.setupUI()
+ self.do_confirm_next = False
+ self.focused_field = False
+ def setupUI(self):
userNameLabel = QtGui.QLabel("User &name:")
userNameLineEdit = QtGui.QLineEdit()
userNameLineEdit.cursorPositionChanged.connect(
@@ -59,6 +75,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!
@@ -81,21 +98,72 @@ 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)
+ self.commitText("Sign up!")
- # pagewizard methods
+ # commit button
+
+ def commitText(self, text):
+ # change "commit" button text
+ self.setButtonText(
+ QtGui.QWizard.CommitButton, text)
+
+ @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)
+ #prev_er = getattr(self, 'prevalidation_error', None)
if bad_str is None:
# first time we fall here.
@@ -103,14 +171,20 @@ class RegisterUserPage(QtGui.QWizardPage, 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)
else:
+ self.focused_field = False
showerr('')
+ unmarkred()
+ else:
+ # no errors
+ self.focused_field = False
+ unmarkred()
def cleanup_errormsg(self):
"""
@@ -130,45 +204,149 @@ 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):
+ def _do_checks(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.
+ generator that yields actual checks
+ that are executed in a separate thread
"""
-
- #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.
+ def checkpass():
+ # we better have here
+ # some call to a password checker...
+ # to assess strenght and avoid silly stuff.
+
+ if password != password2:
+ return self.fail(self.tr('Password does not match..'))
+
+ if len(password) < 6:
+ #self.set_prevalidation_error('Password too short.')
+ return self.fail(self.tr('Password too short.'))
+
+ if password == "123456":
+ # joking, but not too much.
+ #self.set_prevalidation_error('Password too obvious.')
+ return self.fail(self.tr('Password too obvious.'))
+
+ # go
+ return True
+
+ yield(("head_sentinel", 0), checkpass)
- if password != password2:
- self.set_prevalidation_error('Password does not match.')
- return False
+ # XXX should emit signal for .show the frame!
+ # XXX HERE!
- if len(password) < 6:
- self.set_prevalidation_error('Password too short.')
- return False
+ ##################################################
+ # 1) register user
+ ##################################################
- if password == "123456":
- # joking, but not too much.
- self.set_prevalidation_error('Password too obvious.')
- return False
+ # show the frame before going on...
+ QtCore.QMetaObject.invokeMethod(
+ self, "showStepsFrame")
- # some cleanup before we leave the page
+ 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:
+ return self.fail(
+ self.tr("Error connecting to provider (timeout)"))
+
+ except requests.exceptions.ConnectionError as exc:
+ logger.error(exc.message)
+ 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):
+ return self.fail(
+ 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)
+
+ if errors and errors.get('login', None):
+ # XXX this sometimes catch the blank username
+ # but we're not allowing that (soon)
+ return self.fail(
+ self.tr('Username not available.'))
+
+ logger.debug('registering user')
+ yield(("registering with provider", 40), register)
+
+ self.set_done()
+ yield(("end_sentinel", 0), lambda: None)
+
+ def on_checks_validation_ready(self):
+ """
+ after checks
+ """
+ if self.is_done():
+ self.disableFields()
+ self.cleanup_errormsg()
+ 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()
- # go
- return True
+ return self.is_done()
def initializePage(self):
"""
@@ -176,13 +354,15 @@ 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('')
+ 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')
diff --git a/src/leap/gui/firstrun/regvalidation.py b/src/leap/gui/firstrun/regvalidation.py
index dbe30d3c..0e67834b 100644
--- a/src/leap/gui/firstrun/regvalidation.py
+++ b/src/leap/gui/firstrun/regvalidation.py
@@ -9,18 +9,18 @@ used in First Run Wizard
# the login branch of the wizard.
import logging
-import json
-import socket
+#import json
+#import socket
from PyQt4 import QtGui
-import requests
+#import requests
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__)
@@ -29,16 +29,10 @@ class RegisterUserValidationPage(ValidationPage):
def __init__(self, parent=None):
super(RegisterUserValidationPage, self).__init__(parent)
- is_signup = self.field("is_signup")
- self.is_signup = is_signup
- if is_signup:
- title = "User Creation"
- subtitle = "Registering account with provider."
- else:
- title = "Connecting..."
- # XXX uh... really?
- subtitle = "Checking connection with provider."
+ title = "Connecting..."
+ # XXX uh... really?
+ subtitle = "Checking connection with provider."
self.setTitle(title)
self.setSubTitle(subtitle)
@@ -67,7 +61,7 @@ class RegisterUserValidationPage(ValidationPage):
# Set Credentials.
# username and password are in different fields
# if they were stored in log_in or sign_up pages.
- is_signup = self.is_signup
+ is_signup = self.field("is_signup")
unamek_base = 'userName'
passwk_base = 'userPassword'
@@ -83,125 +77,58 @@ class RegisterUserValidationPage(ValidationPage):
pCertChecker = wizard.providercertchecker(
domain=full_domain)
- ###########################################
- # only if from signup
- if is_signup:
- signup = auth.LeapSRPRegister(
- schema="https",
- provider=full_domain,
- verify=verify)
-
- update_signal.emit("head_sentinel", 0)
+ yield(("head_sentinel", 0), lambda: None)
##################################################
- # 1) register user
+ # 1) fetching eip service config
##################################################
- # only if from signup.
-
- if is_signup:
-
- step = "register"
- update_signal.emit("checking availability", 20)
- update_signal.emit("registering with provider", 40)
- logger.debug('registering user')
-
+ def fetcheipconf():
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()
+ eipconfigchecker.fetch_eip_service_config(
+ domain=full_domain)
- ##################################################
- # 2) fetching eip service config
- ##################################################
+ # XXX get specific exception
+ except Exception as exc:
+ return self.fail(exc.message)
- step = "fetch_eipconf"
- fetching_eipconf_msg = "Fetching eip service configuration"
- update_signal.emit(fetching_eipconf_msg, 60)
- try:
- eipconfigchecker.fetch_eip_service_config(
- domain=full_domain)
-
- # XXX get specific exception
- except:
- self.set_error(
- step,
- 'Could not download eip config.')
- pause_for_user()
- return False
- pause_for_user()
+ yield((self.tr("Fetching provider config..."), 40),
+ fetcheipconf)
##################################################
- # 3) getting client certificate
+ # 2) getting client certificate
##################################################
- # XXX maybe only do this if we come from signup
-
- step = "fetch_eipcert"
- fetching_clientcert_msg = "Fetching eip certificate"
- update_signal.emit(fetching_clientcert_msg, 80)
- try:
- pCertChecker.download_new_client_cert(
- credentials=credentials,
- verify=verify)
+ def fetcheipcert():
+ try:
+ pCertChecker.download_new_client_cert(
+ credentials=credentials,
+ verify=verify)
- except auth.SRPAuthenticationError as exc:
- self.set_error(
- step,
- "Authentication error: %s" % exc.message)
- return False
+ except auth.SRPAuthenticationError as exc:
+ return self.fail(self.tr(
+ "Authentication error: %s" % exc.message))
+ else:
+ return True
- pause_for_user()
+ yield((self.tr("Fetching eip certificate"), 80),
+ fetcheipcert)
################
# end !
################
+ self.set_done()
+ yield(("end_sentinel", 100), lambda: None)
- update_signal.emit("end_sentinel", 100)
- pause_for_user()
-
+ def on_checks_validation_ready(self):
+ """
+ called after _do_checks has finished
+ (connected to checker thread finished signal)
+ """
+ # this should be called CONNECT PAGE AGAIN.
# here we go! :)
+ full_domain = self.field('provider_domain')
+ domain, port = get_https_domain_and_port(full_domain)
+ _domain = u"%s:%s" % (domain, port) if port != 443 else unicode(domain)
self.run_eip_checks_for_provider_and_connect(_domain)
def run_eip_checks_for_provider_and_connect(self, domain):
@@ -225,6 +152,14 @@ class RegisterUserValidationPage(ValidationPage):
"probably the wizard has been launched "
"in an stand-alone way.")
+ # XXX look for a better place to signal
+ # we are done.
+ # We could probably have a fake validatePage
+ # that checks if the domain transfer has been
+ # done to conductor object, triggers the start_signal
+ # and does the go_next()
+ self.set_done()
+
def eip_error_check(self):
"""
a version of the main app error checker,
@@ -241,7 +176,8 @@ class RegisterUserValidationPage(ValidationPage):
called after _do_checks has finished
(connected to checker thread finished signal)
"""
- prevpage = "signup" if self.is_signup else "login"
+ is_signup = self.field("is_signup")
+ prevpage = "signup" if is_signup else "login"
wizard = self.wizard()
if self.errors:
@@ -253,13 +189,16 @@ class RegisterUserValidationPage(ValidationPage):
first_error)
self.go_back()
else:
- logger.debug('going next')
- # check if this "next" interferes
- # with the eip signal.
- self.go_next()
+ logger.debug('should go next, wait for user to click next')
+ #self.go_next()
def nextId(self):
wizard = self.wizard()
if not wizard:
return
return wizard.get_page_index('lastpage')
+
+ def initializePage(self):
+ super(RegisterUserValidationPage, self).initializePage()
+ self.set_undone()
+ self.completeChanged.emit()
diff --git a/src/leap/gui/firstrun/wizard.py b/src/leap/gui/firstrun/wizard.py
index bbb48149..9b77b877 100755
--- a/src/leap/gui/firstrun/wizard.py
+++ b/src/leap/gui/firstrun/wizard.py
@@ -39,7 +39,7 @@ TODO-ish:
[ ] Document signals used / expected.
[ ] Separate style from widgets.
[ ] Fix TOFU Widget for provider cert.
-[ ] Refactor widgets out.
+[X] Refactor widgets out.
[ ] Follow more MVC style.
[ ] Maybe separate "first run wizard" into different wizards
that share some of the pages?
@@ -137,6 +137,10 @@ class FirstRunWizard(QtGui.QWizard):
QtGui.QWizard.BackgroundPixmap,
QtGui.QPixmap(':/images/background.png'))
+ # set options
+ self.setOption(QtGui.QWizard.IndependentPages, on=False)
+ self.setOption(QtGui.QWizard.NoBackButtonOnStartPage, on=True)
+
self.setWindowTitle("First Run Wizard")
# TODO: set style for MAC / windows ...
@@ -167,6 +171,11 @@ class FirstRunWizard(QtGui.QWizard):
def set_validation_error(self, pagename, error):
self.validation_errors[pagename] = error
+ def clean_validation_error(self, pagename):
+ vald = self.validation_errors
+ if pagename in vald:
+ del vald[pagename]
+
def get_validation_error(self, pagename):
return self.validation_errors.get(pagename, None)