feat(@desktop/wallet): account interaction - stop using a keycard for profile keypair - handling on paired devices
Part 4 of: #11737
This commit is contained in:
parent
f11b2b1e86
commit
b22b632b2d
|
@ -478,6 +478,8 @@ proc finishAppLoading*(self: AppController) =
|
|||
self.startupModule.delete
|
||||
self.startupModule = nil
|
||||
|
||||
self.mainModule.checkAndPerformProfileMigrationIfNeeded()
|
||||
|
||||
proc logout*(self: AppController) =
|
||||
self.generalService.logout()
|
||||
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
import chronicles, stint, tables
|
||||
import ../../global/app_sections_config as conf
|
||||
import ../../global/global_singleton
|
||||
import ../../global/app_signals
|
||||
import ../../core/signals/types as signal_types
|
||||
import ../../core/eventemitter
|
||||
import ../../core/notifications/notifications_manager
|
||||
import ../../../app_service/common/types
|
||||
import ../../../app_service/service/settings/service as settings_service
|
||||
import ../../../app_service/service/node_configuration/service as node_configuration_service
|
||||
import ../../../app_service/service/accounts/service as accounts_service
|
||||
import ../../../app_service/service/chat/service as chat_service
|
||||
import ../../../app_service/service/community/service as community_service
|
||||
import ../../../app_service/service/contacts/service as contacts_service
|
||||
import ../../../app_service/service/message/service as message_service
|
||||
import ../../../app_service/service/gif/service as gif_service
|
||||
import ../../../app_service/service/mailservers/service as mailservers_service
|
||||
import ../../../app_service/service/privacy/service as privacy_service
|
||||
import ../../../app_service/service/node/service as node_service
|
||||
import ../../../app_service/service/community_tokens/service as community_tokens_service
|
||||
import ../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../app_service/service/token/service as token_service
|
||||
import ../../../app_service/service/network/service as networks_service
|
||||
import ../../../app_service/service/visual_identity/service as procs_from_visual_identity_service
|
||||
import app/global/app_sections_config as conf
|
||||
import app/global/global_singleton
|
||||
import app/global/app_signals
|
||||
import app/core/signals/types as signal_types
|
||||
import app/core/eventemitter
|
||||
import app/core/notifications/notifications_manager
|
||||
import app_service/common/types
|
||||
import app_service/service/settings/service as settings_service
|
||||
import app_service/service/node_configuration/service as node_configuration_service
|
||||
import app_service/service/accounts/service as accounts_service
|
||||
import app_service/service/chat/service as chat_service
|
||||
import app_service/service/community/service as community_service
|
||||
import app_service/service/contacts/service as contacts_service
|
||||
import app_service/service/message/service as message_service
|
||||
import app_service/service/gif/service as gif_service
|
||||
import app_service/service/mailservers/service as mailservers_service
|
||||
import app_service/service/privacy/service as privacy_service
|
||||
import app_service/service/node/service as node_service
|
||||
import app_service/service/community_tokens/service as community_tokens_service
|
||||
import app_service/service/wallet_account/service as wallet_account_service
|
||||
import app_service/service/token/service as token_service
|
||||
import app_service/service/network/service as networks_service
|
||||
import app_service/service/visual_identity/service as procs_from_visual_identity_service
|
||||
|
||||
import ../../../app_service/service/community_tokens/community_collectible_owner
|
||||
import app_service/service/community_tokens/community_collectible_owner
|
||||
|
||||
import io_interface
|
||||
import ../shared_modules/keycard_popup/io_interface as keycard_shared_module
|
||||
|
@ -31,8 +31,9 @@ import ../shared_modules/keycard_popup/io_interface as keycard_shared_module
|
|||
logScope:
|
||||
topics = "main-module-controller"
|
||||
|
||||
const UNIQUE_MAIN_MODULE_IDENTIFIER* = "MainModule"
|
||||
const UNIQUE_MAIN_MODULE_AUTHENTICATE_KEYPAIR_IDENTIFIER* = "MainModule-AuthenticateKeypair"
|
||||
const UNIQUE_MAIN_MODULE_KEYCARD_SYNC_IDENTIFIER* = "MainModule-KeycardSyncPurpose"
|
||||
const UNIQUE_MAIN_MODULE_SHARED_KEYCARD_MODULE_IDENTIFIER* = "MainModule-SharedKeycardModule"
|
||||
|
||||
type
|
||||
Controller* = ref object of RootObj
|
||||
|
@ -418,10 +419,13 @@ proc init*(self: Controller) =
|
|||
self.delegate.onSharedKeycarModuleKeycardSyncPurposeTerminated(args.lastStepInTheCurrentFlow)
|
||||
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_KEYCARD_SYNC_TERMINATED, Args())
|
||||
return
|
||||
if args.uniqueIdentifier != UNIQUE_MAIN_MODULE_IDENTIFIER or
|
||||
if args.uniqueIdentifier == UNIQUE_MAIN_MODULE_SHARED_KEYCARD_MODULE_IDENTIFIER:
|
||||
self.delegate.onSharedKeycarModuleFlowTerminated(args.lastStepInTheCurrentFlow)
|
||||
return
|
||||
if args.uniqueIdentifier != UNIQUE_MAIN_MODULE_AUTHENTICATE_KEYPAIR_IDENTIFIER or
|
||||
self.authenticateUserFlowRequestedBy.len == 0:
|
||||
return
|
||||
self.delegate.onSharedKeycarModuleFlowTerminated(args.lastStepInTheCurrentFlow)
|
||||
self.delegate.onSharedKeycarModuleForAuthenticationTerminated(args.lastStepInTheCurrentFlow)
|
||||
let data = SharedKeycarModuleArgs(uniqueIdentifier: self.authenticateUserFlowRequestedBy,
|
||||
password: args.password,
|
||||
pin: args.pin,
|
||||
|
@ -435,10 +439,13 @@ proc init*(self: Controller) =
|
|||
|
||||
self.events.on(SIGNAL_SHARED_KEYCARD_MODULE_DISPLAY_POPUP) do(e: Args):
|
||||
let args = SharedKeycarModuleBaseArgs(e)
|
||||
if args.uniqueIdentifier != UNIQUE_MAIN_MODULE_IDENTIFIER or
|
||||
if args.uniqueIdentifier == UNIQUE_MAIN_MODULE_SHARED_KEYCARD_MODULE_IDENTIFIER:
|
||||
self.delegate.onDisplayKeycardSharedModuleFlow()
|
||||
return
|
||||
if args.uniqueIdentifier != UNIQUE_MAIN_MODULE_AUTHENTICATE_KEYPAIR_IDENTIFIER or
|
||||
self.authenticateUserFlowRequestedBy.len == 0:
|
||||
return
|
||||
self.delegate.onDisplayKeycardSharedModuleFlow()
|
||||
self.delegate.onDisplayKeycardSharedModuleForAuthentication()
|
||||
|
||||
self.events.on(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER) do(e: Args):
|
||||
let args = SharedKeycarModuleAuthenticationArgs(e)
|
||||
|
@ -449,6 +456,9 @@ proc init*(self: Controller) =
|
|||
let args = SharedKeycarModuleArgs(e)
|
||||
self.delegate.tryKeycardSync(args.keyUid, args.pin)
|
||||
|
||||
self.events.on(SIGNAL_PROFILE_MIGRATION_NEEDED_UPDATED) do(e: Args):
|
||||
self.delegate.checkAndPerformProfileMigrationIfNeeded()
|
||||
|
||||
proc isConnected*(self: Controller): bool =
|
||||
return self.nodeService.isConnected()
|
||||
|
||||
|
@ -551,4 +561,4 @@ proc asyncGetRevealedAccountsForAllMembers*(self: Controller, communityId: strin
|
|||
self.communityService.asyncGetRevealedAccountsForAllMembers(communityId)
|
||||
|
||||
proc asyncReevaluateCommunityMembersPermissions*(self: Controller, communityId: string) =
|
||||
self.communityService.asyncReevaluateCommunityMembersPermissions(communityId)
|
||||
self.communityService.asyncReevaluateCommunityMembersPermissions(communityId)
|
||||
|
|
|
@ -261,6 +261,15 @@ method onStatusUrlRequested*(self: AccessInterface, action: StatusUrlAction, com
|
|||
method getVerificationRequestFrom*(self: AccessInterface, publicKey: string): VerificationRequest {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getKeycardSharedModuleForAuthentication*(self: AccessInterface): QVariant {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onDisplayKeycardSharedModuleForAuthentication*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onSharedKeycarModuleForAuthenticationTerminated*(self: AccessInterface, lastStepInTheCurrentFlow: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getKeycardSharedModule*(self: AccessInterface): QVariant {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
@ -273,6 +282,12 @@ method onSharedKeycarModuleFlowTerminated*(self: AccessInterface, lastStepInTheC
|
|||
method runAuthenticationPopup*(self: AccessInterface, keyUid: string, bip44Paths: seq[string] = @[]) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onSharedKeycarModuleRunningKeycardFlowsPurposeTerminated*(self: AccessInterface, lastStepInTheCurrentFlow: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method checkAndPerformProfileMigrationIfNeeded*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onMyRequestAdded*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
|
|
@ -103,8 +103,9 @@ type
|
|||
communitiesModule: communities_module.AccessInterface
|
||||
appSearchModule: app_search_module.AccessInterface
|
||||
nodeSectionModule: node_section_module.AccessInterface
|
||||
keycardSharedModule: keycard_shared_module.AccessInterface
|
||||
keycardSharedModuleForAuthentication: keycard_shared_module.AccessInterface
|
||||
keycardSharedModuleKeycardSyncPurpose: keycard_shared_module.AccessInterface
|
||||
keycardSharedModule: keycard_shared_module.AccessInterface
|
||||
networkConnectionModule: network_connection_module.AccessInterface
|
||||
sharedUrlsModule: shared_urls_module.AccessInterface
|
||||
moduleLoaded: bool
|
||||
|
@ -233,10 +234,12 @@ method delete*[T](self: Module[T]) =
|
|||
self.browserSectionModule.delete
|
||||
self.appSearchModule.delete
|
||||
self.nodeSectionModule.delete
|
||||
if not self.keycardSharedModule.isNil:
|
||||
self.keycardSharedModule.delete
|
||||
if not self.keycardSharedModuleForAuthentication.isNil:
|
||||
self.keycardSharedModuleForAuthentication.delete
|
||||
if not self.keycardSharedModuleKeycardSyncPurpose.isNil:
|
||||
self.keycardSharedModuleKeycardSyncPurpose.delete
|
||||
if not self.keycardSharedModule.isNil:
|
||||
self.keycardSharedModule.delete
|
||||
self.networkConnectionModule.delete
|
||||
self.sharedUrlsModule.delete
|
||||
self.view.delete
|
||||
|
@ -1284,30 +1287,40 @@ method onStatusUrlRequested*[T](self: Module[T], action: StatusUrlAction, commun
|
|||
# self.setActiveSection(item)
|
||||
# self.browserSectionModule.openUrl(url)
|
||||
|
||||
proc isSharedKeycardModuleFlowRunning[T](self: Module[T]): bool =
|
||||
return not self.keycardSharedModule.isNil
|
||||
################################################################################
|
||||
## keycard shared module - authentication purpose
|
||||
################################################################################
|
||||
proc isSharedKeycardModuleForAuthenticationRunning[T](self: Module[T]): bool =
|
||||
return not self.keycardSharedModuleForAuthentication.isNil
|
||||
|
||||
method getKeycardSharedModule*[T](self: Module[T]): QVariant =
|
||||
if self.isSharedKeycardModuleFlowRunning():
|
||||
return self.keycardSharedModule.getModuleAsVariant()
|
||||
method getKeycardSharedModuleForAuthentication*[T](self: Module[T]): QVariant =
|
||||
if self.isSharedKeycardModuleForAuthenticationRunning():
|
||||
return self.keycardSharedModuleForAuthentication.getModuleAsVariant()
|
||||
|
||||
proc createSharedKeycardModule[T](self: Module[T]) =
|
||||
self.keycardSharedModule = keycard_shared_module.newModule[Module[T]](self, UNIQUE_MAIN_MODULE_IDENTIFIER,
|
||||
proc createSharedKeycardModuleForAuthentication[T](self: Module[T]) =
|
||||
self.keycardSharedModuleForAuthentication = keycard_shared_module.newModule[Module[T]](self, UNIQUE_MAIN_MODULE_AUTHENTICATE_KEYPAIR_IDENTIFIER,
|
||||
self.events, self.keycardService, self.settingsService, self.networkService, self.privacyService, self.accountsService,
|
||||
self.walletAccountService, self.keychainService)
|
||||
|
||||
method onSharedKeycarModuleFlowTerminated*[T](self: Module[T], lastStepInTheCurrentFlow: bool) =
|
||||
if self.isSharedKeycardModuleFlowRunning():
|
||||
self.view.emitDestroyKeycardSharedModuleFlow()
|
||||
self.keycardSharedModule.delete
|
||||
self.keycardSharedModule = nil
|
||||
method onSharedKeycarModuleForAuthenticationTerminated*[T](self: Module[T], lastStepInTheCurrentFlow: bool) =
|
||||
if self.isSharedKeycardModuleForAuthenticationRunning():
|
||||
self.view.emitDestroyKeycardSharedModuleForAuthentication()
|
||||
self.keycardSharedModuleForAuthentication.delete
|
||||
self.keycardSharedModuleForAuthentication = nil
|
||||
|
||||
method runAuthenticationPopup*[T](self: Module[T], keyUid: string, bip44Paths: seq[string] = @[]) =
|
||||
self.createSharedKeycardModule()
|
||||
if self.keycardSharedModule.isNil:
|
||||
self.createSharedKeycardModuleForAuthentication()
|
||||
if self.keycardSharedModuleForAuthentication.isNil:
|
||||
return
|
||||
self.keycardSharedModule.runFlow(keycard_shared_module.FlowType.Authentication, keyUid, bip44Paths)
|
||||
self.keycardSharedModuleForAuthentication.runFlow(keycard_shared_module.FlowType.Authentication, keyUid, bip44Paths)
|
||||
|
||||
method onDisplayKeycardSharedModuleForAuthentication*[T](self: Module[T]) =
|
||||
self.view.emitDisplayKeycardSharedModuleForAuthentication()
|
||||
################################################################################
|
||||
|
||||
################################################################################
|
||||
## keycard shared module - keycard syncing purpose
|
||||
################################################################################
|
||||
method onSharedKeycarModuleKeycardSyncPurposeTerminated*[T](self: Module[T], lastStepInTheCurrentFlow: bool) =
|
||||
if not self.keycardSharedModuleKeycardSyncPurpose.isNil:
|
||||
self.keycardSharedModuleKeycardSyncPurpose.delete
|
||||
|
@ -1320,10 +1333,59 @@ method tryKeycardSync*[T](self: Module[T], keyUid: string, pin: string) =
|
|||
if self.keycardSharedModuleKeycardSyncPurpose.isNil:
|
||||
return
|
||||
self.keycardSharedModuleKeycardSyncPurpose.syncKeycardBasedOnAppState(keyUid, pin)
|
||||
################################################################################
|
||||
|
||||
################################################################################
|
||||
## keycard shared module - general purpose
|
||||
################################################################################
|
||||
method getKeycardSharedModule*[T](self: Module[T]): QVariant =
|
||||
if not self.keycardSharedModule.isNil:
|
||||
return self.keycardSharedModule.getModuleAsVariant()
|
||||
|
||||
method onSharedKeycarModuleFlowTerminated*[T](self: Module[T], lastStepInTheCurrentFlow: bool) =
|
||||
if not self.keycardSharedModule.isNil:
|
||||
self.view.emitDestroyKeycardSharedModuleFlow()
|
||||
self.keycardSharedModule.delete
|
||||
self.keycardSharedModule = nil
|
||||
|
||||
method onDisplayKeycardSharedModuleFlow*[T](self: Module[T]) =
|
||||
self.view.emitDisplayKeycardSharedModuleFlow()
|
||||
|
||||
proc runStopUsingKeycardForProfilePopup[T](self: Module[T]) =
|
||||
if not self.keycardSharedModule.isNil:
|
||||
info "shared keycard module is already running, cannot run stop using keycard flow"
|
||||
return
|
||||
self.keycardSharedModule = keycard_shared_module.newModule[Module[T]](self, UNIQUE_MAIN_MODULE_SHARED_KEYCARD_MODULE_IDENTIFIER,
|
||||
self.events, self.keycardService, self.settingsService, self.networkService, self.privacyService, self.accountsService,
|
||||
self.walletAccountService, self.keychainService)
|
||||
self.keycardSharedModule.runFlow(keycard_shared_module.FlowType.MigrateFromKeycardToApp,
|
||||
singletonInstance.userProfile.getKeyUid(), bip44Paths = @[], txHash = "", forceFlow = true)
|
||||
################################################################################
|
||||
|
||||
method checkAndPerformProfileMigrationIfNeeded*[T](self: Module[T]) =
|
||||
let migrationNeeded = self.settingsService.getProfileMigrationNeeded()
|
||||
let profileKeypair = self.walletAccountService.getKeypairByKeyUid(singletonInstance.userProfile.getKeyUid())
|
||||
if profileKeypair.isNil:
|
||||
info "quit the app because of unresolved profile keypair"
|
||||
quit() # quit the app
|
||||
if not migrationNeeded:
|
||||
if not self.keycardSharedModule.isNil:
|
||||
let currentFlow = self.keycardSharedModule.getCurrentFlowType()
|
||||
if currentFlow == FlowType.MigrateFromKeycardToApp:
|
||||
self.keycardSharedModule.onCancelActionClicked()
|
||||
return
|
||||
if profileKeypair.keycards.len > 0:
|
||||
if not self.keycardSharedModule.isNil:
|
||||
let currentFlow = self.keycardSharedModule.getCurrentFlowType()
|
||||
if currentFlow == FlowType.MigrateFromKeycardToApp:
|
||||
return
|
||||
self.keycardSharedModule.onCancelActionClicked()
|
||||
info "run stop using keycard flow for the profile, cause profile was migrated on paired device"
|
||||
self.runStopUsingKeycardForProfilePopup()
|
||||
return
|
||||
## TODO: we need to add a flow to handle migration to a Keycard
|
||||
info "run migrate to a Keycard flow for the profile, cause profile was migrated on paired device"
|
||||
|
||||
method activateStatusDeepLink*[T](self: Module[T], statusDeepLink: string) =
|
||||
let urlData = self.sharedUrlsModule.parseSharedUrl(statusDeepLink)
|
||||
if urlData.community.communityId != "":
|
||||
|
|
|
@ -243,6 +243,17 @@ QtObject:
|
|||
proc emitDisplayUserProfileSignal*(self: View, publicKey: string) =
|
||||
self.displayUserProfile(publicKey)
|
||||
|
||||
proc getKeycardSharedModuleForAuthentication(self: View): QVariant {.slot.} =
|
||||
let module = self.delegate.getKeycardSharedModuleForAuthentication()
|
||||
if not module.isNil:
|
||||
return module
|
||||
return newQVariant()
|
||||
QtProperty[QVariant] keycardSharedModuleForAuthentication:
|
||||
read = getKeycardSharedModuleForAuthentication
|
||||
|
||||
proc activateStatusDeepLink*(self: View, statusDeepLink: string) {.slot.} =
|
||||
self.delegate.activateStatusDeepLink(statusDeepLink)
|
||||
|
||||
proc getKeycardSharedModule(self: View): QVariant {.slot.} =
|
||||
let module = self.delegate.getKeycardSharedModule()
|
||||
if not module.isNil:
|
||||
|
@ -251,8 +262,13 @@ QtObject:
|
|||
QtProperty[QVariant] keycardSharedModule:
|
||||
read = getKeycardSharedModule
|
||||
|
||||
proc activateStatusDeepLink*(self: View, statusDeepLink: string) {.slot.} =
|
||||
self.delegate.activateStatusDeepLink(statusDeepLink)
|
||||
proc displayKeycardSharedModuleForAuthentication*(self: View) {.signal.}
|
||||
proc emitDisplayKeycardSharedModuleForAuthentication*(self: View) =
|
||||
self.displayKeycardSharedModuleForAuthentication()
|
||||
|
||||
proc destroyKeycardSharedModuleForAuthentication*(self: View) {.signal.}
|
||||
proc emitDestroyKeycardSharedModuleForAuthentication*(self: View) =
|
||||
self.destroyKeycardSharedModuleForAuthentication()
|
||||
|
||||
proc displayKeycardSharedModuleFlow*(self: View) {.signal.}
|
||||
proc emitDisplayKeycardSharedModuleFlow*(self: View) =
|
||||
|
|
|
@ -231,6 +231,11 @@ method load*(self: Module) =
|
|||
if not args.success:
|
||||
return
|
||||
self.notifyFilterChanged()
|
||||
self.events.on(SIGNAL_ALL_KEYCARDS_DELETED) do(e: Args):
|
||||
let args = KeycardArgs(e)
|
||||
if not args.success:
|
||||
return
|
||||
self.notifyFilterChanged()
|
||||
self.events.on(SIGNAL_WALLET_ACCOUNT_POSITION_UPDATED) do(e:Args):
|
||||
self.notifyFilterChanged()
|
||||
self.events.on(SIGNAL_INCLUDE_WATCH_ONLY_ACCOUNTS_UPDATED) do(e: Args):
|
||||
|
|
|
@ -12,6 +12,10 @@ method executeCancelCommand*(self: CreatePasswordState, controller: Controller)
|
|||
if self.flowType == FlowType.MigrateFromKeycardToApp:
|
||||
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
|
||||
|
||||
method executePreBackStateCommand*(self: CreatePasswordState, controller: Controller) =
|
||||
if self.flowType == FlowType.MigrateFromKeycardToApp:
|
||||
controller.setPassword("")
|
||||
|
||||
method getNextPrimaryState*(self: CreatePasswordState, controller: Controller): State =
|
||||
if self.flowType == FlowType.MigrateFromKeycardToApp:
|
||||
return createState(StateType.ConfirmPassword, self.flowType, self)
|
|
@ -88,7 +88,8 @@ method getNextPrimaryState*(self: EnterSeedPhraseState, controller: Controller):
|
|||
return
|
||||
return createState(StateType.CreatePassword, self.flowType, self)
|
||||
|
||||
method getNextSecondaryState*(self: EnterSeedPhraseState, controller: Controller): State =
|
||||
method getNextTertiaryState*(self: EnterSeedPhraseState, controller: Controller): State =
|
||||
## Tertiary action is called after each async action during migration process.
|
||||
if self.flowType == FlowType.MigrateFromKeycardToApp:
|
||||
let migratingProfile = controller.getKeyPairForProcessing().getKeyUid() == singletonInstance.userProfile.getKeyUid()
|
||||
if migratingProfile:
|
||||
|
|
|
@ -17,7 +17,8 @@ method executePrePrimaryStateCommand*(self: MigratingKeypairToAppState, controll
|
|||
let migratingProfile = controller.getKeyPairForProcessing().getKeyUid() == singletonInstance.userProfile.getKeyUid()
|
||||
if migratingProfile:
|
||||
let newPassword = controller.getNewPassword()
|
||||
controller.tryToStoreDataToKeychain(newPassword)
|
||||
if singletonInstance.localAccountSettings.getStoreToKeychainValue() == LS_VALUE_STORE:
|
||||
controller.tryToStoreDataToKeychain(newPassword)
|
||||
controller.convertKeycardProfileKeypairToRegular(sp, password, newPassword)
|
||||
return
|
||||
controller.migrateNonProfileKeycardKeypairToApp(kpForProcessing.getKeyUid(), sp, password,
|
||||
|
@ -26,7 +27,11 @@ method executePrePrimaryStateCommand*(self: MigratingKeypairToAppState, controll
|
|||
method executePreTertiaryStateCommand*(self: MigratingKeypairToAppState, controller: Controller) =
|
||||
## Tertiary action is called after each async action during migration process.
|
||||
if self.flowType == FlowType.MigrateFromKeycardToApp:
|
||||
self.migrationOk = controller.getConvertingProfileSuccess()
|
||||
let migratingProfile = controller.getKeyPairForProcessing().getKeyUid() == singletonInstance.userProfile.getKeyUid()
|
||||
if migratingProfile:
|
||||
self.migrationOk = controller.getConvertingProfileSuccess()
|
||||
return
|
||||
self.migrationOk = controller.getAddingMigratedKeypairSuccess()
|
||||
|
||||
method getNextTertiaryState*(self: MigratingKeypairToAppState, controller: Controller): State =
|
||||
if self.flowType == FlowType.MigrateFromKeycardToApp:
|
||||
|
|
|
@ -57,7 +57,8 @@ method getNextPrimaryState*(self: WrongSeedPhraseState, controller: Controller):
|
|||
return createState(StateType.CreatePin, self.flowType, nil)
|
||||
return self
|
||||
|
||||
method getNextSecondaryState*(self: WrongSeedPhraseState, controller: Controller): State =
|
||||
method getNextTertiaryState*(self: WrongSeedPhraseState, controller: Controller): State =
|
||||
## Tertiary action is called after each async action during migration process.
|
||||
if self.flowType == FlowType.MigrateFromKeycardToApp:
|
||||
let migratingProfile = controller.getKeyPairForProcessing().getKeyUid() == singletonInstance.userProfile.getKeyUid()
|
||||
if migratingProfile:
|
||||
|
|
|
@ -120,7 +120,7 @@ method onCancelActionClicked*(self: AccessInterface) {.base.} =
|
|||
method onKeycardResponse*(self: AccessInterface, keycardFlowType: string, keycardEvent: KeycardEvent) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method runFlow*(self: AccessInterface, flowToRun: FlowType, keyUid = "", bip44Paths: seq[string] = @[], txHash = "") {.base.} =
|
||||
method runFlow*(self: AccessInterface, flowToRun: FlowType, keyUid = "", bip44Paths: seq[string] = @[], txHash = "", forceFlow = false) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setPin*(self: AccessInterface, value: string) {.base.} =
|
||||
|
|
|
@ -460,7 +460,7 @@ method prepareKeyPairForProcessing*[T](self: Module[T], keyUid: string, keycardU
|
|||
item.setIcon("keycard")
|
||||
self.view.setKeyPairForProcessing(item)
|
||||
|
||||
method runFlow*[T](self: Module[T], flowToRun: FlowType, keyUid = "", bip44Paths: seq[string] = @[], txHash = "") =
|
||||
method runFlow*[T](self: Module[T], flowToRun: FlowType, keyUid = "", bip44Paths: seq[string] = @[], txHash = "", forceFlow = false) =
|
||||
## In case of `Authentication` if we're signing a transaction we need to provide a key uid of a keypair that an account
|
||||
## we want to sign a transaction for belongs to. If we're just doing an authentication for a logged in user, then
|
||||
## default key uid is always the key uid of the logged in user.
|
||||
|
@ -469,6 +469,7 @@ method runFlow*[T](self: Module[T], flowToRun: FlowType, keyUid = "", bip44Paths
|
|||
error "sm_cannot run an general flow"
|
||||
return
|
||||
self.init()
|
||||
self.view.setForceFlow(forceFlow)
|
||||
if flowToRun == FlowType.FactoryReset:
|
||||
if keyUid.len > 0:
|
||||
self.prepareKeyPairForProcessing(keyUid)
|
||||
|
@ -562,7 +563,7 @@ method runFlow*[T](self: Module[T], flowToRun: FlowType, keyUid = "", bip44Paths
|
|||
return
|
||||
if flowToRun == FlowType.MigrateFromKeycardToApp:
|
||||
if keyUid.len == 0:
|
||||
error "sm_cannot run a migration from keycar to app flow without knowing in advance a keypair being migrated"
|
||||
error "sm_cannot run a migration from keycard to app flow without knowing in advance a keypair being migrated"
|
||||
self.controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
|
||||
return
|
||||
self.prepareKeyPairForProcessing(keyUid)
|
||||
|
|
|
@ -7,6 +7,7 @@ QtObject:
|
|||
type
|
||||
View* = ref object of QObject
|
||||
delegate: io_interface.AccessInterface
|
||||
forceFlow: bool # used to disable any possibility of closing the popup, the user is forced to complete the flow or forcibly close the app (no other way to close the popup)
|
||||
disablePopup: bool # used to disable popup after each action, to block users do multiple clikcs which the action is ongoing
|
||||
currentState: StateWrapper
|
||||
currentStateVariant: QVariant
|
||||
|
@ -44,6 +45,7 @@ QtObject:
|
|||
result.currentState = newStateWrapper()
|
||||
result.currentStateVariant = newQVariant(result.currentState)
|
||||
result.remainingAttempts = -1
|
||||
result.forceFlow = false
|
||||
result.disablePopup = false
|
||||
|
||||
signalConnect(result.currentState, "backActionClicked()", result, "onBackActionClicked()", 2)
|
||||
|
@ -52,6 +54,16 @@ QtObject:
|
|||
signalConnect(result.currentState, "secondaryActionClicked()", result, "onSecondaryActionClicked()", 2)
|
||||
signalConnect(result.currentState, "tertiaryActionClicked()", result, "onTertiaryActionClicked()", 2)
|
||||
|
||||
proc forceFlowChanged*(self: View) {.signal.}
|
||||
proc getForceFlow*(self: View): bool {.slot.} =
|
||||
return self.forceFlow
|
||||
QtProperty[bool] forceFlow:
|
||||
read = getForceFlow
|
||||
notify = forceFlowChanged
|
||||
proc setForceFlow*(self: View, value: bool) =
|
||||
self.forceFlow = value
|
||||
self.forceFlowChanged()
|
||||
|
||||
proc diablePopupChanged*(self: View) {.signal.}
|
||||
proc getDisablePopup*(self: View): bool {.slot.} =
|
||||
return self.disablePopup
|
||||
|
|
|
@ -45,6 +45,7 @@ const KEY_DISPLAY_NAME* = "display-name"
|
|||
const KEY_BIO* = "bio"
|
||||
const KEY_TEST_NETWORKS_ENABLED* = "test-networks-enabled?"
|
||||
const INCLUDE_WATCH_ONLY_ACCOUNT* = "include-watch-only-account?"
|
||||
const PROFILE_MIGRATION_NEEDED* = "profile-migration-needed"
|
||||
|
||||
# Notifications Settings Values
|
||||
const VALUE_NOTIF_SEND_ALERTS* = "SendAlerts"
|
||||
|
@ -137,6 +138,7 @@ type
|
|||
notificationsVolume*: int
|
||||
notificationsMessagePreview*: int
|
||||
includeWatchOnlyAccount*: bool
|
||||
profileMigrationNeeded*: bool
|
||||
|
||||
proc toPinnedMailserver*(jsonObj: JsonNode): PinnedMailserver =
|
||||
# we maintain pinned mailserver per fleet
|
||||
|
@ -191,6 +193,7 @@ proc toSettingsDto*(jsonObj: JsonNode): SettingsDto =
|
|||
discard jsonObj.getProp(KEY_GIF_FAVORITES, result.gifFavorites)
|
||||
discard jsonObj.getProp(KEY_TEST_NETWORKS_ENABLED, result.testNetworksEnabled)
|
||||
discard jsonObj.getProp(INCLUDE_WATCH_ONLY_ACCOUNT, result.includeWatchOnlyAccount)
|
||||
discard jsonObj.getProp(PROFILE_MIGRATION_NEEDED, result.profileMigrationNeeded)
|
||||
|
||||
var pinnedMailserverObj: JsonNode
|
||||
if(jsonObj.getProp(KEY_PINNED_MAILSERVERS, pinnedMailserverObj)):
|
||||
|
|
|
@ -28,6 +28,7 @@ const SIGNAL_MNEMONIC_REMOVED* = "mnemonicRemoved"
|
|||
const SIGNAL_SOCIAL_LINKS_UPDATED* = "socialLinksUpdated"
|
||||
const SIGNAL_CURRENT_USER_STATUS_UPDATED* = "currentUserStatusUpdated"
|
||||
const SIGNAL_INCLUDE_WATCH_ONLY_ACCOUNTS_UPDATED* = "includeWatchOnlyAccounts"
|
||||
const SIGNAL_PROFILE_MIGRATION_NEEDED_UPDATED* = "profileMigrationNeededUpdated"
|
||||
|
||||
logScope:
|
||||
topics = "settings-service"
|
||||
|
@ -116,6 +117,9 @@ QtObject:
|
|||
if settingsField.name == INCLUDE_WATCH_ONLY_ACCOUNT:
|
||||
self.settings.includeWatchOnlyAccount = settingsField.value.getBool
|
||||
self.events.emit(SIGNAL_INCLUDE_WATCH_ONLY_ACCOUNTS_UPDATED, Args())
|
||||
if settingsField.name == PROFILE_MIGRATION_NEEDED:
|
||||
self.settings.profileMigrationNeeded = settingsField.value.getBool
|
||||
self.events.emit(SIGNAL_PROFILE_MIGRATION_NEEDED_UPDATED, SettingsBoolValueArgs(value: self.settings.profileMigrationNeeded))
|
||||
|
||||
if receivedData.socialLinksInfo.links.len > 0 or
|
||||
receivedData.socialLinksInfo.removed:
|
||||
|
@ -978,3 +982,6 @@ QtObject:
|
|||
if(self.saveSetting(INCLUDE_WATCH_ONLY_ACCOUNT, newValue)):
|
||||
self.settings.includeWatchOnlyAccount = newValue
|
||||
self.events.emit(SIGNAL_INCLUDE_WATCH_ONLY_ACCOUNTS_UPDATED, SettingsBoolValueArgs(value: newValue))
|
||||
|
||||
proc getProfileMigrationNeeded*(self: Service): bool =
|
||||
self.settings.profileMigrationNeeded
|
|
@ -387,10 +387,6 @@ proc makePrivateKeyKeypairFullyOperable*(self: Service, keyUid, privateKey, pass
|
|||
## Mandatory fields for all accounts: `address`, `keyUid`, `walletType`, `path`, `publicKey`, `name`, `emoji`, `colorId`
|
||||
proc addNewSeedPhraseKeypair*(self: Service, seedPhrase, password: string, doPasswordHashing: bool,
|
||||
keyUid, keypairName, rootWalletMasterKey: string, accounts: seq[WalletAccountDto]): string =
|
||||
if password.len == 0:
|
||||
let err = "for adding a new seed phrase keypair, password must be provided"
|
||||
error "error", err
|
||||
return err
|
||||
var finalPassword = password
|
||||
if password.len > 0 and doPasswordHashing:
|
||||
finalPassword = utils.hashPassword(password)
|
||||
|
|
|
@ -71,6 +71,14 @@ Item {
|
|||
popups.openProfilePopup(publicKey)
|
||||
}
|
||||
|
||||
function onDisplayKeycardSharedModuleForAuthentication() {
|
||||
keycardPopupForAuthentication.active = true
|
||||
}
|
||||
|
||||
function onDestroyKeycardSharedModuleForAuthentication() {
|
||||
keycardPopupForAuthentication.active = false
|
||||
}
|
||||
|
||||
function onDisplayKeycardSharedModuleFlow() {
|
||||
keycardPopup.active = true
|
||||
}
|
||||
|
@ -1558,6 +1566,18 @@ Item {
|
|||
Global.settingsLoaded()
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: keycardPopupForAuthentication
|
||||
active: false
|
||||
sourceComponent: KeycardPopup {
|
||||
sharedKeycardModule: appMain.rootStore.mainModuleInst.keycardSharedModuleForAuthentication
|
||||
}
|
||||
|
||||
onLoaded: {
|
||||
keycardPopupForAuthentication.item.open()
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: keycardPopup
|
||||
active: false
|
||||
|
|
|
@ -13,8 +13,10 @@ StatusModal {
|
|||
property var emojiPopup
|
||||
|
||||
width: Constants.keycard.general.popupWidth
|
||||
closePolicy: d.disableActionPopupButtons || d.disableCloseButton? Popup.NoAutoClose : Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||
hasCloseButton: !d.disableActionPopupButtons && !d.disableCloseButton
|
||||
closePolicy: root.sharedKeycardModule.forceFlow || d.disableActionPopupButtons || d.disableCloseButton?
|
||||
Popup.NoAutoClose :
|
||||
Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||
hasCloseButton: !root.sharedKeycardModule.forceFlow && !d.disableActionPopupButtons && !d.disableCloseButton
|
||||
|
||||
headerSettings.title: {
|
||||
switch (root.sharedKeycardModule.currentState.flowType) {
|
||||
|
@ -45,6 +47,10 @@ StatusModal {
|
|||
case Constants.keycardSharedFlow.createCopyOfAKeycard:
|
||||
return qsTr("Create a backup copy of this Keycard")
|
||||
case Constants.keycardSharedFlow.migrateFromKeycardToApp:
|
||||
// in the context of `migrateFromKeycardToApp` flow, `forceFlow` is set to `true` on paired devices
|
||||
if (root.sharedKeycardModule.forceFlow) {
|
||||
return qsTr("Enable password login on this device")
|
||||
}
|
||||
return qsTr("Migrate a keypair from Keycard to Status")
|
||||
}
|
||||
|
||||
|
|
|
@ -375,14 +375,14 @@ QtObject {
|
|||
case Constants.keycardSharedState.wrongSeedPhrase:
|
||||
case Constants.keycardSharedState.createPassword:
|
||||
case Constants.keycardSharedState.confirmPassword:
|
||||
return true
|
||||
return !root.sharedKeycardModule.forceFlow
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
enabled: !root.disableActionPopupButtons
|
||||
enabled: !root.sharedKeycardModule.forceFlow && !root.disableActionPopupButtons
|
||||
onClicked: {
|
||||
root.cancelBtnClicked();
|
||||
}
|
||||
|
|
|
@ -1371,6 +1371,11 @@ Item {
|
|||
target: title
|
||||
text: {
|
||||
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migrateKeypairToApp) {
|
||||
if (root.sharedKeycardModule.keyPairForProcessing.pairType === Constants.keycard.keyPairType.profile) {
|
||||
if (root.sharedKeycardModule.forceFlow) {
|
||||
return qsTr("Your profile keypair has been\nmigrated from Keycard to Status")
|
||||
}
|
||||
}
|
||||
return qsTr("Are you sure you want to migrate\nthis keypair to Status?")
|
||||
}
|
||||
return ""
|
||||
|
@ -1388,11 +1393,23 @@ Item {
|
|||
target: message
|
||||
text: {
|
||||
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migrateKeypairToApp) {
|
||||
if (root.sharedKeycardModule.keyPairForProcessing.pairType === Constants.keycard.keyPairType.profile) {
|
||||
if (root.sharedKeycardModule.forceFlow) {
|
||||
return qsTr("In order to continue using this profile on this device, you need to enter the keypairs seed phrase and create a new password to log in with on this device.")
|
||||
}
|
||||
|
||||
let t = qsTr("%1 is your default Status keypair.").arg(root.sharedKeycardModule.keyPairForProcessing.name)
|
||||
t += qsTr(" Migrating this keypair will mean you will no longer require this Keycard to login to Status or")
|
||||
t += qsTr(" transact with the keypair’s derived account(s).", "", root.sharedKeycardModule.keyPairForProcessing.accounts.count)
|
||||
t += qsTr(" The keypair and account(s) will be fully removed from Keycard and stored on device.", "", root.sharedKeycardModule.keyPairForProcessing.accounts.count)
|
||||
return t
|
||||
}
|
||||
|
||||
let t = qsTr("%1 keypair and its derived account(s) will be fully removed from Keycard and stored on device.",
|
||||
"",
|
||||
root.sharedKeycardModule.keyPairForProcessing.accounts.count)
|
||||
.arg(root.sharedKeycardModule.keyPairForProcessing.name)
|
||||
t += qsTr("This will make your keypair and derived account(s) less secure as you will no longer require this Keycard to transact.",
|
||||
t += qsTr(" This will make your keypair and derived account(s) less secure as you will no longer require this Keycard to transact.",
|
||||
"",
|
||||
root.sharedKeycardModule.keyPairForProcessing.accounts.count)
|
||||
return t
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit c0f32748b4927b5e3272e1e8e9cb6b226f002720
|
||||
Subproject commit 83d13548458c60d14eba6efdd92a928f9f0050a1
|
Loading…
Reference in New Issue