From c5c19e6c3433d32f4412f37663a7e6edb31e7977 Mon Sep 17 00:00:00 2001 From: Sale Djenic Date: Fri, 3 Mar 2023 11:24:04 +0100 Subject: [PATCH] feat(@desktop/keycard): detecting keycard reader removal for the beginning of each flow Closes: #9117 --- .../keycard_popup/controller.nim | 9 ++++-- .../state_factory_state_implementation.nim | 11 ++++--- src/app/modules/startup/controller.nim | 7 +++-- .../internal/keycard_plugin_reader_state.nim | 1 + .../login_keycard_insert_keycard_state.nim | 2 +- .../startup/internal/login_plugin_state.nim | 1 + .../startup/internal/state_factory.nim | 2 ++ .../state_factory_general_implementation.nim | 28 ++++++++++++++++++ .../state_factory_login_implementation.nim | 18 +++++++----- ...tate_factory_onboarding_implementation.nim | 29 +++++++------------ src/app_service/service/keycard/constants.nim | 3 ++ src/app_service/service/keycard/service.nim | 11 ++++++- 12 files changed, 85 insertions(+), 37 deletions(-) diff --git a/src/app/modules/shared_modules/keycard_popup/controller.nim b/src/app/modules/shared_modules/keycard_popup/controller.nim index 9a3727df2c..9ad7274041 100644 --- a/src/app/modules/shared_modules/keycard_popup/controller.nim +++ b/src/app/modules/shared_modules/keycard_popup/controller.nim @@ -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) diff --git a/src/app/modules/shared_modules/keycard_popup/internal/state_factory_state_implementation.nim b/src/app/modules/shared_modules/keycard_popup/internal/state_factory_state_implementation.nim index c88efc5082..4930a7d713 100644 --- a/src/app/modules/shared_modules/keycard_popup/internal/state_factory_state_implementation.nim +++ b/src/app/modules/shared_modules/keycard_popup/internal/state_factory_state_implementation.nim @@ -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: diff --git a/src/app/modules/startup/controller.nim b/src/app/modules/startup/controller.nim index 6e57ffc776..7fc5c0248a 100644 --- a/src/app/modules/startup/controller.nim +++ b/src/app/modules/startup/controller.nim @@ -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() diff --git a/src/app/modules/startup/internal/keycard_plugin_reader_state.nim b/src/app/modules/startup/internal/keycard_plugin_reader_state.nim index ac98dce2a4..1d5d02849e 100644 --- a/src/app/modules/startup/internal/keycard_plugin_reader_state.nim +++ b/src/app/modules/startup/internal/keycard_plugin_reader_state.nim @@ -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) \ No newline at end of file diff --git a/src/app/modules/startup/internal/login_keycard_insert_keycard_state.nim b/src/app/modules/startup/internal/login_keycard_insert_keycard_state.nim index d33cf5e51d..7e90c6507b 100644 --- a/src/app/modules/startup/internal/login_keycard_insert_keycard_state.nim +++ b/src/app/modules/startup/internal/login_keycard_insert_keycard_state.nim @@ -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 diff --git a/src/app/modules/startup/internal/login_plugin_state.nim b/src/app/modules/startup/internal/login_plugin_state.nim index 2f875efba7..0e77773aec 100644 --- a/src/app/modules/startup/internal/login_plugin_state.nim +++ b/src/app/modules/startup/internal/login_plugin_state.nim @@ -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) \ No newline at end of file diff --git a/src/app/modules/startup/internal/state_factory.nim b/src/app/modules/startup/internal/state_factory.nim index 5eeb6c8690..4df016de50 100644 --- a/src/app/modules/startup/internal/state_factory.nim +++ b/src/app/modules/startup/internal/state_factory.nim @@ -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 diff --git a/src/app/modules/startup/internal/state_factory_general_implementation.nim b/src/app/modules/startup/internal/state_factory_general_implementation.nim index 267e6f7c9c..8b4f0638d5 100644 --- a/src/app/modules/startup/internal/state_factory_general_implementation.nim +++ b/src/app/modules/startup/internal/state_factory_general_implementation.nim @@ -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 \ No newline at end of file diff --git a/src/app/modules/startup/internal/state_factory_login_implementation.nim b/src/app/modules/startup/internal/state_factory_login_implementation.nim index 736cdc95cf..a661dfeba8 100644 --- a/src/app/modules/startup/internal/state_factory_login_implementation.nim +++ b/src/app/modules/startup/internal/state_factory_login_implementation.nim @@ -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) diff --git a/src/app/modules/startup/internal/state_factory_onboarding_implementation.nim b/src/app/modules/startup/internal/state_factory_onboarding_implementation.nim index 0236456b82..e0fab156fd 100644 --- a/src/app/modules/startup/internal/state_factory_onboarding_implementation.nim +++ b/src/app/modules/startup/internal/state_factory_onboarding_implementation.nim @@ -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) diff --git a/src/app_service/service/keycard/constants.nim b/src/app_service/service/keycard/constants.nim index 6f8af7b818..c162037d03 100644 --- a/src/app_service/service/keycard/constants.nim +++ b/src/app_service/service/keycard/constants.nim @@ -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" diff --git a/src/app_service/service/keycard/service.nim b/src/app_service/service/keycard/service.nim index b0f19fa765..01aef0253e 100644 --- a/src/app_service/service/keycard/service.nim +++ b/src/app_service/service/keycard/service.nim @@ -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() \ No newline at end of file