From 361a18b0e727a68d6e0d1e9d03273630b9c14692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Wed, 6 Mar 2013 15:43:36 -0300 Subject: Add UI merging all the code Also add resources --- src/leap/gui/wizard.py | 403 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 403 insertions(+) create mode 100644 src/leap/gui/wizard.py (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py new file mode 100644 index 00000000..7dcc8dd6 --- /dev/null +++ b/src/leap/gui/wizard.py @@ -0,0 +1,403 @@ +# -*- coding: utf-8 -*- +# wizard.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +First run wizard +""" +import os +import logging + +from PySide import QtCore, QtGui + +from ui_wizard import Ui_Wizard +from leap.config.providerconfig import ProviderConfig +from leap.crypto.srpregister import SRPRegister +from leap.services.eip.providerbootstrapper import ProviderBootstrapper +from leap.services.eip.eipbootstrapper import EIPBootstrapper + +logger = logging.getLogger(__name__) + + +class Wizard(QtGui.QWizard): + """ + First run wizard to register a user and setup a provider + """ + + INTRO_PAGE = 0 + SELECT_PROVIDER_PAGE = 1 + PRESENT_PROVIDER_PAGE = 2 + SETUP_PROVIDER_PAGE = 3 + REGISTER_USER_PAGE = 4 + SETUP_EIP_PAGE = 5 + FINISH_PATH = 6 + + WEAK_PASSWORDS = ("1234", "12345", "123456", + "password") + + def __init__(self): + QtGui.QWizard.__init__(self) + + self.ui = Ui_Wizard() + self.ui.setupUi(self) + + self.QUESTION_ICON = QtGui.QPixmap(":/images/Emblem-question.png") + self.ERROR_ICON = QtGui.QPixmap(":/images/Dialog-error.png") + self.OK_ICON = QtGui.QPixmap(":/images/Dialog-accept.png") + + self._show_register = False + + self.ui.grpCheckProvider.setVisible(False) + self.ui.btnCheck.clicked.connect(self._check_provider) + self.ui.lnProvider.returnPressed.connect(self._check_provider) + + self._provider_bootstrapper = ProviderBootstrapper() + self._provider_bootstrapper.name_resolution.connect( + self._name_resolution) + self._provider_bootstrapper.https_connection.connect( + self._https_connection) + self._provider_bootstrapper.download_provider_info.connect( + self._download_provider_info) + + self._provider_bootstrapper.download_ca_cert.connect( + self._download_ca_cert) + self._provider_bootstrapper.check_ca_fingerprint.connect( + self._check_ca_fingerprint) + self._provider_bootstrapper.check_api_certificate.connect( + self._check_api_certificate) + + self._eip_bootstrapper = EIPBootstrapper() + + self._eip_bootstrapper.download_config.connect( + self._download_eip_config) + self._eip_bootstrapper.download_client_certificate.connect( + self._download_client_certificate) + + self._domain = None + self._provider_config = ProviderConfig() + + self.currentIdChanged.connect(self._current_id_changed) + + self.ui.lblPassword.setEchoMode(QtGui.QLineEdit.Password) + self.ui.lblPassword2.setEchoMode(QtGui.QLineEdit.Password) + + self.ui.lblUser.returnPressed.connect( + self._focus_password) + self.ui.lblPassword.returnPressed.connect( + self._focus_second_password) + self.ui.lblPassword2.returnPressed.connect( + self._register) + self.ui.btnRegister.clicked.connect( + self._register) + + self._username = None + + def __del__(self): + self._provider_bootstrapper.set_should_quit() + self._eip_bootstrapper.set_should_quit() + self._provider_bootstrapper.wait() + self._eip_bootstrapper.wait() + + def get_username(self): + return self._username + + def _focus_password(self): + """ + Focuses at the password lineedit for the registration page + """ + self.ui.lblPassword.setFocus() + + def _focus_second_password(self): + """ + Focuses at the second password lineedit for the registration page + """ + self.ui.lblPassword2.setFocus() + + def _basic_password_checks(self, username, password, password2): + """ + Performs basic password checks to avoid really easy passwords. + + @param username: username provided at the registrarion form + @type username: str + @param password: password from the registration form + @type password: str + @param password2: second password from the registration form + @type password: str + + @return: returns True if all the checks pass, False otherwise + @rtype: bool + """ + message = None + + try: + username.encode("ascii") + password.encode("ascii") + except: + message = u"Refrain from using non ASCII áñ characters" + + if message is not None and password != password2: + message = "Passwords don't match" + + if message is not None and len(password) < 4: + message = "Password too short" + + if message is not None and password in self.WEAK_PASSWORDS: + message = "Password too easy" + + if message is not None and username == password: + message = "Password equal to username" + + if message is not None: + self._set_register_status(message) + self._focus_password() + return False + + return True + + def _register(self): + """ + Performs the registration based on the values provided in the form + """ + self.ui.btnRegister.setEnabled(False) + # See the disabled button + while QtGui.QApplication.instance().hasPendingEvents(): + QtGui.QApplication.instance().processEvents() + self.button(QtGui.QWizard.NextButton).setFocus() + + username = self.ui.lblUser.text() + password = self.ui.lblPassword.text() + password2 = self.ui.lblPassword2.text() + + if self._basic_password_checks(username, password, password2): + register = SRPRegister(provider_config=self._provider_config) + ok, req = register.register_user(username, password) + if ok: + self._set_register_status("User registration OK") + self._username = username + self.ui.lblPassword2.clearFocus() + # Detach this call to allow UI updates briefly + QtCore.QTimer.singleShot(1, + self.page(self.REGISTER_USER_PAGE) + .set_completed) + else: + print req.content + error_msg = "Unknown error" + try: + error_msg = req.json().get("errors").get("login")[0] + except: + logger.error("Unknown error: %r" % (req.content,)) + self._set_register_status(error_msg) + self.ui.btnRegister.setEnabled(True) + else: + self.ui.btnRegister.setEnabled(True) + + def _set_register_status(self, status): + """ + Sets the status label in the registration page to status + + @param status: status message to display, can be HTML + @type status: str + """ + self.ui.lblRegisterStatus.setText(status) + + def _check_provider(self): + """ + SLOT + TRIGGERS: + self.ui.btnCheck.clicked + self.ui.lnProvider.returnPressed + + Starts the checks for a given provider + """ + self.ui.grpCheckProvider.setVisible(True) + self.ui.btnCheck.setEnabled(False) + self._domain = self.ui.lnProvider.text() + + self._provider_bootstrapper.start() + self._provider_bootstrapper.run_provider_select_checks(self._domain) + + def _complete_task(self, data, label, complete=False, complete_page=-1): + """ + Checks a task and completes a page if specified + + @param data: data as it comes from the bootstrapper thread for + a specific check + @type data: dict + @param label: label that displays the status icon for a + specific check that corresponds to the data + @type label: QtGui.QLabel + @param complete: if True, it completes the page specified, + which must be of type WizardPage + @type complete: bool + @param complete_page: page id to complete + @type complete_page: int + """ + passed = data[self._provider_bootstrapper.PASSED_KEY] + error = data[self._provider_bootstrapper.ERROR_KEY] + if passed: + label.setPixmap(self.OK_ICON) + if complete: + self.page(complete_page).set_completed() + self.button(QtGui.QWizard.NextButton).setFocus() + else: + label.setPixmap(self.ERROR_ICON) + logger.error(error) + + def _name_resolution(self, data): + """ + SLOT + TRIGGER: self._provider_bootstrapper.name_resolution + + Sets the status for the name resolution check + """ + self._complete_task(data, self.ui.lblNameResolution) + + def _https_connection(self, data): + """ + SLOT + TRIGGER: self._provider_bootstrapper.https_connection + + Sets the status for the https connection check + """ + self._complete_task(data, self.ui.lblHTTPS) + + def _download_provider_info(self, data): + """ + SLOT + TRIGGER: self._provider_bootstrapper.download_provider_info + + Sets the status for the provider information download + check. Since this check is the last of this set, it also + completes the page if passed + """ + if self._provider_config.load(os.path.join("leap", + "providers", + self._domain, + "provider.json")): + self._complete_task(data, self.ui.lblProviderInfo, + True, self.SELECT_PROVIDER_PAGE) + else: + new_data = { + self._provider_bootstrapper.PASSED_KEY: False, + self._provider_bootstrapper.ERROR_KEY: + "Unable to load provider configuration" + } + self._complete_task(new_data, self.ui.lblProviderInfo) + + self.ui.btnCheck.setEnabled(True) + + def _download_ca_cert(self, data): + """ + SLOT + TRIGGER: self._provider_bootstrapper.download_ca_cert + + Sets the status for the download of the CA certificate check + """ + self._complete_task(data, self.ui.lblDownloadCaCert) + + def _check_ca_fingerprint(self, data): + """ + SLOT + TRIGGER: self._provider_bootstrapper.check_ca_fingerprint + + Sets the status for the CA fingerprint check + """ + self._complete_task(data, self.ui.lblCheckCaFpr) + + def _check_api_certificate(self, data): + """ + SLOT + TRIGGER: self._provider_bootstrapper.check_api_certificate + + Sets the status for the API certificate check. Also finishes + the provider bootstrapper thread since it's not needed anymore + from this point on, unless the whole check chain is restarted + """ + self._complete_task(data, self.ui.lblCheckApiCert, + True, self.SETUP_PROVIDER_PAGE) + self._provider_bootstrapper.set_should_quit() + + def _download_eip_config(self, data): + """ + SLOT + TRIGGER: self._eip_bootstrapper.download_config + + Sets the status for the EIP config downloading check + """ + self._complete_task(data, self.ui.lblDownloadEIPConfig) + + def _download_client_certificate(self, data): + """ + SLOT + TRIGGER: self._provider_bootstrapper.download_client_certificate + + Sets the status for the download client certificate check and + completes the page if passed. Also stops the eip bootstrapper + thread since it's not needed from this point on unless the + check chain is restarted + """ + self._complete_task(data, self.ui.lblDownloadClientCert, + True, self.SETUP_EIP_PAGE) + self._eip_bootstrapper.set_should_quit() + + def _current_id_changed(self, pageId): + """ + SLOT + TRIGGER: self.currentIdChanged + + Prepares the pages when they appear + """ + if pageId == self.SELECT_PROVIDER_PAGE: + self.ui.grpCheckProvider.setVisible(False) + self.ui.lblNameResolution.setPixmap(self.QUESTION_ICON) + self.ui.lblHTTPS.setPixmap(self.QUESTION_ICON) + self.ui.lblProviderInfo.setPixmap(self.QUESTION_ICON) + + if pageId == self.SETUP_PROVIDER_PAGE: + self._provider_bootstrapper.\ + run_provider_setup_checks(self._provider_config) + + if pageId == self.SETUP_EIP_PAGE: + self._eip_bootstrapper.start() + self._eip_bootstrapper.run_eip_setup_checks(self._provider_config) + + if pageId == self.PRESENT_PROVIDER_PAGE: + # TODO: get the right lang for these + self.ui.lblProviderName.setText( + "%s" % + (self._provider_config.get_name(),)) + self.ui.lblProviderURL.setText(self._provider_config.get_domain()) + self.ui.lblProviderDesc.setText( + "%s" % + (self._provider_config.get_description(),)) + self.ui.lblProviderPolicy.setText(self._provider_config + .get_enrollment_policy()) + + def nextId(self): + """ + Sets the next page id for the wizard based on wether the user + wants to register a new identity or uses an existing one + """ + if self.currentPage() == self.page(self.INTRO_PAGE): + self._show_register = self.ui.rdoRegister.isChecked() + + if self.currentPage() == self.page(self.SETUP_PROVIDER_PAGE): + if self._show_register: + return self.REGISTER_USER_PAGE + else: + return self.SETUP_EIP_PAGE + + return QtGui.QWizard.nextId(self) -- cgit v1.2.3 From 751638b4eb8208e1eaa1beaaed284da6b412bca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Thu, 7 Mar 2013 19:05:11 -0300 Subject: Change asserts for a custom leap_assert method Also: - Make SRPAuth and the Bootstrappers be a QObject instead of a QThread so we can use them inside another more generic thread - Add a generic CheckerThread that runs checks or whatever operation as long as it returns a boolean value - Closes the whole application if the wizard is rejected at the first run - Do not fail when the config directory doesn't exist - Set the wizard pixmap logo as LEAP's logo - Improve wizard checks - Make SRPRegister play nice with the CheckerThread --- src/leap/gui/wizard.py | 91 ++++++++++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 40 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 7dcc8dd6..bac74d1d 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -21,7 +21,8 @@ First run wizard import os import logging -from PySide import QtCore, QtGui +from PySide import QtGui +from functools import partial from ui_wizard import Ui_Wizard from leap.config.providerconfig import ProviderConfig @@ -45,15 +46,18 @@ class Wizard(QtGui.QWizard): SETUP_EIP_PAGE = 5 FINISH_PATH = 6 - WEAK_PASSWORDS = ("1234", "12345", "123456", + WEAK_PASSWORDS = ("123456", "qweasd", "qwerty", "password") - def __init__(self): + def __init__(self, checker): QtGui.QWizard.__init__(self) self.ui = Ui_Wizard() self.ui.setupUi(self) + self.setPixmap(QtGui.QWizard.LogoPixmap, + QtGui.QPixmap(":/images/leap-color-small.png")) + self.QUESTION_ICON = QtGui.QPixmap(":/images/Emblem-question.png") self.ERROR_ICON = QtGui.QPixmap(":/images/Dialog-error.png") self.OK_ICON = QtGui.QPixmap(":/images/Dialog-accept.png") @@ -94,6 +98,9 @@ class Wizard(QtGui.QWizard): self.ui.lblPassword.setEchoMode(QtGui.QLineEdit.Password) self.ui.lblPassword2.setEchoMode(QtGui.QLineEdit.Password) + self.ui.lnProvider.textChanged.connect( + self._enable_check) + self.ui.lblUser.returnPressed.connect( self._focus_password) self.ui.lblPassword.returnPressed.connect( @@ -105,15 +112,14 @@ class Wizard(QtGui.QWizard): self._username = None - def __del__(self): - self._provider_bootstrapper.set_should_quit() - self._eip_bootstrapper.set_should_quit() - self._provider_bootstrapper.wait() - self._eip_bootstrapper.wait() + self._checker_thread = checker def get_username(self): return self._username + def _enable_check(self, text): + self.ui.btnCheck.setEnabled(len(self.ui.lnProvider.text()) != 0) + def _focus_password(self): """ Focuses at the password lineedit for the registration page @@ -151,13 +157,13 @@ class Wizard(QtGui.QWizard): if message is not None and password != password2: message = "Passwords don't match" - if message is not None and len(password) < 4: + if message is None and len(password) < 6: message = "Password too short" - if message is not None and password in self.WEAK_PASSWORDS: + if message is None and password in self.WEAK_PASSWORDS: message = "Password too easy" - if message is not None and username == password: + if message is None and username == password: message = "Password equal to username" if message is not None: @@ -172,10 +178,6 @@ class Wizard(QtGui.QWizard): Performs the registration based on the values provided in the form """ self.ui.btnRegister.setEnabled(False) - # See the disabled button - while QtGui.QApplication.instance().hasPendingEvents(): - QtGui.QApplication.instance().processEvents() - self.button(QtGui.QWizard.NextButton).setFocus() username = self.ui.lblUser.text() password = self.ui.lblPassword.text() @@ -183,27 +185,32 @@ class Wizard(QtGui.QWizard): if self._basic_password_checks(username, password, password2): register = SRPRegister(provider_config=self._provider_config) - ok, req = register.register_user(username, password) - if ok: - self._set_register_status("User registration OK") - self._username = username - self.ui.lblPassword2.clearFocus() - # Detach this call to allow UI updates briefly - QtCore.QTimer.singleShot(1, - self.page(self.REGISTER_USER_PAGE) - .set_completed) - else: - print req.content - error_msg = "Unknown error" - try: - error_msg = req.json().get("errors").get("login")[0] - except: - logger.error("Unknown error: %r" % (req.content,)) - self._set_register_status(error_msg) - self.ui.btnRegister.setEnabled(True) + register.registration_finished.connect( + self._registration_finished) + self._checker_thread.add_checks( + [partial(register.register_user, username, password)]) + self._username = username + self._set_register_status("Starting registration...") else: self.ui.btnRegister.setEnabled(True) + def _registration_finished(self, ok, req): + if ok: + self._set_register_status("" + "User registration OK") + self.ui.lblPassword2.clearFocus() + self.page(self.REGISTER_USER_PAGE).set_completed() + self.button(QtGui.QWizard.BackButton).setEnabled(False) + else: + self._username = None + error_msg = "Unknown error" + try: + error_msg = req.json().get("errors").get("login")[0] + except: + logger.error("Unknown error: %r" % (req.content,)) + self._set_register_status(error_msg) + self.ui.btnRegister.setEnabled(True) + def _set_register_status(self, status): """ Sets the status label in the registration page to status @@ -222,12 +229,16 @@ class Wizard(QtGui.QWizard): Starts the checks for a given provider """ + if len(self.ui.lnProvider.text()) == 0: + return + self.ui.grpCheckProvider.setVisible(True) self.ui.btnCheck.setEnabled(False) self._domain = self.ui.lnProvider.text() - self._provider_bootstrapper.start() - self._provider_bootstrapper.run_provider_select_checks(self._domain) + self._provider_bootstrapper.run_provider_select_checks( + self._checker_thread, + self._domain) def _complete_task(self, data, label, complete=False, complete_page=-1): """ @@ -328,7 +339,6 @@ class Wizard(QtGui.QWizard): """ self._complete_task(data, self.ui.lblCheckApiCert, True, self.SETUP_PROVIDER_PAGE) - self._provider_bootstrapper.set_should_quit() def _download_eip_config(self, data): """ @@ -351,7 +361,6 @@ class Wizard(QtGui.QWizard): """ self._complete_task(data, self.ui.lblDownloadClientCert, True, self.SETUP_EIP_PAGE) - self._eip_bootstrapper.set_should_quit() def _current_id_changed(self, pageId): """ @@ -365,14 +374,16 @@ class Wizard(QtGui.QWizard): self.ui.lblNameResolution.setPixmap(self.QUESTION_ICON) self.ui.lblHTTPS.setPixmap(self.QUESTION_ICON) self.ui.lblProviderInfo.setPixmap(self.QUESTION_ICON) + self._enable_check("") if pageId == self.SETUP_PROVIDER_PAGE: self._provider_bootstrapper.\ - run_provider_setup_checks(self._provider_config) + run_provider_setup_checks(self._checker_thread, + self._provider_config) if pageId == self.SETUP_EIP_PAGE: - self._eip_bootstrapper.start() - self._eip_bootstrapper.run_eip_setup_checks(self._provider_config) + self._eip_bootstrapper.run_eip_setup_checks(self._checker_thread, + self._provider_config) if pageId == self.PRESENT_PROVIDER_PAGE: # TODO: get the right lang for these -- cgit v1.2.3 From 926575bc811e8382100695a3396da7191fb43eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Fri, 8 Mar 2013 13:15:38 -0300 Subject: Add translation support Also: - Make OpenVPN use a random port every time - Logout in parallel so the UI doesn't block - Add the WAIT status from OpenVPN to the mainwindow displays - Support non-unix sockets in the LinuxVPNLauncher --- src/leap/gui/wizard.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index bac74d1d..fa705645 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -21,7 +21,7 @@ First run wizard import os import logging -from PySide import QtGui +from PySide import QtCore, QtGui from functools import partial from ui_wizard import Ui_Wizard @@ -152,19 +152,20 @@ class Wizard(QtGui.QWizard): username.encode("ascii") password.encode("ascii") except: - message = u"Refrain from using non ASCII áñ characters" + message = self.tr(u"Refrain from using non " + u"ASCII characters like á, ñ, æ") if message is not None and password != password2: - message = "Passwords don't match" + message = self.tr("Passwords don't match") if message is None and len(password) < 6: - message = "Password too short" + message = self.tr("Password too short") if message is None and password in self.WEAK_PASSWORDS: - message = "Password too easy" + message = self.tr("Password too easy") if message is None and username == password: - message = "Password equal to username" + message = self.tr("Password equal to username") if message is not None: self._set_register_status(message) @@ -190,20 +191,20 @@ class Wizard(QtGui.QWizard): self._checker_thread.add_checks( [partial(register.register_user, username, password)]) self._username = username - self._set_register_status("Starting registration...") + self._set_register_status(self.tr("Starting registration...")) else: self.ui.btnRegister.setEnabled(True) def _registration_finished(self, ok, req): if ok: - self._set_register_status("" - "User registration OK") + self._set_register_status(self.tr("" + "User registration OK")) self.ui.lblPassword2.clearFocus() self.page(self.REGISTER_USER_PAGE).set_completed() self.button(QtGui.QWizard.BackButton).setEnabled(False) else: self._username = None - error_msg = "Unknown error" + error_msg = self.tr("Unknown error") try: error_msg = req.json().get("errors").get("login")[0] except: @@ -304,7 +305,7 @@ class Wizard(QtGui.QWizard): new_data = { self._provider_bootstrapper.PASSED_KEY: False, self._provider_bootstrapper.ERROR_KEY: - "Unable to load provider configuration" + self.tr("Unable to load provider configuration") } self._complete_task(new_data, self.ui.lblProviderInfo) @@ -387,13 +388,14 @@ class Wizard(QtGui.QWizard): if pageId == self.PRESENT_PROVIDER_PAGE: # TODO: get the right lang for these + lang = QtCore.QLocale.system().name() self.ui.lblProviderName.setText( "%s" % - (self._provider_config.get_name(),)) + (self._provider_config.get_name(lang=lang),)) self.ui.lblProviderURL.setText(self._provider_config.get_domain()) self.ui.lblProviderDesc.setText( "%s" % - (self._provider_config.get_description(),)) + (self._provider_config.get_description(lang=lang),)) self.ui.lblProviderPolicy.setText(self._provider_config .get_enrollment_policy()) -- cgit v1.2.3 From e4e5f35c3fc7ff02bc20a6ef7eaffae09f485061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Fri, 8 Mar 2013 14:24:05 -0300 Subject: Add keyring and username/password saving capabilities Also: - Fix translations in SRPAuth - Support non-ascii passwords - Make the server check if the characters are allowed, just check for easy passwords --- src/leap/gui/wizard.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index fa705645..72e791b3 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -148,13 +148,6 @@ class Wizard(QtGui.QWizard): """ message = None - try: - username.encode("ascii") - password.encode("ascii") - except: - message = self.tr(u"Refrain from using non " - u"ASCII characters like á, ñ, æ") - if message is not None and password != password2: message = self.tr("Passwords don't match") @@ -189,7 +182,9 @@ class Wizard(QtGui.QWizard): register.registration_finished.connect( self._registration_finished) self._checker_thread.add_checks( - [partial(register.register_user, username, password)]) + [partial(register.register_user, + username.encode("utf8"), + password.encode("utf8"))]) self._username = username self._set_register_status(self.tr("Starting registration...")) else: -- cgit v1.2.3 From 1580197229ce01ebdc6a655d2f5b67ca4b32da88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Mon, 11 Mar 2013 16:07:13 -0300 Subject: Auto login after the first run wizard if registered a new user Also add pyxdg as a dep --- src/leap/gui/wizard.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 72e791b3..f8a1f833 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -111,12 +111,16 @@ class Wizard(QtGui.QWizard): self._register) self._username = None + self._password = None self._checker_thread = checker def get_username(self): return self._username + def get_password(self): + return self._password + def _enable_check(self, text): self.ui.btnCheck.setEnabled(len(self.ui.lnProvider.text()) != 0) @@ -186,6 +190,7 @@ class Wizard(QtGui.QWizard): username.encode("utf8"), password.encode("utf8"))]) self._username = username + self._password = password self._set_register_status(self.tr("Starting registration...")) else: self.ui.btnRegister.setEnabled(True) @@ -199,6 +204,7 @@ class Wizard(QtGui.QWizard): self.button(QtGui.QWizard.BackButton).setEnabled(False) else: self._username = None + self._password = None error_msg = self.tr("Unknown error") try: error_msg = req.json().get("errors").get("login")[0] -- cgit v1.2.3 From 815315bdfb26aaee16a8482f1708bf3868019fd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Mon, 11 Mar 2013 17:03:00 -0300 Subject: Add user regex validator --- src/leap/gui/wizard.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index f8a1f833..ef4eafdb 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -49,6 +49,8 @@ class Wizard(QtGui.QWizard): WEAK_PASSWORDS = ("123456", "qweasd", "qwerty", "password") + BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$" + def __init__(self, checker): QtGui.QWizard.__init__(self) @@ -110,6 +112,10 @@ class Wizard(QtGui.QWizard): self.ui.btnRegister.clicked.connect( self._register) + usernameRe = QtCore.QRegExp(self.BARE_USERNAME_REGEX) + self.ui.lblUser.setValidator( + QtGui.QRegExpValidator(usernameRe, self)) + self._username = None self._password = None -- cgit v1.2.3 From b7325ef4527b90ed007a3f3ba7c61ff680076957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Mon, 11 Mar 2013 17:36:28 -0300 Subject: Provide more meaningful messages in the provider select page --- src/leap/gui/wizard.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index ef4eafdb..82deab0d 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -283,6 +283,11 @@ class Wizard(QtGui.QWizard): Sets the status for the name resolution check """ self._complete_task(data, self.ui.lblNameResolution) + status = "" + if not data[self._provider_bootstrapper.PASSED_KEY]: + status = self.tr("Non-existent " + "provider") + self.ui.lblProviderSelectStatus.setText(status) def _https_connection(self, data): """ @@ -292,6 +297,11 @@ class Wizard(QtGui.QWizard): Sets the status for the https connection check """ self._complete_task(data, self.ui.lblHTTPS) + status = "" + if not data[self._provider_bootstrapper.PASSED_KEY]: + status = self.tr("Provider does not " + "support HTTPS") + self.ui.lblProviderSelectStatus.setText(status) def _download_provider_info(self, data): """ @@ -316,6 +326,11 @@ class Wizard(QtGui.QWizard): } self._complete_task(new_data, self.ui.lblProviderInfo) + status = "" + if not data[self._provider_bootstrapper.PASSED_KEY]: + status = self.tr("Not a valid provider" + "") + self.ui.lblProviderSelectStatus.setText(status) self.ui.btnCheck.setEnabled(True) def _download_ca_cert(self, data): -- cgit v1.2.3 From 77c7e96e2aad4db223e4c7af53ec300d5472829b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Mon, 11 Mar 2013 18:13:55 -0300 Subject: Instantiate provider name in the wizard once its set --- src/leap/gui/wizard.py | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 82deab0d..70028581 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -129,6 +129,7 @@ class Wizard(QtGui.QWizard): def _enable_check(self, text): self.ui.btnCheck.setEnabled(len(self.ui.lnProvider.text()) != 0) + self._reset_provider_check() def _focus_password(self): """ @@ -228,6 +229,14 @@ class Wizard(QtGui.QWizard): """ self.ui.lblRegisterStatus.setText(status) + def _reset_provider_check(self): + self.ui.lblNameResolution.setPixmap(self.QUESTION_ICON) + self.ui.lblHTTPS.setPixmap(self.QUESTION_ICON) + self.ui.lblProviderInfo.setPixmap(self.QUESTION_ICON) + self._domain = None + self.button(QtGui.QWizard.NextButton).setEnabled(False) + self.page(self.SELECT_PROVIDER_PAGE).set_completed(False) + def _check_provider(self): """ SLOT @@ -242,6 +251,8 @@ class Wizard(QtGui.QWizard): self.ui.grpCheckProvider.setVisible(True) self.ui.btnCheck.setEnabled(False) + self.ui.lnProvider.setEnabled(False) + self.button(QtGui.QWizard.BackButton).clearFocus() self._domain = self.ui.lnProvider.text() self._provider_bootstrapper.run_provider_select_checks( @@ -284,10 +295,13 @@ class Wizard(QtGui.QWizard): """ self._complete_task(data, self.ui.lblNameResolution) status = "" - if not data[self._provider_bootstrapper.PASSED_KEY]: + passed = data[self._provider_bootstrapper.PASSED_KEY] + if not passed: status = self.tr("Non-existent " "provider") self.ui.lblProviderSelectStatus.setText(status) + self.ui.btnCheck.setEnabled(not passed) + self.ui.lnProvider.setEnabled(not passed) def _https_connection(self, data): """ @@ -298,10 +312,13 @@ class Wizard(QtGui.QWizard): """ self._complete_task(data, self.ui.lblHTTPS) status = "" - if not data[self._provider_bootstrapper.PASSED_KEY]: + passed = data[self._provider_bootstrapper.PASSED_KEY] + if not passed: status = self.tr("Provider does not " "support HTTPS") self.ui.lblProviderSelectStatus.setText(status) + self.ui.btnCheck.setEnabled(not passed) + self.ui.lnProvider.setEnabled(not passed) def _download_provider_info(self, data): """ @@ -332,6 +349,7 @@ class Wizard(QtGui.QWizard): "") self.ui.lblProviderSelectStatus.setText(status) self.ui.btnCheck.setEnabled(True) + self.ui.lnProvider.setEnabled(True) def _download_ca_cert(self, data): """ @@ -400,6 +418,10 @@ class Wizard(QtGui.QWizard): self._enable_check("") if pageId == self.SETUP_PROVIDER_PAGE: + self.page(pageId).setSubTitle(self.tr("Gathering configuration " + "options for %s") % + (self._provider_config + .get_name(),)) self._provider_bootstrapper.\ run_provider_setup_checks(self._checker_thread, self._provider_config) @@ -409,7 +431,10 @@ class Wizard(QtGui.QWizard): self._provider_config) if pageId == self.PRESENT_PROVIDER_PAGE: - # TODO: get the right lang for these + self.page(pageId).setSubTitle(self.tr("Services offered by %s") % + (self._provider_config + .get_name(),)) + lang = QtCore.QLocale.system().name() self.ui.lblProviderName.setText( "%s" % @@ -421,6 +446,12 @@ class Wizard(QtGui.QWizard): self.ui.lblProviderPolicy.setText(self._provider_config .get_enrollment_policy()) + if pageId == self.REGISTER_USER_PAGE: + self.page(pageId).setSubTitle(self.tr("Register a new user with " + "%s") % + (self._provider_config + .get_name(),)) + def nextId(self): """ Sets the next page id for the wizard based on wether the user -- cgit v1.2.3 From 453a4abc87f957a96fcf68fa0ad625d27c5e73e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Mon, 11 Mar 2013 18:22:19 -0300 Subject: Prepend username if the error message doesn't start with uppercase --- src/leap/gui/wizard.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 70028581..86e0dcfd 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -210,14 +210,17 @@ class Wizard(QtGui.QWizard): self.page(self.REGISTER_USER_PAGE).set_completed() self.button(QtGui.QWizard.BackButton).setEnabled(False) else: + old_username = self._username self._username = None self._password = None error_msg = self.tr("Unknown error") try: error_msg = req.json().get("errors").get("login")[0] + if not error_msg.istitle(): + error_msg = "%s %s" % (old_username, error_msg) + self._set_register_status(error_msg) except: logger.error("Unknown error: %r" % (req.content,)) - self._set_register_status(error_msg) self.ui.btnRegister.setEnabled(True) def _set_register_status(self, status): -- cgit v1.2.3 From 0a295be5fb396e67d7ce6800a647adbc69acee8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Mon, 11 Mar 2013 18:29:49 -0300 Subject: Set register page as commit page Also, document reset_provider_checks method, and add a reset for provider setup --- src/leap/gui/wizard.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 86e0dcfd..90ff7f1b 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -116,6 +116,8 @@ class Wizard(QtGui.QWizard): self.ui.lblUser.setValidator( QtGui.QRegExpValidator(usernameRe, self)) + self.page(self.REGISTER_USER_PAGE).setCommitPage(True) + self._username = None self._password = None @@ -233,6 +235,10 @@ class Wizard(QtGui.QWizard): self.ui.lblRegisterStatus.setText(status) def _reset_provider_check(self): + """ + Resets the UI for checking a provider. Also resets the domain + in this object. + """ self.ui.lblNameResolution.setPixmap(self.QUESTION_ICON) self.ui.lblHTTPS.setPixmap(self.QUESTION_ICON) self.ui.lblProviderInfo.setPixmap(self.QUESTION_ICON) @@ -240,6 +246,14 @@ class Wizard(QtGui.QWizard): self.button(QtGui.QWizard.NextButton).setEnabled(False) self.page(self.SELECT_PROVIDER_PAGE).set_completed(False) + def _reset_provider_setup(self): + """ + Resets the UI for setting up a provider. + """ + self.ui.lblDownloadCaCert.setPixmap(self.QUESTION_ICON) + self.ui.lblCheckCaFpr.setPixmap(self.QUESTION_ICON) + self.ui.lblCheckApiCert.setPixmap(self.QUESTION_ICON) + def _check_provider(self): """ SLOT @@ -421,6 +435,7 @@ class Wizard(QtGui.QWizard): self._enable_check("") if pageId == self.SETUP_PROVIDER_PAGE: + self._reset_provider_setup() self.page(pageId).setSubTitle(self.tr("Gathering configuration " "options for %s") % (self._provider_config -- cgit v1.2.3 From d28912e0a364ba5ed4201e87614ec94b29bd68bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Mon, 11 Mar 2013 18:48:08 -0300 Subject: Explicitly disable watermark pixmap in wizard --- src/leap/gui/wizard.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 90ff7f1b..3a604157 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -60,6 +60,8 @@ class Wizard(QtGui.QWizard): self.setPixmap(QtGui.QWizard.LogoPixmap, QtGui.QPixmap(":/images/leap-color-small.png")) + self.setPixmap(QtGui.QWizard.WatermarkPixmap, None) + self.QUESTION_ICON = QtGui.QPixmap(":/images/Emblem-question.png") self.ERROR_ICON = QtGui.QPixmap(":/images/Dialog-error.png") self.OK_ICON = QtGui.QPixmap(":/images/Dialog-accept.png") -- cgit v1.2.3 From 7752eb5fc11d6f5973c4aa7d575cabd0dbc979b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Mon, 11 Mar 2013 18:54:47 -0300 Subject: Don't display a ? icon when we are checking things in the wizard --- src/leap/gui/wizard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 3a604157..1aa0738b 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -62,7 +62,7 @@ class Wizard(QtGui.QWizard): self.setPixmap(QtGui.QWizard.WatermarkPixmap, None) - self.QUESTION_ICON = QtGui.QPixmap(":/images/Emblem-question.png") + self.QUESTION_ICON = None self.ERROR_ICON = QtGui.QPixmap(":/images/Dialog-error.png") self.OK_ICON = QtGui.QPixmap(":/images/Dialog-accept.png") -- cgit v1.2.3 From 908a726f0f10722ff8a875f24325ea1be6f293a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Tue, 12 Mar 2013 07:49:57 -0300 Subject: Fix passwords are equal check for the register page --- src/leap/gui/wizard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 1aa0738b..ff257601 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -163,7 +163,7 @@ class Wizard(QtGui.QWizard): """ message = None - if message is not None and password != password2: + if message is None and password != password2: message = self.tr("Passwords don't match") if message is None and len(password) < 6: -- cgit v1.2.3 From f838e880b7d694eee09c360ab737103a68e613aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Tue, 12 Mar 2013 11:55:04 -0300 Subject: Display ? icon for the test being run at the time Also, change button texts --- src/leap/gui/wizard.py | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index ff257601..5a66adbc 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -44,7 +44,7 @@ class Wizard(QtGui.QWizard): SETUP_PROVIDER_PAGE = 3 REGISTER_USER_PAGE = 4 SETUP_EIP_PAGE = 5 - FINISH_PATH = 6 + FINISH_PAGE = 6 WEAK_PASSWORDS = ("123456", "qweasd", "qwerty", "password") @@ -62,7 +62,7 @@ class Wizard(QtGui.QWizard): self.setPixmap(QtGui.QWizard.WatermarkPixmap, None) - self.QUESTION_ICON = None + self.QUESTION_ICON = QtGui.QPixmap(":/images/Emblem-question.png") self.ERROR_ICON = QtGui.QPixmap(":/images/Dialog-error.png") self.OK_ICON = QtGui.QPixmap(":/images/Dialog-accept.png") @@ -125,6 +125,11 @@ class Wizard(QtGui.QWizard): self._checker_thread = checker + self.page(self.REGISTER_USER_PAGE).setButtonText( + QtGui.QWizard.CommitButton, self.tr("&Next >")) + self.page(self.FINISH_PAGE).setButtonText( + QtGui.QWizard.FinishButton, self.tr("Connect")) + def get_username(self): return self._username @@ -241,9 +246,9 @@ class Wizard(QtGui.QWizard): Resets the UI for checking a provider. Also resets the domain in this object. """ - self.ui.lblNameResolution.setPixmap(self.QUESTION_ICON) - self.ui.lblHTTPS.setPixmap(self.QUESTION_ICON) - self.ui.lblProviderInfo.setPixmap(self.QUESTION_ICON) + self.ui.lblNameResolution.setPixmap(None) + self.ui.lblHTTPS.setPixmap(None) + self.ui.lblProviderInfo.setPixmap(None) self._domain = None self.button(QtGui.QWizard.NextButton).setEnabled(False) self.page(self.SELECT_PROVIDER_PAGE).set_completed(False) @@ -252,9 +257,16 @@ class Wizard(QtGui.QWizard): """ Resets the UI for setting up a provider. """ - self.ui.lblDownloadCaCert.setPixmap(self.QUESTION_ICON) - self.ui.lblCheckCaFpr.setPixmap(self.QUESTION_ICON) - self.ui.lblCheckApiCert.setPixmap(self.QUESTION_ICON) + self.ui.lblDownloadCaCert.setPixmap(None) + self.ui.lblCheckCaFpr.setPixmap(None) + self.ui.lblCheckApiCert.setPixmap(None) + + def _reset_eip_check(self): + """ + Resets the UI for the EIP check + """ + self.ui.lblDownloadEIPConfig.setPixmap(None) + self.ui.lblDownloadClientCert.setPixmap(None) def _check_provider(self): """ @@ -274,6 +286,7 @@ class Wizard(QtGui.QWizard): self.button(QtGui.QWizard.BackButton).clearFocus() self._domain = self.ui.lnProvider.text() + self.ui.lblNameResolution.setPixmap(self.QUESTION_ICON) self._provider_bootstrapper.run_provider_select_checks( self._checker_thread, self._domain) @@ -321,6 +334,7 @@ class Wizard(QtGui.QWizard): self.ui.lblProviderSelectStatus.setText(status) self.ui.btnCheck.setEnabled(not passed) self.ui.lnProvider.setEnabled(not passed) + self.ui.lblHTTPS.setPixmap(self.QUESTION_ICON) def _https_connection(self, data): """ @@ -338,6 +352,7 @@ class Wizard(QtGui.QWizard): self.ui.lblProviderSelectStatus.setText(status) self.ui.btnCheck.setEnabled(not passed) self.ui.lnProvider.setEnabled(not passed) + self.ui.lblProviderInfo.setPixmap(self.QUESTION_ICON) def _download_provider_info(self, data): """ @@ -378,6 +393,7 @@ class Wizard(QtGui.QWizard): Sets the status for the download of the CA certificate check """ self._complete_task(data, self.ui.lblDownloadCaCert) + self.ui.lblCheckCaFpr.setPixmap(self.QUESTION_ICON) def _check_ca_fingerprint(self, data): """ @@ -387,6 +403,7 @@ class Wizard(QtGui.QWizard): Sets the status for the CA fingerprint check """ self._complete_task(data, self.ui.lblCheckCaFpr) + self.ui.lblCheckApiCert.setPixmap(self.QUESTION_ICON) def _check_api_certificate(self, data): """ @@ -408,6 +425,7 @@ class Wizard(QtGui.QWizard): Sets the status for the EIP config downloading check """ self._complete_task(data, self.ui.lblDownloadEIPConfig) + self.ui.lblDownloadClientCert.setPixmap(self.QUESTION_ICON) def _download_client_certificate(self, data): """ @@ -430,10 +448,7 @@ class Wizard(QtGui.QWizard): Prepares the pages when they appear """ if pageId == self.SELECT_PROVIDER_PAGE: - self.ui.grpCheckProvider.setVisible(False) - self.ui.lblNameResolution.setPixmap(self.QUESTION_ICON) - self.ui.lblHTTPS.setPixmap(self.QUESTION_ICON) - self.ui.lblProviderInfo.setPixmap(self.QUESTION_ICON) + self._reset_provider_check() self._enable_check("") if pageId == self.SETUP_PROVIDER_PAGE: @@ -442,11 +457,14 @@ class Wizard(QtGui.QWizard): "options for %s") % (self._provider_config .get_name(),)) + self.ui.lblDownloadCaCert.setPixmap(self.QUESTION_ICON) self._provider_bootstrapper.\ run_provider_setup_checks(self._checker_thread, self._provider_config) if pageId == self.SETUP_EIP_PAGE: + self._reset_eip_check() + self.ui.lblDownloadEIPConfig.setPixmap(self.QUESTION_ICON) self._eip_bootstrapper.run_eip_setup_checks(self._checker_thread, self._provider_config) -- cgit v1.2.3 From 68c18135659351aac1c10aefadce431240ee6366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Tue, 12 Mar 2013 12:06:56 -0300 Subject: Reset error message when the provider changes --- src/leap/gui/wizard.py | 1 + 1 file changed, 1 insertion(+) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 5a66adbc..08e9cc6b 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -249,6 +249,7 @@ class Wizard(QtGui.QWizard): self.ui.lblNameResolution.setPixmap(None) self.ui.lblHTTPS.setPixmap(None) self.ui.lblProviderInfo.setPixmap(None) + self.ui.lblProviderSelectStatus.setText("") self._domain = None self.button(QtGui.QWizard.NextButton).setEnabled(False) self.page(self.SELECT_PROVIDER_PAGE).set_completed(False) -- cgit v1.2.3 From 605a456ffdb196211d239b6bdb56914b260c468f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Tue, 12 Mar 2013 12:11:34 -0300 Subject: Add watermark image --- src/leap/gui/wizard.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 08e9cc6b..202c6dc2 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -60,7 +60,8 @@ class Wizard(QtGui.QWizard): self.setPixmap(QtGui.QWizard.LogoPixmap, QtGui.QPixmap(":/images/leap-color-small.png")) - self.setPixmap(QtGui.QWizard.WatermarkPixmap, None) + self.setPixmap(QtGui.QWizard.WatermarkPixmap, + QtGui.QPixmap(":/images/watermark.png")) self.QUESTION_ICON = QtGui.QPixmap(":/images/Emblem-question.png") self.ERROR_ICON = QtGui.QPixmap(":/images/Dialog-error.png") -- cgit v1.2.3 From 70ab05982ab778b6d2e949b186b9932b90115a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Tue, 12 Mar 2013 12:54:49 -0300 Subject: Prepend https:// to the provider domain --- src/leap/gui/wizard.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 202c6dc2..de988153 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -479,7 +479,8 @@ class Wizard(QtGui.QWizard): self.ui.lblProviderName.setText( "%s" % (self._provider_config.get_name(lang=lang),)) - self.ui.lblProviderURL.setText(self._provider_config.get_domain()) + self.ui.lblProviderURL.setText( + "https://%s" % (self._provider_config.get_domain(),)) self.ui.lblProviderDesc.setText( "%s" % (self._provider_config.get_description(lang=lang),)) -- cgit v1.2.3 From 66464e6a2ea48d3dbafaa7c11b14478e7d34ab4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Tue, 12 Mar 2013 14:11:56 -0300 Subject: Login after register Also, mark error in red and bold in the register form --- src/leap/gui/wizard.py | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index de988153..1f0bc877 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -27,6 +27,7 @@ from functools import partial from ui_wizard import Ui_Wizard from leap.config.providerconfig import ProviderConfig from leap.crypto.srpregister import SRPRegister +from leap.crypto.srpauth import SRPAuth from leap.services.eip.providerbootstrapper import ProviderBootstrapper from leap.services.eip.eipbootstrapper import EIPBootstrapper @@ -60,9 +61,6 @@ class Wizard(QtGui.QWizard): self.setPixmap(QtGui.QWizard.LogoPixmap, QtGui.QPixmap(":/images/leap-color-small.png")) - self.setPixmap(QtGui.QWizard.WatermarkPixmap, - QtGui.QPixmap(":/images/watermark.png")) - self.QUESTION_ICON = QtGui.QPixmap(":/images/Emblem-question.png") self.ERROR_ICON = QtGui.QPixmap(":/images/Dialog-error.png") self.OK_ICON = QtGui.QPixmap(":/images/Dialog-accept.png") @@ -182,7 +180,7 @@ class Wizard(QtGui.QWizard): message = self.tr("Password equal to username") if message is not None: - self._set_register_status(message) + self._set_register_status(message, error=True) self._focus_password() return False @@ -215,10 +213,20 @@ class Wizard(QtGui.QWizard): def _registration_finished(self, ok, req): if ok: self._set_register_status(self.tr("" - "User registration OK")) + "User registration OK. " + "Logging in...")) self.ui.lblPassword2.clearFocus() - self.page(self.REGISTER_USER_PAGE).set_completed() - self.button(QtGui.QWizard.BackButton).setEnabled(False) + + srp_auth = SRPAuth(self._provider_config) + srp_auth.authentication_finished.connect( + self._authentication_finished) + + auth_partial = partial(srp_auth.authenticate, + self._username, + self._password) + self._checker_thread.add_checks([auth_partial]) + + self.ui.chkRemember.setEnabled(True) else: old_username = self._username self._username = None @@ -233,13 +241,33 @@ class Wizard(QtGui.QWizard): logger.error("Unknown error: %r" % (req.content,)) self.ui.btnRegister.setEnabled(True) - def _set_register_status(self, status): + def _authentication_finished(self, ok, message): + """ + SLOT + TRIGGER: srp_auth.authentication_finished + + Finish the authentication process as it comes from the + register form + """ + if ok: + self._set_register_status(self.tr("" + "Login succeeded!" + "")) + self.page(self.REGISTER_USER_PAGE).set_completed() + else: + self._set_register_status(message) + self.ui.btnRegister.setEnabled(True) + self.ui.chkRemember.setEnabled(False) + + def _set_register_status(self, status, error=False): """ Sets the status label in the registration page to status @param status: status message to display, can be HTML @type status: str """ + if error: + status = "%s" % (status,) self.ui.lblRegisterStatus.setText(status) def _reset_provider_check(self): -- cgit v1.2.3 From 364c6d5e9882f47ff5938f731641bc7509e32fc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Tue, 12 Mar 2013 17:12:20 -0300 Subject: Make the wizard provider setup only Also: - Add a way to enable/disable services for a provider - Run EIP only if it is enabled --- src/leap/gui/wizard.py | 128 +++++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 69 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 1f0bc877..83f64020 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -27,9 +27,7 @@ from functools import partial from ui_wizard import Ui_Wizard from leap.config.providerconfig import ProviderConfig from leap.crypto.srpregister import SRPRegister -from leap.crypto.srpauth import SRPAuth from leap.services.eip.providerbootstrapper import ProviderBootstrapper -from leap.services.eip.eipbootstrapper import EIPBootstrapper logger = logging.getLogger(__name__) @@ -44,7 +42,7 @@ class Wizard(QtGui.QWizard): PRESENT_PROVIDER_PAGE = 2 SETUP_PROVIDER_PAGE = 3 REGISTER_USER_PAGE = 4 - SETUP_EIP_PAGE = 5 + SERVICES_PAGE = 5 FINISH_PAGE = 6 WEAK_PASSWORDS = ("123456", "qweasd", "qwerty", @@ -65,6 +63,16 @@ class Wizard(QtGui.QWizard): self.ERROR_ICON = QtGui.QPixmap(":/images/Dialog-error.png") self.OK_ICON = QtGui.QPixmap(":/images/Dialog-accept.png") + # Correspondence for services and their name to display + self.SERVICE_DISPLAY = [ + self.tr("Encrypted Internet") + ] + self.SERVICE_CONFIG = [ + "openvpn" + ] + + self._selected_services = set() + self._show_register = False self.ui.grpCheckProvider.setVisible(False) @@ -86,13 +94,6 @@ class Wizard(QtGui.QWizard): self._provider_bootstrapper.check_api_certificate.connect( self._check_api_certificate) - self._eip_bootstrapper = EIPBootstrapper() - - self._eip_bootstrapper.download_config.connect( - self._download_eip_config) - self._eip_bootstrapper.download_client_certificate.connect( - self._download_client_certificate) - self._domain = None self._provider_config = ProviderConfig() @@ -135,6 +136,12 @@ class Wizard(QtGui.QWizard): def get_password(self): return self._password + def get_remember(self): + return self.ui.chkRemember.isChecked() + + def get_services(self): + return self._selected_services + def _enable_check(self, text): self.ui.btnCheck.setEnabled(len(self.ui.lnProvider.text()) != 0) self._reset_provider_check() @@ -214,19 +221,11 @@ class Wizard(QtGui.QWizard): if ok: self._set_register_status(self.tr("" "User registration OK. " - "Logging in...")) + "")) self.ui.lblPassword2.clearFocus() - - srp_auth = SRPAuth(self._provider_config) - srp_auth.authentication_finished.connect( - self._authentication_finished) - - auth_partial = partial(srp_auth.authenticate, - self._username, - self._password) - self._checker_thread.add_checks([auth_partial]) - self.ui.chkRemember.setEnabled(True) + + self.page(self.REGISTER_USER_PAGE).set_completed() else: old_username = self._username self._username = None @@ -241,24 +240,6 @@ class Wizard(QtGui.QWizard): logger.error("Unknown error: %r" % (req.content,)) self.ui.btnRegister.setEnabled(True) - def _authentication_finished(self, ok, message): - """ - SLOT - TRIGGER: srp_auth.authentication_finished - - Finish the authentication process as it comes from the - register form - """ - if ok: - self._set_register_status(self.tr("" - "Login succeeded!" - "")) - self.page(self.REGISTER_USER_PAGE).set_completed() - else: - self._set_register_status(message) - self.ui.btnRegister.setEnabled(True) - self.ui.chkRemember.setEnabled(False) - def _set_register_status(self, status, error=False): """ Sets the status label in the registration page to status @@ -291,13 +272,6 @@ class Wizard(QtGui.QWizard): self.ui.lblCheckCaFpr.setPixmap(None) self.ui.lblCheckApiCert.setPixmap(None) - def _reset_eip_check(self): - """ - Resets the UI for the EIP check - """ - self.ui.lblDownloadEIPConfig.setPixmap(None) - self.ui.lblDownloadClientCert.setPixmap(None) - def _check_provider(self): """ SLOT @@ -447,28 +421,47 @@ class Wizard(QtGui.QWizard): self._complete_task(data, self.ui.lblCheckApiCert, True, self.SETUP_PROVIDER_PAGE) - def _download_eip_config(self, data): + def _service_selection_changed(self, service, state): """ SLOT - TRIGGER: self._eip_bootstrapper.download_config + TRIGGER: service_checkbox.stateChanged + Adds the service to the state if the state is checked, removes + it otherwise + + @param service: service to handle + @type service: str + @param state: state of the checkbox + @type state: int + """ + if state == QtCore.Qt.Checked: + self._selected_services = \ + self._selected_services.union({service}) + else: + self._selected_services = \ + self._selected_services.difference({service}) - Sets the status for the EIP config downloading check + def _populate_services(self): """ - self._complete_task(data, self.ui.lblDownloadEIPConfig) - self.ui.lblDownloadClientCert.setPixmap(self.QUESTION_ICON) - - def _download_client_certificate(self, data): + Loads the services that the provider provides into the UI for + the user to enable or disable """ - SLOT - TRIGGER: self._provider_bootstrapper.download_client_certificate + self.ui.grpServices.setTitle( + self.tr("Services by %s") % + (self._provider_config.get_name(),)) - Sets the status for the download client certificate check and - completes the page if passed. Also stops the eip bootstrapper - thread since it's not needed from this point on unless the - check chain is restarted - """ - self._complete_task(data, self.ui.lblDownloadClientCert, - True, self.SETUP_EIP_PAGE) + for service in self._provider_config.get_services(): + try: + checkbox = QtGui.QCheckBox(self) + service_index = self.SERVICE_CONFIG.index(service) + checkbox.setText(self.SERVICE_DISPLAY[service_index]) + self.ui.serviceListLayout.addWidget(checkbox) + checkbox.stateChanged.connect( + partial(self._service_selection_changed, service)) + checkbox.setChecked(True) + except ValueError: + logger.error( + self.tr("Something went wrong while trying to " + "load service %s" % (service,))) def _current_id_changed(self, pageId): """ @@ -492,12 +485,6 @@ class Wizard(QtGui.QWizard): run_provider_setup_checks(self._checker_thread, self._provider_config) - if pageId == self.SETUP_EIP_PAGE: - self._reset_eip_check() - self.ui.lblDownloadEIPConfig.setPixmap(self.QUESTION_ICON) - self._eip_bootstrapper.run_eip_setup_checks(self._checker_thread, - self._provider_config) - if pageId == self.PRESENT_PROVIDER_PAGE: self.page(pageId).setSubTitle(self.tr("Services offered by %s") % (self._provider_config @@ -521,6 +508,9 @@ class Wizard(QtGui.QWizard): (self._provider_config .get_name(),)) + if pageId == self.SERVICES_PAGE: + self._populate_services() + def nextId(self): """ Sets the next page id for the wizard based on wether the user @@ -533,6 +523,6 @@ class Wizard(QtGui.QWizard): if self._show_register: return self.REGISTER_USER_PAGE else: - return self.SETUP_EIP_PAGE + return self.SERVICES_PAGE return QtGui.QWizard.nextId(self) -- cgit v1.2.3 From fdc1d749a859cefd325e1de712f90eba79d3f678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Wed, 13 Mar 2013 14:15:02 -0300 Subject: Display a more related error message for https wizard checks Differentiate between SSLError and other type of errors, so to its clear when the certificate fails and when the connection fails or other kind of problems --- src/leap/gui/wizard.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 83f64020..4e811fb9 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -351,8 +351,8 @@ class Wizard(QtGui.QWizard): status = "" passed = data[self._provider_bootstrapper.PASSED_KEY] if not passed: - status = self.tr("Provider does not " - "support HTTPS") + status = self.tr("%s") \ + % (data[self._provider_bootstrapper.ERROR_KEY]) self.ui.lblProviderSelectStatus.setText(status) self.ui.btnCheck.setEnabled(not passed) self.ui.lnProvider.setEnabled(not passed) -- cgit v1.2.3 From 74600d1c73cfc2f958f2c64d57ea8fb85d348424 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 20 Mar 2013 21:06:59 +0900 Subject: syntax fix for python 2.6 --- src/leap/gui/wizard.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 4e811fb9..dee3b230 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -435,10 +435,10 @@ class Wizard(QtGui.QWizard): """ if state == QtCore.Qt.Checked: self._selected_services = \ - self._selected_services.union({service}) + self._selected_services.union(set([service])) else: self._selected_services = \ - self._selected_services.difference({service}) + self._selected_services.difference(set([service])) def _populate_services(self): """ -- cgit v1.2.3 From 22342664951ac32756ceb7ade59ada90f92c8793 Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 4 Apr 2013 01:47:12 +0900 Subject: Several fixes in wizard Closes:#2061 o Rewording of setup steps in wizard, to make them more meaningful to the non-technical user. Closes: #2061 o Fix typo in wizard o Fix multiple drawing of services if going back o Make registration errors show in red o Add a warning if EIP service needs admin password. Addresses part of #2062 --- src/leap/gui/wizard.py | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index dee3b230..5742dfef 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -27,6 +27,7 @@ from functools import partial from ui_wizard import Ui_Wizard from leap.config.providerconfig import ProviderConfig from leap.crypto.srpregister import SRPRegister +from leap.util.privilege_policies import is_missing_policy_permissions from leap.services.eip.providerbootstrapper import ProviderBootstrapper logger = logging.getLogger(__name__) @@ -50,9 +51,11 @@ class Wizard(QtGui.QWizard): BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$" - def __init__(self, checker): + def __init__(self, checker, standalone=False): QtGui.QWizard.__init__(self) + self.standalone = standalone + self.ui = Ui_Wizard() self.ui.setupUi(self) @@ -64,14 +67,23 @@ class Wizard(QtGui.QWizard): self.OK_ICON = QtGui.QPixmap(":/images/Dialog-accept.png") # Correspondence for services and their name to display + # XXX need to add a note about "requires admin pass" if + # no polkit found. + EIP_LABEL = self.tr("Encrypted Internet") + + if self._is_need_eip_password_warning(): + EIP_LABEL += " " + self.tr( + "(will need admin pass to start)") + self.SERVICE_DISPLAY = [ - self.tr("Encrypted Internet") + EIP_LABEL ] self.SERVICE_CONFIG = [ "openvpn" ] self._selected_services = set() + self._shown_services = set() self._show_register = False @@ -235,7 +247,7 @@ class Wizard(QtGui.QWizard): error_msg = req.json().get("errors").get("login")[0] if not error_msg.istitle(): error_msg = "%s %s" % (old_username, error_msg) - self._set_register_status(error_msg) + self._set_register_status(error_msg, error=True) except: logger.error("Unknown error: %r" % (req.content,)) self.ui.btnRegister.setEnabled(True) @@ -451,13 +463,15 @@ class Wizard(QtGui.QWizard): for service in self._provider_config.get_services(): try: - checkbox = QtGui.QCheckBox(self) - service_index = self.SERVICE_CONFIG.index(service) - checkbox.setText(self.SERVICE_DISPLAY[service_index]) - self.ui.serviceListLayout.addWidget(checkbox) - checkbox.stateChanged.connect( - partial(self._service_selection_changed, service)) - checkbox.setChecked(True) + if service not in self._shown_services: + checkbox = QtGui.QCheckBox(self) + service_index = self.SERVICE_CONFIG.index(service) + checkbox.setText(self.SERVICE_DISPLAY[service_index]) + self.ui.serviceListLayout.addWidget(checkbox) + checkbox.stateChanged.connect( + partial(self._service_selection_changed, service)) + checkbox.setChecked(True) + self._shown_services.add(service) except ValueError: logger.error( self.tr("Something went wrong while trying to " @@ -486,7 +500,8 @@ class Wizard(QtGui.QWizard): self._provider_config) if pageId == self.PRESENT_PROVIDER_PAGE: - self.page(pageId).setSubTitle(self.tr("Services offered by %s") % + self.page(pageId).setSubTitle(self.tr("Description of services " + "offered by %s") % (self._provider_config .get_name(),)) @@ -499,6 +514,9 @@ class Wizard(QtGui.QWizard): self.ui.lblProviderDesc.setText( "%s" % (self._provider_config.get_description(lang=lang),)) + + self.ui.lblServicesOffered.setText(self._provider_config + .get_services_string()) self.ui.lblProviderPolicy.setText(self._provider_config .get_enrollment_policy()) @@ -511,6 +529,15 @@ class Wizard(QtGui.QWizard): if pageId == self.SERVICES_PAGE: self._populate_services() + def _is_need_eip_password_warning(self): + """ + Returns True if we need to add a warning about eip needing + administrative permissions to start. That can be either + because we are running in standalone mode, or because we could + not find the needed privilege escalation mechanisms being operative. + """ + return self.standalone or is_missing_policy_permissions() + def nextId(self): """ Sets the next page id for the wizard based on wether the user -- cgit v1.2.3 From e75fe6ffd58b067b3fc32196ad245d26a1287e99 Mon Sep 17 00:00:00 2001 From: kali Date: Tue, 9 Apr 2013 00:43:13 +0900 Subject: fixes as per review --- src/leap/gui/wizard.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 5742dfef..cc00039b 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -52,6 +52,15 @@ class Wizard(QtGui.QWizard): BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$" def __init__(self, checker, standalone=False): + """ + Constructor for the main Wizard. + + @param checker: Checker thread that the wizard should use. + @type checker: CheckerThread + @param standalone: If True, the application is running as standalone + and the wizard should display some messages according to this. + @type standalone: bool + """ QtGui.QWizard.__init__(self) self.standalone = standalone @@ -67,13 +76,11 @@ class Wizard(QtGui.QWizard): self.OK_ICON = QtGui.QPixmap(":/images/Dialog-accept.png") # Correspondence for services and their name to display - # XXX need to add a note about "requires admin pass" if - # no polkit found. EIP_LABEL = self.tr("Encrypted Internet") if self._is_need_eip_password_warning(): EIP_LABEL += " " + self.tr( - "(will need admin pass to start)") + "(
will need admin password to start
)") self.SERVICE_DISPLAY = [ EIP_LABEL -- cgit v1.2.3 From 785bdfaceb9f3d392f162dd818fea9098d9375a4 Mon Sep 17 00:00:00 2001 From: kali Date: Tue, 9 Apr 2013 20:17:03 +0900 Subject: fix markup typo s/br/b --- src/leap/gui/wizard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index cc00039b..7759b98d 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -80,7 +80,7 @@ class Wizard(QtGui.QWizard): if self._is_need_eip_password_warning(): EIP_LABEL += " " + self.tr( - "(
will need admin password to start
)") + "(will need admin password to start)") self.SERVICE_DISPLAY = [ EIP_LABEL -- cgit v1.2.3 From 4e4268af42e6d0bbf38e6027ca36d1b9f1bdda68 Mon Sep 17 00:00:00 2001 From: Tomas Touceda Date: Fri, 12 Apr 2013 14:05:29 -0300 Subject: Fix UI which was missbehaving - Remove the wrapping on checkboxes, since they don't understand HTML - Change the display of provider since providers with big names like dev.bitmask.net make the UI look bad. --- src/leap/gui/wizard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 7759b98d..4da4c815 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -80,7 +80,7 @@ class Wizard(QtGui.QWizard): if self._is_need_eip_password_warning(): EIP_LABEL += " " + self.tr( - "(will need admin password to start)") + "(will need admin password to start)") self.SERVICE_DISPLAY = [ EIP_LABEL -- cgit v1.2.3 From 1fbf6db1276c5bca41c4cfbcc90818d9605c1938 Mon Sep 17 00:00:00 2001 From: Tomas Touceda Date: Fri, 12 Apr 2013 14:07:15 -0300 Subject: Add --danger option to not validate the first hop of certificates This is intended to be used while testing, not in production --- src/leap/gui/wizard.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 4da4c815..33c3ed0c 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -51,7 +51,7 @@ class Wizard(QtGui.QWizard): BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$" - def __init__(self, checker, standalone=False): + def __init__(self, checker, standalone=False, bypass_checks=False): """ Constructor for the main Wizard. @@ -60,6 +60,9 @@ class Wizard(QtGui.QWizard): @param standalone: If True, the application is running as standalone and the wizard should display some messages according to this. @type standalone: bool + @param bypass_checks: Set to true if the app should bypass + first round of checks for CA certificates at bootstrap + @type bypass_checks: bool """ QtGui.QWizard.__init__(self) @@ -98,7 +101,7 @@ class Wizard(QtGui.QWizard): self.ui.btnCheck.clicked.connect(self._check_provider) self.ui.lnProvider.returnPressed.connect(self._check_provider) - self._provider_bootstrapper = ProviderBootstrapper() + self._provider_bootstrapper = ProviderBootstrapper(bypass_checks) self._provider_bootstrapper.name_resolution.connect( self._name_resolution) self._provider_bootstrapper.https_connection.connect( -- cgit v1.2.3 From 2dae2703fb8c2ae7e721ce83020c0dd10ff9ca33 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 3 May 2013 02:59:22 +0900 Subject: updated documentation * documentation reviewed after rewrite, ready for 0.2.1 * updated docstrings format to fit sphinx autodoc --- src/leap/gui/wizard.py | 56 +++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 33c3ed0c..ad45dd8c 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -55,14 +55,14 @@ class Wizard(QtGui.QWizard): """ Constructor for the main Wizard. - @param checker: Checker thread that the wizard should use. - @type checker: CheckerThread - @param standalone: If True, the application is running as standalone + :param checker: Checker thread that the wizard should use. + :type checker: CheckerThread + :param standalone: If True, the application is running as standalone and the wizard should display some messages according to this. - @type standalone: bool - @param bypass_checks: Set to true if the app should bypass + :type standalone: bool + :param bypass_checks: Set to true if the app should bypass first round of checks for CA certificates at bootstrap - @type bypass_checks: bool + :type bypass_checks: bool """ QtGui.QWizard.__init__(self) @@ -184,15 +184,15 @@ class Wizard(QtGui.QWizard): """ Performs basic password checks to avoid really easy passwords. - @param username: username provided at the registrarion form - @type username: str - @param password: password from the registration form - @type password: str - @param password2: second password from the registration form - @type password: str + :param username: username provided at the registrarion form + :type username: str + :param password: password from the registration form + :type password: str + :param password2: second password from the registration form + :type password: str - @return: returns True if all the checks pass, False otherwise - @rtype: bool + :return: returns True if all the checks pass, False otherwise + :rtype: bool """ message = None @@ -266,8 +266,8 @@ class Wizard(QtGui.QWizard): """ Sets the status label in the registration page to status - @param status: status message to display, can be HTML - @type status: str + :param status: status message to display, can be HTML + :type status: str """ if error: status = "%s" % (status,) @@ -321,17 +321,17 @@ class Wizard(QtGui.QWizard): """ Checks a task and completes a page if specified - @param data: data as it comes from the bootstrapper thread for + :param data: data as it comes from the bootstrapper thread for a specific check - @type data: dict - @param label: label that displays the status icon for a + :type data: dict + :param label: label that displays the status icon for a specific check that corresponds to the data - @type label: QtGui.QLabel - @param complete: if True, it completes the page specified, + :type label: QtGui.QLabel + :param complete: if True, it completes the page specified, which must be of type WizardPage - @type complete: bool - @param complete_page: page id to complete - @type complete_page: int + :type complete: bool + :param complete_page: page id to complete + :type complete_page: int """ passed = data[self._provider_bootstrapper.PASSED_KEY] error = data[self._provider_bootstrapper.ERROR_KEY] @@ -450,10 +450,10 @@ class Wizard(QtGui.QWizard): Adds the service to the state if the state is checked, removes it otherwise - @param service: service to handle - @type service: str - @param state: state of the checkbox - @type state: int + :param service: service to handle + :type service: str + :param state: state of the checkbox + :type state: int """ if state == QtCore.Qt.Checked: self._selected_services = \ -- cgit v1.2.3 From 4e201329042d43c8d281c5737d3d5f6f8e2bf67f Mon Sep 17 00:00:00 2001 From: Tomas Touceda Date: Fri, 10 May 2013 17:01:11 -0300 Subject: Add support for requests<1.0.0 --- src/leap/gui/wizard.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index ad45dd8c..713383a6 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -20,6 +20,7 @@ First run wizard """ import os import logging +import json from PySide import QtCore, QtGui from functools import partial @@ -28,6 +29,7 @@ from ui_wizard import Ui_Wizard from leap.config.providerconfig import ProviderConfig from leap.crypto.srpregister import SRPRegister from leap.util.privilege_policies import is_missing_policy_permissions +from leap.util.request_helpers import get_content from leap.services.eip.providerbootstrapper import ProviderBootstrapper logger = logging.getLogger(__name__) @@ -254,7 +256,9 @@ class Wizard(QtGui.QWizard): self._password = None error_msg = self.tr("Unknown error") try: - error_msg = req.json().get("errors").get("login")[0] + content, _ = get_content(req) + json_content = json.loads(content) + error_msg = json_content.get("errors").get("login")[0] if not error_msg.istitle(): error_msg = "%s %s" % (old_username, error_msg) self._set_register_status(error_msg, error=True) -- cgit v1.2.3 From 4c726c1531abfe288604eaa4c1d347e85bed81eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Mon, 3 Jun 2013 15:02:41 -0300 Subject: Use Twisted's deferToThread and Deferreds to handle parallel tasks This removes CheckerThread --- src/leap/gui/wizard.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 713383a6..552ace50 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -24,6 +24,7 @@ import json from PySide import QtCore, QtGui from functools import partial +from twisted.internet import threads from ui_wizard import Ui_Wizard from leap.config.providerconfig import ProviderConfig @@ -53,12 +54,10 @@ class Wizard(QtGui.QWizard): BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$" - def __init__(self, checker, standalone=False, bypass_checks=False): + def __init__(self, standalone=False, bypass_checks=False): """ Constructor for the main Wizard. - :param checker: Checker thread that the wizard should use. - :type checker: CheckerThread :param standalone: If True, the application is running as standalone and the wizard should display some messages according to this. :type standalone: bool @@ -82,16 +81,19 @@ class Wizard(QtGui.QWizard): # Correspondence for services and their name to display EIP_LABEL = self.tr("Encrypted Internet") + MX_LABEL = self.tr("Encrypted Mail") if self._is_need_eip_password_warning(): EIP_LABEL += " " + self.tr( "(will need admin password to start)") self.SERVICE_DISPLAY = [ - EIP_LABEL + EIP_LABEL, + MX_LABEL ] self.SERVICE_CONFIG = [ - "openvpn" + "openvpn", + "mx" ] self._selected_services = set() @@ -147,8 +149,6 @@ class Wizard(QtGui.QWizard): self._username = None self._password = None - self._checker_thread = checker - self.page(self.REGISTER_USER_PAGE).setButtonText( QtGui.QWizard.CommitButton, self.tr("&Next >")) self.page(self.FINISH_PAGE).setButtonText( @@ -231,10 +231,12 @@ class Wizard(QtGui.QWizard): register = SRPRegister(provider_config=self._provider_config) register.registration_finished.connect( self._registration_finished) - self._checker_thread.add_checks( - [partial(register.register_user, - username.encode("utf8"), - password.encode("utf8"))]) + + threads.deferToThread( + partial(register.register_user, + username.encode("utf8"), + password.encode("utf8"))) + self._username = username self._password = password self._set_register_status(self.tr("Starting registration...")) @@ -318,7 +320,6 @@ class Wizard(QtGui.QWizard): self.ui.lblNameResolution.setPixmap(self.QUESTION_ICON) self._provider_bootstrapper.run_provider_select_checks( - self._checker_thread, self._domain) def _complete_task(self, data, label, complete=False, complete_page=-1): @@ -510,8 +511,7 @@ class Wizard(QtGui.QWizard): .get_name(),)) self.ui.lblDownloadCaCert.setPixmap(self.QUESTION_ICON) self._provider_bootstrapper.\ - run_provider_setup_checks(self._checker_thread, - self._provider_config) + run_provider_setup_checks(self._provider_config) if pageId == self.PRESENT_PROVIDER_PAGE: self.page(pageId).setSubTitle(self.tr("Description of services " -- cgit v1.2.3 From cc247f63441a8d434bc509ea2764f7969ad47fec Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 5 Jun 2013 10:12:22 -0300 Subject: Improve wizard for registration process --- src/leap/gui/wizard.py | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 552ace50..405752ef 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -243,15 +243,42 @@ class Wizard(QtGui.QWizard): else: self.ui.btnRegister.setEnabled(True) + def _set_registration_fields_visibility(self, visible): + """ + This method hides the username and password labels and inputboxes. + + :param visible: sets the visibility of the widgets + True: widgets are visible or False: are not + :type visible: bool + """ + # username and password inputs + self.ui.lblUser.setVisible(visible) + self.ui.lblPassword.setVisible(visible) + self.ui.lblPassword2.setVisible(visible) + + # username and password labels + self.ui.label_15.setVisible(visible) + self.ui.label_16.setVisible(visible) + self.ui.label_17.setVisible(visible) + + # register button + self.ui.btnRegister.setVisible(visible) + def _registration_finished(self, ok, req): if ok: - self._set_register_status(self.tr("" - "User registration OK. " - "")) + user_domain = self._username + "@" + self._domain + message = "

" + message += self.tr("User %s successfully registered.") % ( + user_domain, ) + message += "

" + self._set_register_status(message) + self.ui.lblPassword2.clearFocus() + self._set_registration_fields_visibility(False) self.ui.chkRemember.setEnabled(True) self.page(self.REGISTER_USER_PAGE).set_completed() + self.button(QtGui.QWizard.BackButton).setEnabled(False) else: old_username = self._username self._username = None -- cgit v1.2.3 From 5b5eef87e8eb41916f2f5657287ac1ad8f0bbfeb Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 5 Jun 2013 11:52:37 -0300 Subject: Select the configured domain in the providers box --- src/leap/gui/wizard.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 405752ef..ea4474ae 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -154,6 +154,9 @@ class Wizard(QtGui.QWizard): self.page(self.FINISH_PAGE).setButtonText( QtGui.QWizard.FinishButton, self.tr("Connect")) + def get_domain(self): + return self._domain + def get_username(self): return self._username -- cgit v1.2.3 From 2456b456ae72c7c56c03aaf131aef7a2e7ad011b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Wed, 5 Jun 2013 11:58:17 -0300 Subject: Only show question mark when the previous check passed --- src/leap/gui/wizard.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 405752ef..3cf1765b 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -389,10 +389,11 @@ class Wizard(QtGui.QWizard): if not passed: status = self.tr("Non-existent " "provider") + else: + self.ui.lblHTTPS.setPixmap(self.QUESTION_ICON) self.ui.lblProviderSelectStatus.setText(status) self.ui.btnCheck.setEnabled(not passed) self.ui.lnProvider.setEnabled(not passed) - self.ui.lblHTTPS.setPixmap(self.QUESTION_ICON) def _https_connection(self, data): """ @@ -408,9 +409,10 @@ class Wizard(QtGui.QWizard): status = self.tr("%s") \ % (data[self._provider_bootstrapper.ERROR_KEY]) self.ui.lblProviderSelectStatus.setText(status) + else: + self.ui.lblProviderInfo.setPixmap(self.QUESTION_ICON) self.ui.btnCheck.setEnabled(not passed) self.ui.lnProvider.setEnabled(not passed) - self.ui.lblProviderInfo.setPixmap(self.QUESTION_ICON) def _download_provider_info(self, data): """ @@ -451,7 +453,9 @@ class Wizard(QtGui.QWizard): Sets the status for the download of the CA certificate check """ self._complete_task(data, self.ui.lblDownloadCaCert) - self.ui.lblCheckCaFpr.setPixmap(self.QUESTION_ICON) + passed = data[self._provider_bootstrapper.PASSED_KEY] + if passed: + self.ui.lblCheckCaFpr.setPixmap(self.QUESTION_ICON) def _check_ca_fingerprint(self, data): """ @@ -461,7 +465,9 @@ class Wizard(QtGui.QWizard): Sets the status for the CA fingerprint check """ self._complete_task(data, self.ui.lblCheckCaFpr) - self.ui.lblCheckApiCert.setPixmap(self.QUESTION_ICON) + passed = data[self._provider_bootstrapper.PASSED_KEY] + if passed: + self.ui.lblCheckApiCert.setPixmap(self.QUESTION_ICON) def _check_api_certificate(self, data): """ -- cgit v1.2.3 From 6a01913bffc10a96c6c3acfa6b8b410d6eb27661 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 7 Jun 2013 15:05:01 -0300 Subject: Wizard ui improvements Hide 'remember' checkbox until the registration succeeds. Use word wrapping to the successful registration message, to be more long-username-friendly. --- src/leap/gui/wizard.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 8c5ea2a0..d03427db 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -278,6 +278,9 @@ class Wizard(QtGui.QWizard): self.ui.lblPassword2.clearFocus() self._set_registration_fields_visibility(False) + + # Allow the user to remember his password + self.ui.chkRemember.setVisible(True) self.ui.chkRemember.setEnabled(True) self.page(self.REGISTER_USER_PAGE).set_completed() @@ -575,6 +578,7 @@ class Wizard(QtGui.QWizard): "%s") % (self._provider_config .get_name(),)) + self.ui.chkRemember.setVisible(False) if pageId == self.SERVICES_PAGE: self._populate_services() -- cgit v1.2.3 From 8c9e05eb498f24f9e580d6dd13cb6834612f9530 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 19 Jun 2013 11:04:03 -0300 Subject: Temporary removal of enrollment policy in UI. Only hide the components. Closes issue #2922. --- src/leap/gui/wizard.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index d03427db..897bf94f 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -154,6 +154,11 @@ class Wizard(QtGui.QWizard): self.page(self.FINISH_PAGE).setButtonText( QtGui.QWizard.FinishButton, self.tr("Connect")) + # XXX: Temporary removal for enrollment policy + # https://leap.se/code/issues/2922 + self.ui.label_12.setVisible(False) + self.ui.lblProviderPolicy.setVisible(False) + def get_domain(self): return self._domain -- cgit v1.2.3 From 4a422c92ae83453807074afca6c2f038823e296f Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 20 Jun 2013 10:26:46 +0900 Subject: hide mx until we integrate it Closes: #2938 --- src/leap/gui/wizard.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 897bf94f..066a7db3 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -32,6 +32,7 @@ from leap.crypto.srpregister import SRPRegister from leap.util.privilege_policies import is_missing_policy_permissions from leap.util.request_helpers import get_content from leap.services.eip.providerbootstrapper import ProviderBootstrapper +from leap.services import get_available logger = logging.getLogger(__name__) @@ -514,13 +515,16 @@ class Wizard(QtGui.QWizard): def _populate_services(self): """ Loads the services that the provider provides into the UI for - the user to enable or disable + the user to enable or disable. """ self.ui.grpServices.setTitle( self.tr("Services by %s") % (self._provider_config.get_name(),)) - for service in self._provider_config.get_services(): + services = get_available( + self._provider_config.get_services()) + + for service in services: try: if service not in self._shown_services: checkbox = QtGui.QCheckBox(self) -- cgit v1.2.3 From 440f2036e36985e9536644b28af0e62cea8704eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Fri, 21 Jun 2013 15:31:24 -0300 Subject: Disable remembering when not using a proper keyring backend --- src/leap/gui/wizard.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 066a7db3..34eba84c 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -31,6 +31,7 @@ from leap.config.providerconfig import ProviderConfig from leap.crypto.srpregister import SRPRegister from leap.util.privilege_policies import is_missing_policy_permissions from leap.util.request_helpers import get_content +from leap.util.keyring_helpers import has_keyring from leap.services.eip.providerbootstrapper import ProviderBootstrapper from leap.services import get_available @@ -170,7 +171,7 @@ class Wizard(QtGui.QWizard): return self._password def get_remember(self): - return self.ui.chkRemember.isChecked() + return has_keyring() and self.ui.chkRemember.isChecked() def get_services(self): return self._selected_services @@ -286,8 +287,9 @@ class Wizard(QtGui.QWizard): self._set_registration_fields_visibility(False) # Allow the user to remember his password - self.ui.chkRemember.setVisible(True) - self.ui.chkRemember.setEnabled(True) + if has_keyring(): + self.ui.chkRemember.setVisible(True) + self.ui.chkRemember.setEnabled(True) self.page(self.REGISTER_USER_PAGE).set_completed() self.button(QtGui.QWizard.BackButton).setEnabled(False) -- cgit v1.2.3 From 8ff98b63c077af25fb58dc73750e7765c35ce2f0 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 28 Jun 2013 10:59:56 -0300 Subject: Bugfix: Update available/supported implementation. Closes bug #3032. --- src/leap/gui/wizard.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/gui/wizard.py') diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index 34eba84c..b29250c8 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -33,7 +33,7 @@ from leap.util.privilege_policies import is_missing_policy_permissions from leap.util.request_helpers import get_content from leap.util.keyring_helpers import has_keyring from leap.services.eip.providerbootstrapper import ProviderBootstrapper -from leap.services import get_available +from leap.services import get_supported logger = logging.getLogger(__name__) @@ -523,7 +523,7 @@ class Wizard(QtGui.QWizard): self.tr("Services by %s") % (self._provider_config.get_name(),)) - services = get_available( + services = get_supported( self._provider_config.get_services()) for service in services: -- cgit v1.2.3