summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkali <kali@leap.se>2012-11-09 11:21:40 +0900
committerkali <kali@leap.se>2012-11-09 11:21:40 +0900
commit8118056a244ca74d16380ad26a70e3da40e7e401 (patch)
tree4363948d180a667a545807b99b2d3199e30b5950
parentb84007d8fec8c949ba4ac1d26695c710a210d797 (diff)
connect page merged into regvalidation.
Flow nearly working with fake provider, except for authentication.
-rw-r--r--src/leap/base/auth.py5
-rw-r--r--src/leap/gui/constants.py5
-rw-r--r--src/leap/gui/firstrun/constants.py0
-rw-r--r--src/leap/gui/firstrun/providerinfo.py24
-rw-r--r--src/leap/gui/firstrun/providerselect.py10
-rw-r--r--src/leap/gui/firstrun/register.py49
-rw-r--r--src/leap/gui/firstrun/regvalidation.py186
-rw-r--r--src/leap/gui/progress.py6
-rw-r--r--src/leap/util/web.py18
9 files changed, 211 insertions, 92 deletions
diff --git a/src/leap/base/auth.py b/src/leap/base/auth.py
index 9ee159e7..f1b618ba 100644
--- a/src/leap/base/auth.py
+++ b/src/leap/base/auth.py
@@ -37,6 +37,7 @@ class LeapSRPRegister(object):
schema="https",
provider=None,
port=None,
+ verify=True,
register_path="1/users.json",
method="POST",
fetcher=requests,
@@ -47,6 +48,7 @@ class LeapSRPRegister(object):
self.schema = schema
self.provider = provider
self.port = port
+ self.verify = verify
self.register_path = register_path
self.method = method
self.fetcher = fetcher
@@ -98,7 +100,8 @@ class LeapSRPRegister(object):
# XXX get self.method
req = self.session.post(
uri, data=user_data,
- timeout=SIGNUP_TIMEOUT)
+ timeout=SIGNUP_TIMEOUT,
+ verify=self.verify)
logger.debug(req)
logger.debug('user_data: %s', user_data)
#logger.debug('response: %s', req.text)
diff --git a/src/leap/gui/constants.py b/src/leap/gui/constants.py
index c874cbc9..277f3540 100644
--- a/src/leap/gui/constants.py
+++ b/src/leap/gui/constants.py
@@ -1,3 +1,5 @@
+import time
+
APP_LOGO = ':/images/leap-color-small.png'
# bare is the username portion of a JID
@@ -6,3 +8,6 @@ APP_LOGO = ':/images/leap-color-small.png'
BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$"
FULL_USERNAME_REGEX = r"^[A-Za-z\d_@.-]+$"
+
+GUI_PAUSE_FOR_USER_SECONDS = 1
+pause_for_user = lambda: time.sleep(GUI_PAUSE_FOR_USER_SECONDS)
diff --git a/src/leap/gui/firstrun/constants.py b/src/leap/gui/firstrun/constants.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/leap/gui/firstrun/constants.py
diff --git a/src/leap/gui/firstrun/providerinfo.py b/src/leap/gui/firstrun/providerinfo.py
index 9b959602..4df477a7 100644
--- a/src/leap/gui/firstrun/providerinfo.py
+++ b/src/leap/gui/firstrun/providerinfo.py
@@ -2,7 +2,6 @@
Provider Info Page, used in First run Wizard
"""
import logging
-import time
from PyQt4 import QtCore
from PyQt4 import QtGui
@@ -14,29 +13,12 @@ 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
+from leap.gui.constants import APP_LOGO, pause_for_user
logger = logging.getLogger(__name__)
-GUI_PAUSE_FOR_USER_SECONDS = 1
-pause_for_user = lambda: time.sleep(GUI_PAUSE_FOR_USER_SECONDS)
-
-
-def get_https_domain_and_port(full_domain):
- """
- returns a tuple with domain and port
- from a full_domain string that can
- contain a colon
- """
- domain_split = full_domain.split(':')
- _len = len(domain_split)
- if _len == 1:
- domain, port = full_domain, 443
- if _len == 2:
- domain, port = domain_split
- return domain, port
-
class ProviderInfoPage(ValidationPage):
def __init__(self, parent=None):
@@ -127,7 +109,7 @@ class ProviderInfoPage(ValidationPage):
domain)
except baseexceptions.LeapException as exc:
- logger.debug('exception')
+ logger.error(exc.message)
wizard.set_validation_error(
prevpage, exc.usermessage)
pause_and_finish()
diff --git a/src/leap/gui/firstrun/providerselect.py b/src/leap/gui/firstrun/providerselect.py
index c282e3ab..a20f40b3 100644
--- a/src/leap/gui/firstrun/providerselect.py
+++ b/src/leap/gui/firstrun/providerselect.py
@@ -6,9 +6,9 @@ import logging
from PyQt4 import QtCore
from PyQt4 import QtGui
-from leap.base import exceptions as baseexceptions
-from leap.crypto import certs
-from leap.eip import exceptions as eipexceptions
+#from leap.base import exceptions as baseexceptions
+#from leap.crypto import certs
+#from leap.eip import exceptions as eipexceptions
from leap.gui.constants import APP_LOGO
from leap.gui.styles import ErrorLabelStyleSheet
@@ -30,6 +30,7 @@ class SelectProviderPage(QtGui.QWizardPage):
QtGui.QPixmap(APP_LOGO))
self.did_cert_check = False
+ self.current_page = 'providerselection'
providerNameLabel = QtGui.QLabel("h&ttps://")
# note that we expect the bare domain name
@@ -154,7 +155,8 @@ class SelectProviderPage(QtGui.QWizardPage):
# XXX could move this to ValidationMixin
#logger.debug('getting errors')
- errors = self.wizard().get_validation_error('providerselection')
+ errors = self.wizard().get_validation_error(
+ self.current_page)
if errors:
#logger.debug('errors! -> %s', errors)
self.validationMsg.setText(errors)
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:
diff --git a/src/leap/gui/firstrun/regvalidation.py b/src/leap/gui/firstrun/regvalidation.py
index 6cf150b6..f6d69a60 100644
--- a/src/leap/gui/firstrun/regvalidation.py
+++ b/src/leap/gui/firstrun/regvalidation.py
@@ -5,16 +5,16 @@ used if First Run Wizard
import logging
import json
import socket
-import time
from PyQt4 import QtGui
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
+from leap.gui.constants import APP_LOGO, pause_for_user
logger = logging.getLogger(__name__)
@@ -22,6 +22,10 @@ logger = logging.getLogger(__name__)
class RegisterUserValidationPage(ValidationPage):
def __init__(self, parent=None):
+ # XXX TODO:
+ # We should check if we come from signup
+ # or login, and change title / first step
+ # accordingly.
super(RegisterUserValidationPage, self).__init__(parent)
self.setTitle("User Creation")
@@ -39,25 +43,40 @@ class RegisterUserValidationPage(ValidationPage):
we initialize the srp protocol register
and try to register user.
"""
- print 'register user checks'
-
wizard = self.wizard()
- domain = self.field('provider_domain')
- username = self.field('userName')
- password = self.field('userPassword')
+ full_domain = self.field('provider_domain')
+ domain, port = get_https_domain_and_port(full_domain)
- # XXX use pause_for_user from providerinfo
- update_signal.emit("head_sentinel", 0)
- update_signal.emit("registering with provider", 40)
- time.sleep(0.5)
- update_signal.emit("registering 2", 60)
- time.sleep(1)
- update_signal.emit("end_sentinel", 100)
- time.sleep(0.5)
- return
+ # FIXME #BUG 638 FIXME FIXME FIXME
+ verify = False # !!!!!!!!!!!!!!!!
+ # FIXME #BUG 638 FIXME FIXME FIXME
+
+ ###########################################
+ # Set Credentials.
+ # username and password are in different fields
+ # if they were stored in log_in or sign_up pages.
+
+ from_login = self.wizard().from_login
+ unamek_base = 'userName'
+ passwk_base = 'userPassword'
+ unamek = 'login_%s' % unamek_base if from_login else unamek_base
+ passwk = 'login_%s' % passwk_base if from_login else passwk_base
+
+ username = self.field(unamek)
+ password = self.field(passwk)
+ credentials = username, password
+
+ eipconfigchecker = wizard.eipconfigchecker()
+ pCertChecker = wizard.providercertchecker(
+ domain=domain)
+
+ ###########################################
+ # XXX this only should be setup
+ # if not from_login.
if wizard and wizard.debug_server:
# We're debugging
+ # XXX remove this branch?
dbgsrv = wizard.debug_server
schema = dbgsrv.scheme
netloc = dbgsrv.netloc
@@ -71,71 +90,140 @@ class RegisterUserValidationPage(ValidationPage):
signup = auth.LeapSRPRegister(
scheme=schema,
provider=provider,
- port=port)
+ port=port,
+ verify=verify)
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)
+ schema="https",
+ port=port,
+ provider=domain,
+ verify=verify)
+
+ update_signal.emit("head_sentinel", 0)
+
+ ##################################################
+ # 1) register user
+ ##################################################
+ # XXX this only should be DONE
+ # if NOT from_login.
+
+ step = "register"
+ update_signal.emit("registering with provider", 40)
+ logger.debug('registering user')
+
try:
- ok, req = signup.register_user(username, password)
+ ok, req = signup.register_user(
+ username, password)
+
except socket.timeout:
- self.set_validation_status(
+ self.set_error(
+ step,
"Error connecting to provider (timeout)")
+ pause_for_user()
return False
except requests.exceptions.ConnectionError as exc:
- logger.error(exc)
- self.set_validation_status(
+ 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
- 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
+ # XXX check for != OK instead???
- if req.status_code == 404:
- self.set_validation_status(
- "Error during registration (404)")
+ 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)
- logger.debug('validation errors: %s' % validation_msgs)
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_validation_status(
+ self.set_error(
+ step,
'Username not available.')
- else:
- self.set_validation_status(
- "Error during sign up")
- return False
+ pause_for_user()
+ return False
+
+ pause_for_user()
+
+ ##################################################
+ # 2) fetching eip service config
+ ##################################################
+
+ 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()
+
+ ##################################################
+ # 3) getting client certificate
+ ##################################################
+
+ 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)
+
+ except auth.SRPAuthenticationError as exc:
+ self.set_error(
+ step,
+ "Authentication error: %s" % exc.message)
+ return False
+
+ pause_for_user()
+
+ ################
+ # end !
+ ################
+
+ update_signal.emit("end_sentinel", 100)
+ pause_for_user()
def _do_validation(self):
"""
called after _do_checks has finished
(connected to checker thread finished signal)
"""
+ is_signup = self.field("is_signup")
+ prevpage = "signup" if is_signup else "login"
+
wizard = self.wizard()
if self.errors:
print 'going back with errors'
+ logger.error(self.errors)
+ name, first_error = self.pop_first_error()
wizard.set_validation_error(
- 'signup', 'that name is taken')
+ prevpage,
+ first_error)
self.go_back()
else:
print 'going next'
@@ -145,4 +233,4 @@ class RegisterUserValidationPage(ValidationPage):
wizard = self.wizard()
if not wizard:
return
- return wizard.get_page_index('connecting')
+ return wizard.get_page_index('lastpage')
diff --git a/src/leap/gui/progress.py b/src/leap/gui/progress.py
index d6551939..b2e34e22 100644
--- a/src/leap/gui/progress.py
+++ b/src/leap/gui/progress.py
@@ -186,6 +186,12 @@ class ValidationPage(QtGui.QWizardPage):
self.errors = OrderedDict()
+ def set_error(self, name, error):
+ self.errors[name] = error
+
+ def pop_first_error(self):
+ return list(reversed(self.errors.items())).pop()
+
def populateStepsTable(self):
# from examples,
# but I guess it's not needed to re-populate
diff --git a/src/leap/util/web.py b/src/leap/util/web.py
new file mode 100644
index 00000000..6ddf4b21
--- /dev/null
+++ b/src/leap/util/web.py
@@ -0,0 +1,18 @@
+"""
+web related utilities
+"""
+
+
+def get_https_domain_and_port(full_domain):
+ """
+ returns a tuple with domain and port
+ from a full_domain string that can
+ contain a colon
+ """
+ domain_split = full_domain.split(':')
+ _len = len(domain_split)
+ if _len == 1:
+ domain, port = full_domain, 443
+ if _len == 2:
+ domain, port = domain_split
+ return domain, port