From f65c0176ba7a57129180efc851728082d187ee97 Mon Sep 17 00:00:00 2001 From: miruka Date: Tue, 27 Aug 2019 23:51:38 -0400 Subject: [PATCH] Better error handling and fixes for key import --- TODO.md | 2 + src/python/backend.py | 22 +++++++++-- src/qml/Base/HPasswordPopup.qml | 48 ++++++++++++++++++------ src/qml/Pages/EditAccount/Encryption.qml | 13 ++++--- 4 files changed, 64 insertions(+), 21 deletions(-) diff --git a/TODO.md b/TODO.md index 1cf54d97..b1491fcd 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,5 @@ +rename hinterfacebox +translated arg for avatar upload and login - Refactoring - Banners diff --git a/src/python/backend.py b/src/python/backend.py index 436df170..dcdf0684 100644 --- a/src/python/backend.py +++ b/src/python/backend.py @@ -128,12 +128,26 @@ class Backend: @staticmethod - def check_exported_keys_password(file_path: str, password: str) -> bool: + async def check_exported_keys_passphrase(file_path: str, passphrase: str, + ) -> Union[bool, Tuple[str, bool]]: + """Check if the exported keys file can be decrypted with passphrase. + + Returns True on success, False is the passphrase is invalid, or + an (error_message, error_is_translated) tuple if another error occured. + """ + try: - nio.crypto.key_export.decrypt_and_read(file_path, password) + nio.crypto.key_export.decrypt_and_read(file_path, passphrase) return True - except (FileNotFoundError, ValueError): - return False + + except OSError as err: + return (f"{file_path}: {err.strerror}", True) + + except ValueError as err: + if str(err).startswith("HMAC check failed"): + return False + + return (str(err), False) async def load_settings(self) -> tuple: diff --git a/src/qml/Base/HPasswordPopup.qml b/src/qml/Base/HPasswordPopup.qml index 8050fa31..45e5a753 100644 --- a/src/qml/Base/HPasswordPopup.qml +++ b/src/qml/Base/HPasswordPopup.qml @@ -9,9 +9,14 @@ Popup { modal: true padding: 0 + onAboutToShow: { + acceptedPassword = "" + passwordValid = null + okClicked = false + errorMessage.text = "" + } onOpened: passwordField.forceActiveFocus() - property bool validateWhileTyping: false property string acceptedPassword: "" @@ -22,9 +27,11 @@ Popup { property alias field: passwordField - function verifyPassword(pass) { - // Implement me when using this component - return false + function verifyPassword(pass, callback) { + // Implement this function when using this component. + // Return true on success, false on invalid password, or + // a [error message, translated] array for any other error. + return ["Verification not implemented", false] } @@ -56,15 +63,20 @@ Popup { okClicked = true button.loading = true - if (verifyPassword(password)) { - passwordValid = true - popup.acceptedPassword = password - popup.close() - } else { - passwordValid = false - } + verifyPassword(password, result => { + if (result === true) { + passwordValid = true + popup.acceptedPassword = password + popup.close() + } else if (result === false) { + passwordValid = false + } else { + let [msg, translated] = result + errorMessage.text = translated ? msg : qsTr(msg) + } - button.loading = false + button.loading = false + }) }, cancel: button => { popup.close() }, }) @@ -105,5 +117,17 @@ Popup { Behavior on Layout.preferredWidth { HNumberAnimation {} } } } + + HLabel { + id: errorMessage + wrapMode: Text.Wrap + color: theme.colors.errorText + + visible: Layout.maximumHeight > 0 + Layout.maximumHeight: text ? implicitHeight : 0 + Behavior on Layout.maximumHeight { HNumberAnimation {} } + + Layout.fillWidth: true + } } } diff --git a/src/qml/Pages/EditAccount/Encryption.qml b/src/qml/Pages/EditAccount/Encryption.qml index bcbb097e..7e27cab1 100644 --- a/src/qml/Pages/EditAccount/Encryption.qml +++ b/src/qml/Pages/EditAccount/Encryption.qml @@ -8,10 +8,11 @@ HColumnLayout { function importKeys(file, passphrase) { importButton.loading = true - let path = Qt.resolvedUrl(file).replace(/^file:\/\//, "") + let path = file.toString().replace(/^file:\/\//, "") py.callClientCoro( editAccount.userId, "import_keys", [path, passphrase], () => { + print("import done") importButton.loading = false } ) @@ -63,9 +64,11 @@ HColumnLayout { HPasswordPopup { property url file: "" - function verifyPassword(pass) { - return py.callSync( - "check_exported_keys_password", [file.toString(), pass] + function verifyPassword(pass, callback) { + return py.callCoro( + "check_exported_keys_passphrase", + [file.toString().replace(/^file:\/\//, ""), pass], + callback ) } @@ -73,6 +76,6 @@ HColumnLayout { label.text: qsTr( "Please enter the passphrase that was used to protect this file:" ) - onAcceptedPasswordChanged: importKeys(file, password) + onAcceptedPasswordChanged: importKeys(file, acceptedPassword) } }