diff --git a/src/app/modules/shared_modules/keycard_popup/controller.nim b/src/app/modules/shared_modules/keycard_popup/controller.nim index 2f6c294c77..8061fbfd2a 100644 --- a/src/app/modules/shared_modules/keycard_popup/controller.nim +++ b/src/app/modules/shared_modules/keycard_popup/controller.nim @@ -391,22 +391,22 @@ proc verifyPassword*(self: Controller, password: string): bool = return return self.accountsService.verifyPassword(password) -proc convertSelectedKeyPairToKeycardAccount*(self: Controller, keycardUid: string, password: string) = +proc convertRegularProfileKeypairToKeycard*(self: Controller, keycardUid: string, currentPassword: string) = if not serviceApplicable(self.accountsService): return let acc = self.accountsService.createAccountFromMnemonic(self.getSeedPhrase(), includeEncryption = true) singletonInstance.localAccountSettings.setStoreToKeychainValue(LS_VALUE_NOT_NOW) - self.accountsService.convertToKeycardAccount(keycardUid, currentPassword = password, + self.accountsService.convertRegularProfileKeypairToKeycard(keycardUid, currentPassword = currentPassword, newPassword = acc.derivedAccounts.encryption.publicKey) +proc convertKeycardProfileKeypairToRegular*(self: Controller, seedPhrase: string, currentPassword: string, newPassword: string) = + if not serviceApplicable(self.accountsService): + return + self.accountsService.convertKeycardProfileKeypairToRegular(seedPhrase, currentPassword, newPassword) + proc getConvertingProfileSuccess*(self: Controller): bool = return self.tmpConvertingProfileSuccess -proc getLoggedInAccount*(self: Controller): AccountDto = - if not serviceApplicable(self.accountsService): - return - return self.accountsService.getLoggedInAccount() - proc getCurrentKeycardServiceFlow*(self: Controller): keycard_service.KCSFlowType = if not serviceApplicable(self.keycardService): return @@ -804,14 +804,12 @@ proc tryToObtainDataFromKeychain*(self: Controller) = return if(not singletonInstance.userProfile.getUsingBiometricLogin()): return - let loggedInAccount = self.getLoggedInAccount() - self.keychainService.tryToObtainData(loggedInAccount.keyUid) + self.keychainService.tryToObtainData(singletonInstance.userProfile.getKeyUid()) proc tryToStoreDataToKeychain*(self: Controller, password: string) = if not serviceApplicable(self.keychainService): return - let loggedInAccount = self.getLoggedInAccount() - self.keychainService.storeData(loggedInAccount.keyUid, password) + self.keychainService.storeData(singletonInstance.userProfile.getKeyUid(), password) proc getCurrencyFormat*(self: Controller, symbol: string): CurrencyFormatDto = return self.walletAccountService.getCurrencyFormat(symbol) diff --git a/src/app/modules/shared_modules/keycard_popup/internal/migrating_keypair_to_keycard_state.nim b/src/app/modules/shared_modules/keycard_popup/internal/migrating_keypair_to_keycard_state.nim index 6b21a76d53..b5584f5854 100644 --- a/src/app/modules/shared_modules/keycard_popup/internal/migrating_keypair_to_keycard_state.nim +++ b/src/app/modules/shared_modules/keycard_popup/internal/migrating_keypair_to_keycard_state.nim @@ -27,7 +27,7 @@ proc doMigration(self: MigratingKeypairToKeycardState, controller: Controller) = proc doConversion(self: MigratingKeypairToKeycardState, controller: Controller) = let password = controller.getPassword() let selectedKeyPairDto = controller.getSelectedKeyPairDto() - controller.convertSelectedKeyPairToKeycardAccount(selectedKeyPairDto.keycardUid, password) + controller.convertRegularProfileKeypairToKeycard(selectedKeyPairDto.keycardUid, password) proc runStoreMetadataFlow(self: MigratingKeypairToKeycardState, controller: Controller) = let selectedKeyPairDto = controller.getSelectedKeyPairDto() diff --git a/src/app/modules/startup/controller.nim b/src/app/modules/startup/controller.nim index 246b3665bf..61b7ead310 100644 --- a/src/app/modules/startup/controller.nim +++ b/src/app/modules/startup/controller.nim @@ -188,6 +188,11 @@ proc init*(self: Controller) = self.delegate.emitAccountLoginError(args.error) self.connectionIds.add(handlerId) + handlerId = self.events.onWithUUID(SIGNAL_CONVERTING_PROFILE_KEYPAIR) do(e: Args): + let args = ResultArgs(e) + self.delegate.onProfileConverted(args.success) + self.connectionIds.add(handlerId) + proc shouldStartWithOnboardingScreen*(self: Controller): bool = return self.accountsService.openedAccounts().len == 0 @@ -512,9 +517,11 @@ proc loginAccountKeycardUsingSeedPhrase*(self: Controller, storeToKeychain: bool if(error.len > 0): self.delegate.emitAccountLoginError(error) -proc convertToRegularAccount*(self: Controller): string = +proc convertKeycardProfileKeypairToRegular*(self: Controller) = let acc = self.accountsService.createAccountFromMnemonic(self.getSeedPhrase(), includeEncryption = true) - return self.accountsService.convertToRegularAccount(self.getSeedPhrase(), acc.derivedAccounts.encryption.publicKey, self.getPassword()) + self.accountsService.convertKeycardProfileKeypairToRegular(self.getSeedPhrase(), acc.derivedAccounts.encryption.publicKey, + self.getPassword()) + proc getKeyUidForSeedPhrase*(self: Controller, seedPhrase: string): string = let acc = self.accountsService.createAccountFromMnemonic(seedPhrase) return acc.keyUid diff --git a/src/app/modules/startup/io_interface.nim b/src/app/modules/startup/io_interface.nim index 52a3e2f986..ab88403773 100644 --- a/src/app/modules/startup/io_interface.nim +++ b/src/app/modules/startup/io_interface.nim @@ -115,6 +115,9 @@ method setSelectedLoginAccount*(self: AccessInterface, item: login_acc_item.Item method onNodeLogin*(self: AccessInterface, error: string) {.base.} = raise newException(ValueError, "No implementation available") +method onProfileConverted*(self: AccessInterface, success: bool) {.base.} = + raise newException(ValueError, "No implementation available") + method emitAccountLoginError*(self: AccessInterface, error: string) {.base.} = raise newException(ValueError, "No implementation available") diff --git a/src/app/modules/startup/module.nim b/src/app/modules/startup/module.nim index c3a6147525..316f897f32 100644 --- a/src/app/modules/startup/module.nim +++ b/src/app/modules/startup/module.nim @@ -375,7 +375,7 @@ method startAppAfterDelay*[T](self: Module[T]) = if not self.view.fetchingDataModel().allMessagesLoaded(): let currStateObj = self.view.currentStartupStateObj() if currStateObj.isNil: - error "cannot determine current startup state" + error "cannot determine current startup state", procName="startAppAfterDelay" quit() # quit the app self.view.setCurrentStartupState(newProfileFetchingState(currStateObj.flowType(), nil)) self.moveToStartupState() @@ -392,10 +392,22 @@ proc logoutAndDisplayError[T](self: Module[T], error: string, errType: StartupEr self.moveToStartupState() self.emitAccountLoginError(error) +method onProfileConverted*[T](self: Module[T], success: bool) = + if not success: + self.logoutAndDisplayError("", StartupErrorType.ConvertToRegularAccError) + return + let currStateObj = self.view.currentStartupStateObj() + if currStateObj.isNil: + error "cannot determine current startup state", procName="onProfileConverted" + quit() # quit the app + self.delegate.logout() + self.moveToStartupState() + self.view.setCurrentStartupState(newLoginKeycardConvertedToRegularAccountState(currStateObj.flowType(), nil)) + method onNodeLogin*[T](self: Module[T], error: string) = let currStateObj = self.view.currentStartupStateObj() if currStateObj.isNil: - error "cannot determine current startup state" + error "cannot determine current startup state", procName="onNodeLogin" quit() # quit the app if error.len == 0: @@ -409,12 +421,8 @@ method onNodeLogin*[T](self: Module[T], error: string) = self.logoutAndDisplayError(err, StartupErrorType.UnknownType) return elif currStateObj.flowType() == state.FlowType.LostKeycardConvertToRegularAccount: - let err = self.controller.convertToRegularAccount() - if err.len > 0: - self.logoutAndDisplayError(err, StartupErrorType.ConvertToRegularAccError) - return - self.delegate.logout() - self.view.setCurrentStartupState(newLoginKeycardConvertedToRegularAccountState(currStateObj.flowType(), nil)) + self.controller.convertKeycardProfileKeypairToRegular() + return else: let err = self.delegate.userLoggedIn() if err.len > 0: diff --git a/src/app_service/service/accounts/async_tasks.nim b/src/app_service/service/accounts/async_tasks.nim index 910453a2d8..a57affb64a 100644 --- a/src/app_service/service/accounts/async_tasks.nim +++ b/src/app_service/service/accounts/async_tasks.nim @@ -1,23 +1,67 @@ ################################################# -# Async convert profile keypair +# Async convert profile keypair from regular to keycard keypair ################################################# type - ConvertToKeycardAccountTaskArg* = ref object of QObjectTaskArg - accountDataJson: JsonNode - settingsJson: JsonNode + ConvertRegularProfileKeypairToKeycardTaskArg* = ref object of QObjectTaskArg + accountDataJson: JsonNode + settingsJson: JsonNode keycardUid: string hashedCurrentPassword: string newPassword: string -const convertToKeycardAccountTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = - let arg = decode[ConvertToKeycardAccountTaskArg](argEncoded) +const convertRegularProfileKeypairToKeycardTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = + let arg = decode[ConvertRegularProfileKeypairToKeycardTaskArg](argEncoded) try: - let response = status_account.convertToKeycardAccount(arg.accountDataJson, arg.settingsJson, + var response: RpcResponse[JsonNode] + if arg.accountDataJson.isNil or arg.settingsJson.isNil: + response.error.message = "at least one json object is not prepared well" + error "error: ", errDescription=response.error.message + elif arg.keycardUid.len == 0: + response.error.message = "provided keycardUid must not be empty" + error "error: ", errDescription=response.error.message + elif arg.hashedCurrentPassword.len == 0: + response.error.message = "provided password must not be empty" + error "error: ", errDescription=response.error.message + elif arg.newPassword.len == 0: + response.error.message = "provided new password must not be empty" + error "error: ", errDescription=response.error.message + else: + response = status_account.convertRegularProfileKeypairToKeycard(arg.accountDataJson, arg.settingsJson, arg.keycardUid, arg.hashedCurrentPassword, arg.newPassword) arg.finish(response) except Exception as e: - error "error converting profile keypair: ", message = e.msg + error "error converting profile keypair to keycard keypair: ", errDescription=e.msg + arg.finish("") + +################################################# +# Async convert profile keypair from keycard to regular keypair +################################################# + +type + ConvertKeycardProfileKeypairToRegularTaskArg* = ref object of QObjectTaskArg + mnemonic: string + currentPassword: string + hashedNewPassword: string + +const convertKeycardProfileKeypairToRegularTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = + let arg = decode[ConvertKeycardProfileKeypairToRegularTaskArg](argEncoded) + try: + var response: RpcResponse[JsonNode] + if arg.mnemonic.len == 0: + response.error.message = "provided mnemonic must not be empty" + error "error: ", errDescription=response.error.message + elif arg.currentPassword.len == 0: + response.error.message = "provided password must not be empty" + error "error: ", errDescription=response.error.message + elif arg.hashedNewPassword.len == 0: + response.error.message = "provided new password must not be empty" + error "error: ", errDescription=response.error.message + else: + response = status_account.convertKeycardProfileKeypairToRegular(arg.mnemonic, arg.currentPassword, arg.hashedNewPassword) + arg.finish(response) + except Exception as e: + error "error converting profile keypair to regular keypair: ", errDescription=e.msg arg.finish("") diff --git a/src/app_service/service/accounts/service.nim b/src/app_service/service/accounts/service.nim index e55d1de5e5..0f962c6bef 100644 --- a/src/app_service/service/accounts/service.nim +++ b/src/app_service/service/accounts/service.nim @@ -723,7 +723,7 @@ QtObject: error "error: ", procName="loginAccountKeycard", errName = e.name, errDesription = e.msg return e.msg - proc convertToKeycardAccount*(self: Service, keycardUid, currentPassword: string, newPassword: string) = + proc convertRegularProfileKeypairToKeycard*(self: Service, keycardUid, currentPassword: string, newPassword: string) = var accountDataJson = %* { "key-uid": self.getLoggedInAccount().keyUid, "kdfIterations": KDF_ITERATIONS @@ -732,16 +732,11 @@ QtObject: self.addKeycardDetails(keycardUid, settingsJson, accountDataJson) - if(accountDataJson.isNil or settingsJson.isNil): - let description = "at least one json object is not prepared well" - error "error: ", procName="convertToKeycardAccount", errDesription = description - return - let hashedCurrentPassword = hashPassword(currentPassword) - let arg = ConvertToKeycardAccountTaskArg( - tptr: cast[ByteAddress](convertToKeycardAccountTask), + let arg = ConvertRegularProfileKeypairToKeycardTaskArg( + tptr: cast[ByteAddress](convertRegularProfileKeypairToKeycardTask), vptr: cast[ByteAddress](self.vptr), - slot: "onConvertToKeycardAccount", + slot: "onConvertRegularProfileKeypairToKeycard", accountDataJson: accountDataJson, settingsJson: settingsJson, keycardUid: keycardUid, @@ -752,7 +747,7 @@ QtObject: DB_BLOCKED_DUE_TO_PROFILE_MIGRATION = true self.threadpool.start(arg) - proc onConvertToKeycardAccount*(self: Service, response: string) {.slot.} = + proc onConvertRegularProfileKeypairToKeycard*(self: Service, response: string) {.slot.} = var result = false try: let rpcResponse = Json.decode(response, RpcResponse[JsonNode]) @@ -761,24 +756,38 @@ QtObject: if(errMsg.len == 0): result = true else: - error "error: ", procName="convertToKeycardAccount", errDesription = errMsg + error "error: ", procName="onConvertRegularProfileKeypairToKeycard", errDesription = errMsg except Exception as e: - error "error handilng migrated keypair response", errDesription=e.msg + error "error handilng migrated keypair response", procName="onConvertRegularProfileKeypairToKeycard", errDesription=e.msg self.events.emit(SIGNAL_CONVERTING_PROFILE_KEYPAIR, ResultArgs(success: result)) - proc convertToRegularAccount*(self: Service, mnemonic: string, currentPassword: string, newPassword: string): string = - let hashedPassword = hashPassword(newPassword) + proc convertKeycardProfileKeypairToRegular*(self: Service, mnemonic: string, currentPassword: string, newPassword: string) = + let hashedNewPassword = hashPassword(newPassword) + let arg = ConvertKeycardProfileKeypairToRegularTaskArg( + tptr: cast[ByteAddress](convertKeycardProfileKeypairToRegularTask), + vptr: cast[ByteAddress](self.vptr), + slot: "onConvertKeycardProfileKeypairToRegular", + mnemonic: mnemonic, + currentPassword: currentPassword, + hashedNewPassword: hashedNewPassword + ) + + DB_BLOCKED_DUE_TO_PROFILE_MIGRATION = true + self.threadpool.start(arg) + + proc onConvertKeycardProfileKeypairToRegular*(self: Service, response: string) {.slot.} = + var result = false try: - let response = status_account.convertToRegularAccount(mnemonic, currentPassword, hashedPassword) - var errMsg = "" - if(response.result.contains("error")): - errMsg = response.result["error"].getStr - if errMsg.len > 0: - error "error: ", procName="convertToRegularAccount", errDesription = errMsg - return errMsg + let rpcResponse = Json.decode(response, RpcResponse[JsonNode]) + if(rpcResponse.result.contains("error")): + let errMsg = rpcResponse.result["error"].getStr + if(errMsg.len == 0): + result = true + else: + error "error: ", procName="onConvertKeycardProfileKeypairToRegular", errDesription = errMsg except Exception as e: - error "error converting to regular account: ", message = e.msg - return e.msg + error "error handilng migrated keypair response", procName="onConvertKeycardProfileKeypairToRegular", errDesription=e.msg + self.events.emit(SIGNAL_CONVERTING_PROFILE_KEYPAIR, ResultArgs(success: result)) proc verifyPassword*(self: Service, password: string): bool = try: diff --git a/src/backend/accounts.nim b/src/backend/accounts.nim index dde4a37443..652268bb6c 100644 --- a/src/backend/accounts.nim +++ b/src/backend/accounts.nim @@ -370,22 +370,22 @@ proc saveAccountAndLoginWithKeycard*(chatKey, password: string, account, subacco error "error doing rpc request", methodName = "saveAccountAndLogin", exception=e.msg raise newException(RpcException, e.msg) -proc convertToKeycardAccount*(account: JsonNode, settings: JsonNode, keycardUid: string, password: string, newPassword: string): +proc convertRegularProfileKeypairToKeycard*(account: JsonNode, settings: JsonNode, keycardUid: string, password: string, newPassword: string): RpcResponse[JsonNode] {.raises: [Exception].} = try: let response = status_go.convertToKeycardAccount($account, $settings, keycardUid, password, newPassword) result.result = Json.decode(response, JsonNode) except RpcException as e: - error "error doing rpc request", methodName = "convertToKeycardAccount", exception=e.msg + error "error doing rpc request", methodName = "convertRegularProfileKeypairToKeycard", exception=e.msg raise newException(RpcException, e.msg) -proc convertToRegularAccount*(mnemonic: string, currPassword: string, newPassword: string): +proc convertKeycardProfileKeypairToRegular*(mnemonic: string, currPassword: string, newPassword: string): RpcResponse[JsonNode] {.raises: [Exception].} = try: let response = status_go.convertToRegularAccount(mnemonic, currPassword, newPassword) result.result = Json.decode(response, JsonNode) except RpcException as e: - error "error doing rpc request", methodName = "convertToRegularAccount", exception=e.msg + error "error doing rpc request", methodName = "convertKeycardProfileKeypairToRegular", exception=e.msg raise newException(RpcException, e.msg) proc login*(name, keyUid: string, kdfIterations: int, hashedPassword, thumbnail, large: string, nodeCfgObj: string):