fix(@desktop/keycard): updates to the onboarding/login flow

Changes done within this commit were required by the latest keycard
library change, where we gave up of sending few signals when we're
running/resuming flow, which were sent before (those were signal notifying
about unplugged reader, card not inserted and card inserted, they are sent
by the keycard lib now only if that is really needed).
This commit is contained in:
Sale Djenic 2022-09-02 13:03:40 +02:00 committed by saledjenic
parent 2b84a91675
commit 79aece0aeb
35 changed files with 348 additions and 225 deletions

View File

@ -241,7 +241,8 @@ proc delete*(self: AppController) =
self.contactsService.delete
self.bookmarkService.delete
self.gifService.delete
self.startupModule.delete
if not self.startupModule.isNil:
self.startupModule.delete
self.mainModule.delete
self.languageService.delete
@ -359,6 +360,9 @@ proc userLoggedIn*(self: AppController) =
if(importedAccount.isValid()):
self.privacyService.removeMnemonic()
if not self.startupModule.isNil:
self.startupModule.delete
proc buildAndRegisterLocalAccountSensitiveSettings(self: AppController) =
var pubKey = self.settingsService.getPublicKey()
singletonInstance.localAccountSensitiveSettings.setFileName(pubKey)

View File

@ -1,5 +1,5 @@
import chronicles, strutils, os
import uuids
import io_interface
import ../../global/global_singleton
@ -33,10 +33,12 @@ type
keychainService: keychain_service.Service
profileService: profile_service.Service
keycardService: keycard_service.Service
connectionIds: seq[UUID]
tmpProfileImageDetails: ProfileImageDetails
tmpDisplayName: string
tmpPassword: string
tmpSelectedLoginAccountKeyUid: string
tmpSelectedLoginAccountIsKeycardAccount: bool
tmpPin: string
tmpPinMatch: bool
tmpPuk: string
@ -68,43 +70,59 @@ proc newController*(delegate: io_interface.AccessInterface,
result.tmpSeedPhraseLength = 0
result.tmpKeychainErrorOccurred = true
result.tmpRecoverUsingSeedPhraseWhileLogin = false
result.tmpSelectedLoginAccountIsKeycardAccount = false
# Forward declaration
proc cleanTmpData*(self: Controller)
proc disconnect*(self: Controller) =
for id in self.connectionIds:
self.events.disconnect(id)
proc delete*(self: Controller) =
discard
self.disconnect()
proc init*(self: Controller) =
self.events.on(SignalType.NodeLogin.event) do(e:Args):
var handlerId = self.events.onWithUUID(SignalType.NodeLogin.event) do(e:Args):
let signal = NodeSignal(e)
self.delegate.onNodeLogin(signal.event.error)
self.connectionIds.add(handlerId)
self.events.on(SignalType.NodeStopped.event) do(e:Args):
handlerId = self.events.onWithUUID(SignalType.NodeStopped.event) do(e:Args):
self.events.emit("nodeStopped", Args())
self.accountsService.clear()
self.cleanTmpData()
self.delegate.emitLogOut()
self.connectionIds.add(handlerId)
self.events.on(SignalType.NodeReady.event) do(e:Args):
handlerId = self.events.onWithUUID(SignalType.NodeReady.event) do(e:Args):
self.events.emit("nodeReady", Args())
self.connectionIds.add(handlerId)
self.events.on(SIGNAL_KEYCHAIN_SERVICE_SUCCESS) do(e:Args):
handlerId = self.events.onWithUUID(SIGNAL_KEYCHAIN_SERVICE_SUCCESS) do(e:Args):
let args = KeyChainServiceArg(e)
self.delegate.emitObtainingPasswordSuccess(args.data)
self.connectionIds.add(handlerId)
self.events.on(SIGNAL_KEYCHAIN_SERVICE_ERROR) do(e:Args):
handlerId = self.events.onWithUUID(SIGNAL_KEYCHAIN_SERVICE_ERROR) do(e:Args):
let args = KeyChainServiceArg(e)
self.tmpKeychainErrorOccurred = true
self.delegate.emitObtainingPasswordError(args.errDescription, args.errType)
self.connectionIds.add(handlerId)
self.events.on(SignalKeycardResponse) do(e: Args):
handlerId = self.events.onWithUUID(SignalKeycardResponse) do(e: Args):
let args = KeycardArgs(e)
self.delegate.onKeycardResponse(args.flowType, args.flowEvent)
self.connectionIds.add(handlerId)
self.events.on(SignalSharedKeycarModuleFlowTerminated) do(e: Args):
handlerId = self.events.onWithUUID(SignalSharedKeycarModuleFlowTerminated) do(e: Args):
let args = SharedKeycarModuleFlowTerminatedArgs(e)
self.delegate.onSharedKeycarModuleFlowTerminated(args.lastStepInTheCurrentFlow)
self.connectionIds.add(handlerId)
handlerId = self.events.onWithUUID(SignalSharedKeycarModuleDisplayPopup) do(e: Args):
self.delegate.onDisplayKeycardSharedModuleFlow()
self.connectionIds.add(handlerId)
proc shouldStartWithOnboardingScreen*(self: Controller): bool =
return self.accountsService.openedAccounts().len == 0
@ -201,6 +219,7 @@ proc getRecoverUsingSeedPhraseWhileLogin*(self: Controller): bool =
proc cleanTmpData*(self: Controller) =
self.tmpSelectedLoginAccountKeyUid = ""
self.tmpSelectedLoginAccountIsKeycardAccount = false
self.tmpProfileImageDetails = ProfileImageDetails()
self.tmpKeychainErrorOccurred = true
self.setDisplayName("")
@ -306,8 +325,12 @@ proc getSelectedLoginAccount(self: Controller): AccountDto =
proc keyUidMatch*(self: Controller, keyUid: string): bool =
return self.tmpSelectedLoginAccountKeyUid == keyUid
proc setSelectedLoginAccountKeyUid*(self: Controller, keyUid: string) =
proc isSelectedLoginAccountKeycardAccount*(self: Controller): bool =
return self.tmpSelectedLoginAccountIsKeycardAccount
proc setSelectedLoginAccount*(self: Controller, keyUid: string, isKeycardAccount: bool) =
self.tmpSelectedLoginAccountKeyUid = keyUid
self.tmpSelectedLoginAccountIsKeycardAccount = isKeycardAccount
let selectedAccount = self.getSelectedLoginAccount()
singletonInstance.localAccountSettings.setFileName(selectedAccount.name)
@ -339,7 +362,7 @@ proc loginAccountKeycard*(self: Controller) =
if(error.len > 0):
self.delegate.emitAccountLoginError(error)
proc cancelCurrentFlow(self: Controller) =
proc cancelCurrentFlow*(self: Controller) =
self.keycardService.cancelCurrentFlow()
# in most cases we're running another flow after canceling the current one,
# this way we're giving to the keycard some time to cancel the current flow

View File

@ -8,6 +8,10 @@ proc newBiometricsState*(flowType: FlowType, backState: State): BiometricsState
proc delete*(self: BiometricsState) =
self.State.delete
method executeBackCommand*(self: BiometricsState, controller: Controller) =
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
controller.runRecoverAccountFlow()
method executePrimaryCommand*(self: BiometricsState, controller: Controller) =
let storeToKeychain = true # true, cause we have support for keychain for mac os
if self.flowType == FlowType.FirstRunNewUserNewKeys:

View File

@ -10,15 +10,9 @@ proc delete*(self: KeycardEmptyState) =
method executePrimaryCommand*(self: KeycardEmptyState, controller: Controller) =
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
controller.runLoadAccountFlow(factoryReset = true)
self.setFlowType(FlowType.FirstRunNewUserNewKeycardKeys)
controller.runLoadAccountFlow()
method resolveKeycardNextState*(self: KeycardEmptyState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.resumeCurrentFlowLater()
return createState(StateType.KeycardPluginReader, FlowType.FirstRunNewUserNewKeycardKeys, self)
if keycardFlowType == ResponseTypeValueInsertCard:
return createState(StateType.KeycardInsertKeycard, FlowType.FirstRunNewUserNewKeycardKeys, self)
return ensureReaderAndCardPresenceAndResolveNextOnboardingState(self, keycardFlowType, keycardEvent, controller)

View File

@ -29,6 +29,9 @@ method executePrimaryCommand*(self: KeycardEnterPinState, controller: Controller
method resolveKeycardNextState*(self: KeycardEnterPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceOnboarding(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len > 0 and

View File

@ -18,6 +18,9 @@ method executePrimaryCommand*(self: KeycardEnterPukState, controller: Controller
method resolveKeycardNextState*(self: KeycardEnterPukState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceOnboarding(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and

View File

@ -17,6 +17,9 @@ method executePrimaryCommand*(self: KeycardEnterSeedPhraseWordsState, controller
method resolveKeycardNextState*(self: KeycardEnterSeedPhraseWordsState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceOnboarding(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.keyUid.len > 0:

View File

@ -10,6 +10,9 @@ proc delete*(self: KeycardInsertKeycardState) =
method resolveKeycardNextState*(self: KeycardInsertKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceOnboarding(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if keycardFlowType == ResponseTypeValueInsertCard and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:

View File

@ -16,18 +16,6 @@ method executeSecondaryCommand*(self: KeycardMaxPairingSlotsReachedState, contro
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
controller.runRecoverAccountFlow()
method getNextSecondaryState*(self: KeycardMaxPairingSlotsReachedState, controller: Controller): State =
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
return createState(StateType.KeycardPluginReader, self.flowType, nil)
return nil
method resolveKeycardNextState*(self: KeycardMaxPairingSlotsReachedState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.resumeCurrentFlowLater()
return createState(StateType.KeycardPluginReader, FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard, self.getBackState)
if keycardFlowType == ResponseTypeValueInsertCard:
return createState(StateType.KeycardInsertKeycard, FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard, self.getBackState)
return ensureReaderAndCardPresenceAndResolveNextOnboardingState(self, keycardFlowType, keycardEvent, controller)

View File

@ -16,18 +16,6 @@ method executeSecondaryCommand*(self: KeycardMaxPukRetriesReachedState, controll
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
controller.runRecoverAccountFlow()
method getNextSecondaryState*(self: KeycardMaxPukRetriesReachedState, controller: Controller): State =
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
return createState(StateType.KeycardPluginReader, self.flowType, nil)
return nil
method resolveKeycardNextState*(self: KeycardMaxPukRetriesReachedState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.resumeCurrentFlowLater()
return createState(StateType.KeycardPluginReader, FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard, self.getBackState)
if keycardFlowType == ResponseTypeValueInsertCard:
return createState(StateType.KeycardInsertKeycard, FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard, self.getBackState)
return ensureReaderAndCardPresenceAndResolveNextOnboardingState(self, keycardFlowType, keycardEvent, controller)

View File

@ -18,14 +18,11 @@ method executeSecondaryCommand*(self: KeycardNotEmptyState, controller: Controll
self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
controller.runLoadAccountFlow()
method getNextSecondaryState*(self: KeycardNotEmptyState, controller: Controller): State =
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys or
self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
return createState(StateType.KeycardPluginReader, self.flowType, nil)
return nil
method resolveKeycardNextState*(self: KeycardNotEmptyState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceOnboarding(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys:
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and

View File

@ -8,20 +8,6 @@ proc newKeycardPluginReaderState*(flowType: FlowType, backState: State): Keycard
proc delete*(self: KeycardPluginReaderState) =
self.State.delete
method executePrimaryCommand*(self: KeycardPluginReaderState, controller: Controller) =
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys:
controller.runLoadAccountFlow()
elif self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
controller.runLoadAccountFlow()
elif self.flowType == FlowType.FirstRunOldUserKeycardImport:
controller.runRecoverAccountFlow()
method resolveKeycardNextState*(self: KeycardPluginReaderState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.resumeCurrentFlowLater()
return nil
if keycardFlowType == ResponseTypeValueInsertCard:
return createState(StateType.KeycardInsertKeycard, self.flowType, self.getBackState)
return ensureReaderAndCardPresenceAndResolveNextOnboardingState(self, keycardFlowType, keycardEvent, controller)

View File

@ -10,65 +10,4 @@ proc delete*(self: KeycardReadingKeycardState) =
method resolveKeycardNextState*(self: KeycardReadingKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys:
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorRequireInit:
return createState(StateType.KeycardCreatePin, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len == 0:
return createState(StateType.KeycardNotEmpty, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
(keycardEvent.error == ErrorHasKeys or
keycardEvent.error == RequestParamPUKRetries):
return createState(StateType.KeycardNotEmpty, self.flowType, self.getBackState)
if self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorRequireInit:
return createState(StateType.UserProfileEnterSeedPhrase, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len == 0:
return createState(StateType.KeycardNotEmpty, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
(keycardEvent.error == ErrorHasKeys or
keycardEvent.error == RequestParamPUKRetries):
return createState(StateType.KeycardNotEmpty, self.flowType, self.getBackState)
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len == 0:
return createState(StateType.KeycardEnterPin, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len == 0:
if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0:
return createState(StateType.KeycardMaxPinRetriesReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorNoKeys:
return createState(StateType.KeycardEmpty, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUKRetries:
return createState(StateType.KeycardMaxPukRetriesReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamFreeSlots:
return createState(StateType.KeycardMaxPairingSlotsReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorRequireInit:
return createState(StateType.KeycardCreatePin, self.flowType, self.getBackState)
if self.flowType == FlowType.AppLogin:
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUKRetries:
return createState(StateType.KeycardMaxPukRetriesReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorRequireInit:
return createState(StateType.KeycardCreatePin, self.flowType, self.getBackState)
return ensureReaderAndCardPresenceAndResolveNextOnboardingState(self, keycardFlowType, keycardEvent, controller)

View File

@ -26,6 +26,9 @@ method executePrimaryCommand*(self: KeycardRepeatPinState, controller: Controlle
method resolveKeycardNextState*(self: KeycardRepeatPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceOnboarding(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys:
if keycardFlowType == ResponseTypeValueEnterMnemonic and
keycardEvent.error.len > 0 and

View File

@ -20,6 +20,9 @@ method executePrimaryCommand*(self: KeycardWrongPinState, controller: Controller
method resolveKeycardNextState*(self: KeycardWrongPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceOnboarding(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len > 0 and

View File

@ -18,6 +18,9 @@ method executePrimaryCommand*(self: KeycardWrongPukState, controller: Controller
method resolveKeycardNextState*(self: KeycardWrongPukState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceOnboarding(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len > 0 and

View File

@ -10,21 +10,19 @@ proc delete*(self: LoginKeycardEmptyState) =
method executePrimaryCommand*(self: LoginKeycardEmptyState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
controller.runLoadAccountFlow(factoryReset = true)
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
else:
controller.runLoadAccountFlow(factoryReset = true)
method getNextSecondaryState*(self: LoginKeycardEmptyState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextTertiaryState*(self: LoginKeycardEmptyState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardEmptyState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
if self.flowType == FlowType.AppLogin:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.resumeCurrentFlowLater()
return createState(StateType.KeycardPluginReader, FlowType.FirstRunNewUserNewKeycardKeys, self)
if keycardFlowType == ResponseTypeValueInsertCard:
return createState(StateType.KeycardInsertKeycard, FlowType.FirstRunNewUserNewKeycardKeys, self)
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)

View File

@ -10,17 +10,24 @@ proc delete*(self: LoginKeycardEnterPinState) =
method executePrimaryCommand*(self: LoginKeycardEnterPinState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
if controller.getPin().len == PINLengthForStatusApp:
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
elif controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
method getNextSecondaryState*(self: LoginKeycardEnterPinState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextTertiaryState*(self: LoginKeycardEnterPinState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardEnterPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceLogin(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.AppLogin:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len == 0:

View File

@ -8,14 +8,24 @@ proc newLoginKeycardInsertKeycardState*(flowType: FlowType, backState: State): L
proc delete*(self: LoginKeycardInsertKeycardState) =
self.State.delete
method executePrimaryCommand*(self: LoginKeycardInsertKeycardState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
method getNextSecondaryState*(self: LoginKeycardInsertKeycardState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextTertiaryState*(self: LoginKeycardInsertKeycardState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardInsertKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceLogin(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if keycardFlowType == ResponseTypeValueInsertCard and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:

View File

@ -12,11 +12,18 @@ method executeBackCommand*(self: LoginKeycardMaxPinRetriesReachedState, controll
if self.flowType == FlowType.AppLogin and controller.isKeycardCreatedAccountSelectedOne():
controller.runLoginFlow()
method executePrimaryCommand*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
method getNextPrimaryState*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller): State =
return createState(StateType.KeycardRecover, self.flowType, self)
method getNextSecondaryState*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextTertiaryState*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)

View File

@ -11,45 +11,24 @@ proc delete*(self: LoginKeycardReadingKeycardState) =
self.State.delete
method executePrimaryCommand*(self: LoginKeycardReadingKeycardState, controller: Controller) =
if not controller.keychainErrorOccurred():
controller.enterKeycardPin(controller.getPin())
if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
elif not controller.keychainErrorOccurred():
controller.enterKeycardPin(controller.getPin())
method getNextPrimaryState*(self: LoginKeycardReadingKeycardState, controller: Controller): State =
if controller.keychainErrorOccurred():
return createState(StateType.LoginKeycardEnterPin, self.flowType, nil)
method getNextSecondaryState*(self: LoginKeycardReadingKeycardState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextTertiaryState*(self: LoginKeycardReadingKeycardState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardReadingKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
if self.flowType == FlowType.AppLogin:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len == 0:
controller.setKeycardEvent(keycardEvent)
controller.loginAccountKeycard()
return nil
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len == 0:
if not controller.keyUidMatch(keycardEvent.keyUid):
return createState(StateType.LoginKeycardWrongKeycard, self.flowType, nil)
let value = singletonInstance.localAccountSettings.getStoreToKeychainValue()
if value == LS_VALUE_STORE:
controller.tryToObtainDataFromKeychain()
return nil
return createState(StateType.LoginKeycardEnterPin, self.flowType, nil)
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len == 0:
if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0:
return createState(StateType.LoginKeycardMaxPinRetriesReached, self.flowType, nil)
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorNoKeys:
return createState(StateType.LoginKeycardEmpty, self.flowType, nil)
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUKRetries:
return createState(StateType.LoginKeycardMaxPukRetriesReached, self.flowType, nil)
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)

View File

@ -8,8 +8,15 @@ proc newLoginKeycardWrongKeycardState*(flowType: FlowType, backState: State): Lo
proc delete*(self: LoginKeycardWrongKeycardState) =
self.State.delete
method executePrimaryCommand*(self: LoginKeycardWrongKeycardState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
method getNextSecondaryState*(self: LoginKeycardWrongKeycardState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextTertiaryState*(self: LoginKeycardWrongKeycardState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)

View File

@ -12,17 +12,24 @@ proc delete*(self: LoginKeycardWrongPinState) =
method executePrimaryCommand*(self: LoginKeycardWrongPinState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
if controller.getPin().len == PINLengthForStatusApp:
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
elif controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
method getNextSecondaryState*(self: LoginKeycardWrongPinState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextTertiaryState*(self: LoginKeycardWrongPinState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardWrongPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceLogin(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.AppLogin:
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len > 0 and

View File

@ -9,21 +9,18 @@ proc delete*(self: LoginState) =
self.State.delete
method executePrimaryCommand*(self: LoginState, controller: Controller) =
controller.login()
if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
method getNextSecondaryState*(self: LoginState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextTertiaryState*(self: LoginState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
if self.flowType == FlowType.AppLogin:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.resumeCurrentFlowLater()
return nil
if keycardFlowType == ResponseTypeValueInsertCard:
return createState(StateType.LoginKeycardInsertKeycard, self.flowType, nil)
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)

View File

@ -82,6 +82,10 @@ proc newState*(self: State, flowType: FlowType, stateType: StateType, backState:
proc delete*(self: State) =
discard
## Returns flow type
method setFlowType*(self: State, flowType: FlowType) {.inline base.} =
self.flowType = flowType
## Returns flow type
method flowType*(self: State): FlowType {.inline base.} =
self.flowType

View File

@ -1,6 +1,7 @@
import chronicles
import ../../../../app_service/service/keycard/constants
import ../controller
from ../../../../app_service/service/keycard/service import KCSFlowType
from ../../../../app_service/service/keycard/service import PINLengthForStatusApp
from ../../../../app_service/service/keycard/service import PUKLengthForStatusApp
import state
@ -10,6 +11,10 @@ logScope:
# Forward declaration
proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: State): State
proc ensureReaderAndCardPresenceOnboarding*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State
proc ensureReaderAndCardPresenceLogin*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State
proc ensureReaderAndCardPresenceAndResolveNextOnboardingState*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State
proc ensureReaderAndCardPresenceAndResolveNextLoginState*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State
include biometrics_state
include keycard_create_pin_state
@ -131,4 +136,153 @@ proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: St
if stateToBeCreated == StateType.LoginKeycardEmpty:
return newLoginKeycardEmptyState(flowType, backState)
error "No implementation available for state ", state=stateToBeCreated
error "No implementation available for state ", state=stateToBeCreated
proc ensureReaderAndCardPresenceOnboarding*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State =
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.resumeCurrentFlowLater()
if state.stateType == StateType.KeycardPluginReader:
return nil
return createState(StateType.KeycardPluginReader, state.flowType, state)
if keycardFlowType == ResponseTypeValueInsertCard and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
if state.stateType == StateType.KeycardInsertKeycard:
return nil
return createState(StateType.KeycardInsertKeycard, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueCardInserted:
controller.setKeycardData("")
return createState(StateType.KeycardReadingKeycard, state.flowType, state.getBackState)
proc ensureReaderAndCardPresenceLogin*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State =
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.resumeCurrentFlowLater()
if state.stateType == StateType.Login:
return nil
return createState(StateType.Login, state.flowType, state)
if keycardFlowType == ResponseTypeValueInsertCard and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
if state.stateType == StateType.LoginKeycardInsertKeycard:
return nil
return createState(StateType.LoginKeycardInsertKeycard, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueCardInserted:
controller.setKeycardData("")
return createState(StateType.LoginKeycardReadingKeycard, state.flowType, state.getBackState)
proc ensureReaderAndCardPresenceAndResolveNextOnboardingState*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State =
let ensureState = ensureReaderAndCardPresenceOnboarding(state, keycardFlowType, keycardEvent, controller)
if not ensureState.isNil:
return ensureState
if state.flowType == FlowType.FirstRunNewUserNewKeycardKeys:
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorRequireInit:
return createState(StateType.KeycardCreatePin, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len == 0:
return createState(StateType.KeycardNotEmpty, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
(keycardEvent.error == ErrorHasKeys or
keycardEvent.error == RequestParamPUKRetries):
return createState(StateType.KeycardNotEmpty, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueEnterMnemonic and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorLoadingKeys:
controller.buildSeedPhrasesFromIndexes(keycardEvent.seedPhraseIndexes)
return createState(StateType.KeycardPinSet, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.keyUid.len > 0:
controller.setKeyUid(keycardEvent.keyUid)
return createState(StateType.UserProfileCreate, state.flowType, state)
if state.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorRequireInit:
return createState(StateType.KeycardCreatePin, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len == 0:
return createState(StateType.KeycardNotEmpty, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
(keycardEvent.error == ErrorHasKeys or
keycardEvent.error == RequestParamPUKRetries):
return createState(StateType.KeycardNotEmpty, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.keyUid.len > 0:
controller.setKeyUid(keycardEvent.keyUid)
return createState(StateType.KeycardPinSet, state.flowType, state.getBackState)
if state.flowType == FlowType.FirstRunOldUserKeycardImport:
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len == 0:
return createState(StateType.KeycardEnterPin, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len == 0:
if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0:
return createState(StateType.KeycardMaxPinRetriesReached, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorNoKeys:
return createState(StateType.KeycardEmpty, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUKRetries:
return createState(StateType.KeycardMaxPukRetriesReached, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamFreeSlots:
return createState(StateType.KeycardMaxPairingSlotsReached, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorRequireInit:
return createState(StateType.KeycardCreatePin, state.flowType, state.getBackState)
if state.flowType == FlowType.AppLogin:
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUKRetries:
return createState(StateType.KeycardMaxPukRetriesReached, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorRequireInit:
return createState(StateType.KeycardCreatePin, state.flowType, state.getBackState)
proc ensureReaderAndCardPresenceAndResolveNextLoginState*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State =
let ensureState = ensureReaderAndCardPresenceLogin(state, keycardFlowType, keycardEvent, controller)
if not ensureState.isNil:
return ensureState
if state.flowType == FlowType.AppLogin:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len == 0:
controller.setKeycardEvent(keycardEvent)
controller.loginAccountKeycard()
return nil
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len == 0:
if not controller.keyUidMatch(keycardEvent.keyUid):
return createState(StateType.LoginKeycardWrongKeycard, state.flowType, nil)
let value = singletonInstance.localAccountSettings.getStoreToKeychainValue()
if value == LS_VALUE_STORE:
controller.tryToObtainDataFromKeychain()
return nil
return createState(StateType.LoginKeycardEnterPin, state.flowType, nil)
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len == 0:
if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0:
return createState(StateType.LoginKeycardMaxPinRetriesReached, state.flowType, nil)
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorNoKeys:
return createState(StateType.LoginKeycardEmpty, state.flowType, nil)
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUKRetries:
return createState(StateType.LoginKeycardMaxPukRetriesReached, state.flowType, nil)

View File

@ -10,6 +10,10 @@ proc newUserProfileEnterSeedPhraseState*(flowType: FlowType, backState: State):
proc delete*(self: UserProfileEnterSeedPhraseState) =
self.State.delete
method executeBackCommand*(self: UserProfileEnterSeedPhraseState, controller: Controller) =
if self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
controller.cancelCurrentFlow()
method getNextPrimaryState*(self: UserProfileEnterSeedPhraseState, controller: Controller): State =
if not self.successfulImport:
return nil
@ -24,30 +28,10 @@ method executePrimaryCommand*(self: UserProfileEnterSeedPhraseState, controller:
self.successfulImport = controller.importMnemonic()
if self.successfulImport:
if self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
controller.storeSeedPhraseToKeycard(controller.getSeedPhraseLength(), controller.getSeedPhrase())
controller.runLoadAccountFlowWithSeedPhrase(controller.getSeedPhraseLength(), controller.getSeedPhrase(), factoryReset = true)
elif self.flowType == FlowType.FirstRunOldUserKeycardImport:
controller.runLoadAccountFlowWithSeedPhrase(controller.getSeedPhraseLength(), controller.getSeedPhrase(), factoryReset = true)
method resolveKeycardNextState*(self: UserProfileEnterSeedPhraseState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
if self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorRequireInit:
return createState(StateType.KeycardCreatePin, self.flowType, self.getBackState)
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.resumeCurrentFlowLater()
return createState(StateType.KeycardPluginReader, self.flowType, self)
if keycardFlowType == ResponseTypeValueInsertCard:
return createState(StateType.KeycardInsertKeycard, self.flowType, self.getBackState)
if self.flowType == FlowType.AppLogin:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.resumeCurrentFlowLater()
return createState(StateType.KeycardPluginReader, self.flowType, self)
if keycardFlowType == ResponseTypeValueInsertCard:
return createState(StateType.KeycardInsertKeycard, self.flowType, self.getBackState)
return ensureReaderAndCardPresenceAndResolveNextOnboardingState(self, keycardFlowType, keycardEvent, controller)

View File

@ -12,4 +12,12 @@ method getNextPrimaryState*(self: UserProfileImportSeedPhraseState, controller:
return createState(StateType.UserProfileEnterSeedPhrase, FlowType.FirstRunNewUserImportSeedPhrase, self)
method getNextSecondaryState*(self: UserProfileImportSeedPhraseState, controller: Controller): State =
return createState(StateType.KeycardPluginReader, FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard, self)
return createState(StateType.UserProfileEnterSeedPhrase, FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard, self.getBackState)
# method executeSecondaryCommand*(self: UserProfileImportSeedPhraseState, controller: Controller) =
# if self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
# controller.runLoadAccountFlow()
# method resolveKeycardNextState*(self: UserProfileImportSeedPhraseState, keycardFlowType: string, keycardEvent: KeycardEvent,
# controller: Controller): State =
# return ensureReaderAndCardPresenceAndResolveNextOnboardingState(self, keycardFlowType, keycardEvent, controller)

View File

@ -9,14 +9,21 @@ proc delete*(self: WelcomeStateNewUser) =
self.State.delete
method executeBackCommand*(self: WelcomeStateNewUser, controller: Controller) =
if self.flowType == FlowType.AppLogin and controller.isKeycardCreatedAccountSelectedOne():
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys:
controller.cancelCurrentFlow()
elif self.flowType == FlowType.AppLogin and controller.isKeycardCreatedAccountSelectedOne():
controller.runLoginFlow()
method executeSecondaryCommand*(self: WelcomeStateNewUser, controller: Controller) =
self.setFlowType(FlowType.FirstRunNewUserNewKeycardKeys)
controller.runLoadAccountFlow()
method getNextPrimaryState*(self: WelcomeStateNewUser, controller: Controller): State =
return createState(StateType.UserProfileCreate, FlowType.FirstRunNewUserNewKeys, self)
method getNextSecondaryState*(self: WelcomeStateNewUser, controller: Controller): State =
return createState(StateType.KeycardPluginReader, FlowType.FirstRunNewUserNewKeycardKeys, self)
method getNextTertiaryState*(self: WelcomeStateNewUser, controller: Controller): State =
return createState(StateType.UserProfileImportSeedPhrase, FlowType.General, self)
return createState(StateType.UserProfileImportSeedPhrase, FlowType.General, self)
method resolveKeycardNextState*(self: WelcomeStateNewUser, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
return ensureReaderAndCardPresenceAndResolveNextOnboardingState(self, keycardFlowType, keycardEvent, controller)

View File

@ -16,9 +16,13 @@ method getNextPrimaryState*(self: WelcomeStateOldUser, controller: Controller):
# We will handle here a click on `Scan sync code`
discard
method getNextSecondaryState*(self: WelcomeStateOldUser, controller: Controller): State =
return createState(StateType.KeycardPluginReader, FlowType.FirstRunOldUserKeycardImport, self)
method getNextTertiaryState*(self: WelcomeStateOldUser, controller: Controller): State =
return createState(StateType.UserProfileEnterSeedPhrase, FlowType.FirstRunOldUserImportSeedPhrase, self)
method executeSecondaryCommand*(self: WelcomeStateOldUser, controller: Controller) =
self.setFlowType(FlowType.FirstRunOldUserKeycardImport)
controller.runRecoverAccountFlow()
method resolveKeycardNextState*(self: WelcomeStateOldUser, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
return ensureReaderAndCardPresenceAndResolveNextOnboardingState(self, keycardFlowType, keycardEvent, controller)

View File

@ -16,6 +16,9 @@ method load*(self: AccessInterface) {.base.} =
method getKeycardSharedModule*(self: AccessInterface): QVariant {.base.} =
raise newException(ValueError, "No implementation available")
method onDisplayKeycardSharedModuleFlow*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method onSharedKeycarModuleFlowTerminated*(self: AccessInterface, lastStepInTheCurrentFlow: bool) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -29,6 +29,7 @@ type
controller: Controller
events: EventEmitter
keycardService: keycard_service.Service
accountsService: accounts_service.Service
keycardSharedModule: keycard_shared_module.AccessInterface
proc newModule*[T](delegate: T,
@ -43,6 +44,7 @@ proc newModule*[T](delegate: T,
result.delegate = delegate
result.events = events
result.keycardService = keycardService
result.accountsService = accountsService
result.view = view.newView(result)
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController(result, events, generalService, accountsService, keychainService,
@ -102,7 +104,8 @@ method getKeycardSharedModule*[T](self: Module[T]): QVariant =
return self.keycardSharedModule.getModuleAsVariant()
proc createSharedKeycardModule[T](self: Module[T]) =
self.keycardSharedModule = keycard_shared_module.newModule[Module[T]](self, self.events, self.keycardService)
self.keycardSharedModule = keycard_shared_module.newModule[Module[T]](self, self.events, self.keycardService,
privacyService = nil, self.accountsService, walletAccountService = nil)
proc isSharedKeycardModuleFlowRunning[T](self: Module[T]): bool =
return not self.keycardSharedModule.isNil
@ -220,7 +223,8 @@ method importAccountSuccess*[T](self: Module[T]) =
self.view.importAccountSuccess()
method setSelectedLoginAccount*[T](self: Module[T], item: login_acc_item.Item) =
self.controller.setSelectedLoginAccountKeyUid(item.getKeyUid())
self.controller.cancelCurrentFlow()
self.controller.setSelectedLoginAccount(item.getKeyUid(), item.getKeycardCreatedAccount())
if item.getKeycardCreatedAccount():
self.view.setCurrentStartupState(newLoginState(FlowType.AppLogin, nil)) # nim garbage collector will handle all abandoned state objects
self.controller.runLoginFlow()
@ -294,10 +298,16 @@ method setKeycardData*[T](self: Module[T], value: string) =
method runFactoryResetPopup*[T](self: Module[T]) =
self.createSharedKeycardModule()
self.view.emitRunKeycardSharedModuleFlow()
if self.keycardSharedModule.isNil:
return
self.keycardSharedModule.runFlow(keycard_shared_module.FlowType.FactoryReset)
method onDisplayKeycardSharedModuleFlow*[T](self: Module[T]) =
self.view.emitDisplayKeycardSharedModuleFlow()
method onSharedKeycarModuleFlowTerminated*[T](self: Module[T], lastStepInTheCurrentFlow: bool) =
if self.isSharedKeycardModuleFlowRunning():
self.controller.cancelCurrentFlow()
self.view.emitDestroyKeycardSharedModuleFlow()
self.keycardSharedModule.delete
self.keycardSharedModule = nil

View File

@ -242,9 +242,9 @@ QtObject:
read = getKeycardData
notify = keycardDataChanged
proc runKeycardSharedModuleFlow*(self: View) {.signal.}
proc emitRunKeycardSharedModuleFlow*(self: View) =
self.runKeycardSharedModuleFlow()
proc displayKeycardSharedModuleFlow*(self: View) {.signal.}
proc emitDisplayKeycardSharedModuleFlow*(self: View) =
self.displayKeycardSharedModuleFlow()
proc destroyKeycardSharedModuleFlow*(self: View) {.signal.}
proc emitDestroyKeycardSharedModuleFlow*(self: View) =

View File

@ -142,7 +142,7 @@ case of Keycard try recovering using PUK or reinstall the app and try login with
}
msgDialog.open()
}
onRunKeycardSharedModuleFlow: {
onDisplayKeycardSharedModuleFlow: {
keycardPopup.active = true
}
onDestroyKeycardSharedModuleFlow: {
@ -275,7 +275,6 @@ case of Keycard try recovering using PUK or reinstall the app and try login with
onLoaded: {
keycardPopup.item.open()
keycardPopup.item.sharedKeycardModule.runFactoryResetFlow()
}
}
}

View File

@ -14,12 +14,6 @@ Item {
property StartupStore startupStore
Component.onCompleted: {
if(root.startupStore.currentStartupState.stateType === Constants.startupState.keycardPluginReader) {
root.startupStore.doPrimaryAction()
}
}
QtObject {
id: d