Rework import keys pass confirmation

- Show button as loading until the import is done, *then* close popup
- Remove the dedicated backend password checking function, we can use
  import_keys() directly now
- Handle all the possible errors that could be thrown from python
This commit is contained in:
miruka 2019-11-30 05:50:56 -04:00
parent a09e811e56
commit 3b2ab048fb
4 changed files with 33 additions and 47 deletions

View File

@ -141,29 +141,6 @@ class Backend:
return nio.Api.mxc_to_http(mxc) return nio.Api.mxc_to_http(mxc)
@staticmethod
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, passphrase)
return True
except OSError as err: # XXX raise
return (f"{file_path}: {err.strerror}", True)
except ValueError as err: # XXX raise
if str(err).startswith("HMAC check failed"):
return False
return (str(err), False)
async def load_settings(self) -> tuple: async def load_settings(self) -> tuple:
from .config_files import Theme from .config_files import Theme
settings = await self.ui_settings.read() settings = await self.ui_settings.read()

View File

@ -12,6 +12,8 @@ HFileDialogOpener {
} }
// This is used for the LogoutPopup to know when the export is done
// so it can close
signal done() signal done()

View File

@ -11,24 +11,10 @@ HFileDialogOpener {
} }
signal done()
property string userId: "" property string userId: ""
property bool importing: false property bool importing: false
function importKeys(file, passphrase) {
importing = true
let path = file.toString().replace(/^file:\/\//, "")
py.callClientCoro(userId, "import_keys", [path, passphrase], () => {
importing = false
done()
})
}
PasswordPopup { PasswordPopup {
id: importPasswordPopup id: importPasswordPopup
details.text: qsTr( details.text: qsTr(
@ -36,16 +22,38 @@ HFileDialogOpener {
) )
okText: qsTr("Import") okText: qsTr("Import")
onAcceptedPasswordChanged: importKeys(file, acceptedPassword)
property url file: "" property url file: ""
function verifyPassword(pass, callback) { function verifyPassword(pass, callback) {
py.callCoro( importing = true
"check_exported_keys_passphrase", let path = file.toString().replace(/^file:\/\//, "")
[file.toString().replace(/^file:\/\//, ""), pass],
callback py.callClientCoro(userId, "import_keys", [path, pass], () => {
importing = false
callback(true)
}, (type, args) => {
callback(
type === "EncryptionError" ?
false :
type === "ValueError" ?
qsTr("Invalid file format") :
type === "FileNotFoundError" ?
qsTr("This file doesn't exist") :
type === "IsADirectoryError" ?
qsTr("A folder was given, expecting a file") :
type === "PermissionError" ?
qsTr("No permission to read this file") :
qsTr("Unknown error: %1 - %2").arg(type).arg(args)
) )
})
} }
} }
} }

View File

@ -25,8 +25,8 @@ BoxPopup {
function verifyPassword(pass, callback) { function verifyPassword(pass, callback) {
// Can be reimplemented when using this component. // Can be reimplemented when using this component.
// Pass to the callback true on success, false on invalid password, or // Pass to the callback true on success, false on invalid password,
// a [error message, translated] array for any other error. // or a custom error message string.
callback(true) callback(true)
} }
@ -46,8 +46,7 @@ BoxPopup {
} else if (result === false) { } else if (result === false) {
passwordValid = false passwordValid = false
} else { } else {
let [msg, translated] = result errorMessage.text = result
errorMessage.text = translated ? msg : qsTr(msg)
} }
button.loading = false button.loading = false