feat(@desktop/keycard): detecting keycard reader removal for the beginning of each flow

Closes: #9117
This commit is contained in:
Sale Djenic 2023-03-03 11:24:04 +01:00 committed by saledjenic
parent 21a5b10fab
commit c5c19e6c34
12 changed files with 85 additions and 37 deletions

View File

@ -530,10 +530,15 @@ proc runLoadAccountFlow*(self: Controller, seedPhraseLength = 0, seedPhrase = ""
# self.cancelCurrentFlow()
# self.keycardService.startSignFlow(bip44Path, txHash)
proc resumeCurrentFlowLater*(self: Controller) =
proc reRunCurrentFlow*(self: Controller) =
if not serviceApplicable(self.keycardService):
return
self.keycardService.resumeCurrentFlowLater()
self.keycardService.reRunCurrentFlow()
proc reRunCurrentFlowLater*(self: Controller) =
if not serviceApplicable(self.keycardService):
return
self.keycardService.reRunCurrentFlowLater()
proc readyToDisplayPopup*(self: Controller) =
let data = SharedKeycarModuleBaseArgs(uniqueIdentifier: self.uniqueIdentifier)

View File

@ -14,14 +14,15 @@ proc ensureReaderAndCardPresence*(state: State, keycardFlowType: string, keycard
state.flowType == FlowType.ImportFromKeycard:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.resumeCurrentFlowLater()
keycardEvent.error == ErrorNoReader:
controller.reRunCurrentFlowLater()
if state.stateType == StateType.PluginReader:
return nil
return createState(StateType.PluginReader, state.flowType, nil)
if keycardFlowType == ResponseTypeValueInsertCard and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.reRunCurrentFlowLater()
if state.stateType == StateType.InsertKeycard:
return nil
return createState(StateType.InsertKeycard, state.flowType, nil)
@ -33,14 +34,16 @@ proc ensureReaderAndCardPresence*(state: State, keycardFlowType: string, keycard
if state.flowType == FlowType.SetupNewKeycard:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.resumeCurrentFlowLater()
keycardEvent.error == ErrorConnection or
keycardEvent.error == ErrorNoReader:
controller.reRunCurrentFlowLater()
if state.stateType == StateType.PluginReader:
return nil
return createState(StateType.PluginReader, state.flowType, state)
if keycardFlowType == ResponseTypeValueInsertCard and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.reRunCurrentFlowLater()
if state.stateType == StateType.InsertKeycard:
return nil
if state.stateType == StateType.SelectExistingKeyPair:

View File

@ -507,8 +507,11 @@ proc runGetMetadataFlow*(self: Controller, resolveAddress = false, exportMasterA
proc resumeCurrentFlow*(self: Controller) =
self.keycardService.resumeCurrentFlow()
proc resumeCurrentFlowLater*(self: Controller) =
self.keycardService.resumeCurrentFlowLater()
proc reRunCurrentFlow*(self: Controller) =
self.keycardService.reRunCurrentFlow()
proc reRunCurrentFlowLater*(self: Controller) =
self.keycardService.reRunCurrentFlowLater()
proc runFactoryResetPopup*(self: Controller) =
self.delegate.runFactoryResetPopup()

View File

@ -17,4 +17,5 @@ method executeBackCommand*(self: KeycardPluginReaderState, controller: Controlle
method resolveKeycardNextState*(self: KeycardPluginReaderState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
controller.setKeycardData("")
return ensureReaderAndCardPresenceAndResolveNextOnboardingState(self, keycardFlowType, keycardEvent, controller)

View File

@ -25,7 +25,7 @@ method getNextQuinaryState*(self: LoginKeycardInsertKeycardState, controller: Co
method resolveKeycardNextState*(self: LoginKeycardInsertKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceLogin(self, keycardFlowType, keycardEvent, controller)
let state = ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if keycardFlowType == ResponseTypeValueInsertCard and

View File

@ -25,4 +25,5 @@ method getNextQuinaryState*(self: LoginPluginState, controller: Controller): Sta
method resolveKeycardNextState*(self: LoginPluginState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
controller.setKeycardData("")
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)

View File

@ -1,6 +1,7 @@
import sequtils, sugar, chronicles
import ../../../global/global_singleton
import ../../../../constants as main_constants
import ../../../../app_service/common/utils as common_utils
import ../../../../app_service/service/keycard/constants
import ../controller
from ../../../../app_service/service/keycard/service import KCSFlowType
@ -18,6 +19,7 @@ logScope:
# General section
proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: State): State
proc findBackStateWithTargetedStateType*(currentState: State, targetedStateType: StateType): State
proc findBackStateWhichDoesNotBelongToAnyOfReadingStates*(currentState: State): State
# Resolve state section
proc ensureReaderAndCardPresenceOnboarding*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State
proc ensureReaderAndCardPresenceLogin*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State

View File

@ -128,4 +128,32 @@ proc findBackStateWithTargetedStateType*(currentState: State, targetedStateType:
if state.stateType == targetedStateType:
return state
state = state.getBackState
return nil
proc findBackStateWhichDoesNotBelongToAnyOfReadingStates*(currentState: State): State =
if currentState.isNil:
return nil
var state = currentState
const onboardingReadingStates = @[
StateType.KeycardPluginReader,
StateType.KeycardInsertKeycard,
StateType.KeycardInsertedKeycard,
StateType.KeycardReadingKeycard,
StateType.KeycardRecognizedKeycard
]
const loginReadingStates = @[
StateType.Login,
StateType.LoginPlugin,
StateType.LoginKeycardInsertKeycard,
StateType.LoginKeycardInsertedKeycard,
StateType.LoginKeycardReadingKeycard,
StateType.LoginKeycardRecognizedKeycard
]
while not state.isNil:
if not common_utils.arrayContains(onboardingReadingStates, state.stateType) and
not common_utils.arrayContains(loginReadingStates, state.stateType):
return state
state = state.getBackState
return nil

View File

@ -1,20 +1,22 @@
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.LoginPlugin:
return nil
return createState(StateType.LoginPlugin, state.flowType, nil)
keycardEvent.error.len > 0:
if keycardEvent.error == ErrorNoReader:
controller.reRunCurrentFlowLater()
if state.stateType == StateType.LoginPlugin:
return nil
return createState(StateType.LoginPlugin, state.flowType, nil)
if keycardFlowType == ResponseTypeValueInsertCard and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.reRunCurrentFlowLater()
if state.stateType == StateType.LoginKeycardInsertKeycard:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WronglyInsertedCard, add = true))
return nil
return createState(StateType.LoginKeycardInsertKeycard, state.flowType, state.getBackState)
return createState(StateType.LoginKeycardInsertKeycard, state.flowType, nil)
if keycardFlowType == ResponseTypeValueCardInserted:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WronglyInsertedCard, add = false))
return createState(StateType.LoginKeycardInsertedKeycard, state.flowType, state.getBackState)
return createState(StateType.LoginKeycardInsertedKeycard, state.flowType, nil)
proc ensureReaderAndCardPresenceAndResolveNextLoginState*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State =
let ensureState = ensureReaderAndCardPresenceLogin(state, keycardFlowType, keycardEvent, controller)

View File

@ -1,31 +1,22 @@
proc ensureReaderAndCardPresenceOnboarding*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State =
var defaultBackState = state
if state.flowType == FlowType.FirstRunNewUserNewKeycardKeys and
state.stateType == StateType.KeycardEmpty:
## `KeycardEmpty` state is known in the context of `FirstRunNewUserNewKeycardKeys` only if we jump to it from
## `FirstRunOldUserKeycardImport` flow, in that case we need to set back state appropriatelly respecting different flow.
defaultBackState = state.getBackState
let backState = findBackStateWhichDoesNotBelongToAnyOfReadingStates(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, defaultBackState)
keycardEvent.error.len > 0:
if keycardEvent.error == ErrorNoReader:
controller.reRunCurrentFlowLater()
if state.stateType == StateType.KeycardPluginReader:
return nil
return createState(StateType.KeycardPluginReader, state.flowType, backState)
if keycardFlowType == ResponseTypeValueInsertCard and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.reRunCurrentFlowLater()
if state.stateType == StateType.KeycardInsertKeycard:
return nil
if state.stateType == StateType.KeycardPluginReader:
return createState(StateType.KeycardInsertKeycard, state.flowType, state.getBackState)
return createState(StateType.KeycardInsertKeycard, state.flowType, defaultBackState)
return createState(StateType.KeycardInsertKeycard, state.flowType, backState)
if keycardFlowType == ResponseTypeValueCardInserted:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WronglyInsertedCard, add = false))
if state.stateType == StateType.KeycardInsertKeycard:
return createState(StateType.KeycardInsertedKeycard, state.flowType, state.getBackState)
return createState(StateType.KeycardInsertedKeycard, state.flowType, defaultBackState)
return createState(StateType.KeycardInsertedKeycard, state.flowType, backState)
proc ensureReaderAndCardPresenceAndResolveNextOnboardingState*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State =
let ensureState = ensureReaderAndCardPresenceOnboarding(state, keycardFlowType, keycardEvent, controller)

View File

@ -18,6 +18,9 @@ const ErrorNoData* = "no-data"
const ErrorFreePairingSlots* = "free-pairing-slots"
const ErrorPIN* = "pin"
const ErrorPUKRetries* = "puk-retries"
const ErrorPCSC* = "no-pcsc"
const ErrorReaderList* = "no-reader-list"
const ErrorNoReader* = "no-reader-found"
const RequestParamAppInfo* = "application-info"
const RequestParamInstanceUID* = "instance-uid"

View File

@ -380,5 +380,14 @@ QtObject:
var payload = %* { }
self.resumeFlow(payload)
proc resumeCurrentFlowLater*(self: Service) =
proc reRunCurrentFlow*(self: Service) =
let tmpFlow = self.currentFlow
self.cancelCurrentFlow()
self.currentFlow = tmpFlow
self.startFlow(self.setPayloadForCurrentFlow)
proc reRunCurrentFlowLater*(self: Service) =
let tmpFlow = self.currentFlow
self.cancelCurrentFlow()
self.currentFlow = tmpFlow
self.runTimer()