fix(re-encryption): make sure loading screen is shown when re-encrypting

Fixes #10352

Adds a 1 second timer before re-encrypting, to make sure the loading screen is shown before it starts, since it can freeze.
This commit is contained in:
Jonathan Rainville 2023-04-18 14:17:53 -04:00
parent 435b08501b
commit 10b8d38844
2 changed files with 68 additions and 19 deletions

View File

@ -175,6 +175,11 @@ proc init*(self: Controller) =
self.delegate.onReencryptionProcessStarted() self.delegate.onReencryptionProcessStarted()
self.connectionIds.add(handlerId) self.connectionIds.add(handlerId)
handlerId = self.events.onWithUUID(SIGNAL_LOGIN_ERROR) do(e: Args):
let args = LoginErrorArgs(e)
self.delegate.emitAccountLoginError(args.error)
self.connectionIds.add(handlerId)
proc shouldStartWithOnboardingScreen*(self: Controller): bool = proc shouldStartWithOnboardingScreen*(self: Controller): bool =
return self.accountsService.openedAccounts().len == 0 return self.accountsService.openedAccounts().len == 0
@ -440,9 +445,7 @@ proc isSelectedAccountAKeycardAccount*(self: Controller): bool =
proc login*(self: Controller) = proc login*(self: Controller) =
self.delegate.moveToLoadingAppState() self.delegate.moveToLoadingAppState()
let selectedAccount = self.getSelectedLoginAccount() let selectedAccount = self.getSelectedLoginAccount()
let error = self.accountsService.login(selectedAccount, self.tmpPassword) self.accountsService.login(selectedAccount, self.tmpPassword)
if(error.len > 0):
self.delegate.emitAccountLoginError(error)
proc loginAccountKeycard*(self: Controller, storeToKeychainValue: string, syncWalletAfterLogin = false) = proc loginAccountKeycard*(self: Controller, storeToKeychainValue: string, syncWalletAfterLogin = false) =
if syncWalletAfterLogin: if syncWalletAfterLogin:

View File

@ -38,16 +38,21 @@ let TEST_PEER_ENR = getEnv("TEST_PEER_ENR").string
const SIGNAL_CONVERTING_PROFILE_KEYPAIR* = "convertingProfileKeypair" const SIGNAL_CONVERTING_PROFILE_KEYPAIR* = "convertingProfileKeypair"
const SIGNAL_DERIVED_ADDRESSES_FROM_NOT_IMPORTED_MNEMONIC_FETCHED* = "derivedAddressesFromNotImportedMnemonicFetched" const SIGNAL_DERIVED_ADDRESSES_FROM_NOT_IMPORTED_MNEMONIC_FETCHED* = "derivedAddressesFromNotImportedMnemonicFetched"
const SIGNAL_REENCRYPTION_PROCESS_STARTED* = "reencryptionProcessStarted" const SIGNAL_REENCRYPTION_PROCESS_STARTED* = "reencryptionProcessStarted"
const SIGNAL_LOGIN_ERROR* = "errorWhileLogin"
type ResultArgs* = ref object of Args type ResultArgs* = ref object of Args
success*: bool success*: bool
type LoginErrorArgs* = ref object of Args
error*: string
type DerivedAddressesFromNotImportedMnemonicArgs* = ref object of Args type DerivedAddressesFromNotImportedMnemonicArgs* = ref object of Args
error*: string error*: string
derivations*: Table[string, DerivedAccountDetails] derivations*: Table[string, DerivedAccountDetails]
include utils include utils
include async_tasks include async_tasks
include ../../common/async_tasks
QtObject: QtObject:
type Service* = ref object of QObject type Service* = ref object of QObject
@ -60,6 +65,12 @@ QtObject:
importedAccount: GeneratedAccountDto importedAccount: GeneratedAccountDto
keyStoreDir: string keyStoreDir: string
defaultWalletEmoji: string defaultWalletEmoji: string
tmpAccount: AccountDto
tmpPassword: string
tmpHashedPassword: string
tmpThumbnailImage: string
tmpLargeImage: string
tmpNodeCfg: JsonNode
proc delete*(self: Service) = proc delete*(self: Service) =
self.QObject.delete self.QObject.delete
@ -595,7 +606,19 @@ QtObject:
except Exception as e: except Exception as e:
error "error: ", procName="verifyDatabasePassword", errName = e.name, errDesription = e.msg error "error: ", procName="verifyDatabasePassword", errName = e.name, errDesription = e.msg
proc login*(self: Service, account: AccountDto, password: string): string = proc doLogin(self: Service, account: AccountDto, hashedPassword, thumbnailImage, largeImage: string, nodeCfg: JsonNode) =
let response = status_account.login(
account.name, account.keyUid, account.kdfIterations, hashedPassword, thumbnailImage, largeImage, $nodeCfg
)
if response.result{"error"}.getStr != "":
self.events.emit(SIGNAL_LOGIN_ERROR, LoginErrorArgs(error: response.result{"error"}.getStr))
return
debug "Account logged in"
self.loggedInAccount = account
self.setLocalAccountSettingsFile()
proc login*(self: Service, account: AccountDto, password: string) =
try: try:
let hashedPassword = hashPassword(password) let hashedPassword = hashPassword(password)
var thumbnailImage: string var thumbnailImage: string
@ -669,26 +692,49 @@ QtObject:
"DiscV5BootstrapNodes": @[] "DiscV5BootstrapNodes": @[]
} }
let isOldHashPassword = self.verifyDatabasePassword(account.keyUid, hashPassword(password, lower=false)) let isOldHashPassword = self.verifyDatabasePassword(account.keyUid, hashPassword(password, lower=false))
if isOldHashPassword: if isOldHashPassword:
# Start loading screen with warning
self.events.emit(SIGNAL_REENCRYPTION_PROCESS_STARTED, Args()) self.events.emit(SIGNAL_REENCRYPTION_PROCESS_STARTED, Args())
discard status_privacy.lowerDatabasePassword(account.keyUid, password)
let response = status_account.login( # Save tmp properties so that we can login after the timer
account.name, account.keyUid, account.kdfIterations, hashedPassword, thumbnailImage, largeImage, $nodeCfg self.tmpAccount = account
) self.tmpPassword = password
if response.result{"error"}.getStr == "": self.tmpHashedPassword = hashedPassword
debug "Account logged in" self.tmpThumbnailImage = thumbnailImage
self.loggedInAccount = account self.tmpLargeImage = largeImage
self.setLocalAccountSettingsFile() self.tmpNodeCfg = nodeCfg
return ""
return response.result{"error"}.getStr # Start a 1 second timer for the loading screen to appear
let arg = TimerTaskArg(
tptr: cast[ByteAddress](timerTask),
vptr: cast[ByteAddress](self.vptr),
slot: "onWaitForReencryptionTimeout",
timeoutInMilliseconds: 1000
)
self.threadpool.start(arg)
return
self.doLogin(account, hashedPassword, thumbnailImage, largeImage, nodeCfg)
except Exception as e: except Exception as e:
error "error: ", procName="login", errName = e.name, errDesription = e.msg error "error: ", procName="login", errName = e.name, errDesription = e.msg
return e.msg self.events.emit(SIGNAL_LOGIN_ERROR, LoginErrorArgs(error: e.msg))
proc onWaitForReencryptionTimeout(self: Service, response: string) {.slot.} =
# Reencryption (can freeze and take up to 30 minutes)
let pwd = self.tmpPassword
self.tmpPassword = "" # Clear the password from memory as fast as possible
discard status_privacy.lowerDatabasePassword(self.tmpAccount.keyUid, pwd)
# Normal login after reencryption
self.doLogin(self.tmpAccount, self.tmpHashedPassword, self.tmpThumbnailImage, self.tmpLargeImage, self.tmpNodeCfg)
# Clear out the temp properties
self.tmpAccount = AccountDto()
self.tmpHashedPassword = ""
self.tmpThumbnailImage = ""
self.tmpLargeImage = ""
self.tmpNodeCfg = JsonNode()
proc loginAccountKeycard*(self: Service, accToBeLoggedIn: AccountDto, keycardData: KeycardEvent): string = proc loginAccountKeycard*(self: Service, accToBeLoggedIn: AccountDto, keycardData: KeycardEvent): string =
try: try: