feat(@desktop/keycard): no `pcsc` service error screen

Closes: #9116
This commit is contained in:
Sale Djenic 2023-03-03 11:24:50 +01:00 committed by saledjenic
parent c5c19e6c34
commit d5cddbf79a
19 changed files with 220 additions and 0 deletions

View File

@ -0,0 +1,19 @@
type
NoPCSCServiceState* = ref object of State
proc newNoPCSCServiceState*(flowType: FlowType, backState: State): NoPCSCServiceState =
result = NoPCSCServiceState()
result.setup(flowType, StateType.NoPCSCService, backState)
proc delete*(self: NoPCSCServiceState) =
self.State.delete
method executeCancelCommand*(self: NoPCSCServiceState, controller: Controller) =
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
method executePrePrimaryStateCommand*(self: NoPCSCServiceState, controller: Controller) =
controller.reRunCurrentFlow()
method resolveKeycardNextState*(self: NoPCSCServiceState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
return ensureReaderAndCardPresenceAndResolveNextState(self, keycardFlowType, keycardEvent, controller)

View File

@ -6,6 +6,7 @@ export FlowType, KeycardEvent, KeyDetails
type StateType* {.pure.} = enum
NoState = "NoState"
NoPCSCService = "NoPCSCService"
PluginReader = "PluginReader"
ReadingKeycard = "ReadingKeycard"
InsertKeycard = "InsertKeycard"

View File

@ -89,6 +89,7 @@ include max_pin_retries_reached_state
include max_puk_retries_reached_state
include max_pairing_slots_reached_state
include migrating_key_pair_state
include no_pcsc_service_state
include not_keycard_state
include pin_set_state
include pin_verified_state

View File

@ -145,6 +145,8 @@ proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: St
return newMaxPairingSlotsReachedState(flowType, backState)
if stateToBeCreated == StateType.MigratingKeyPair:
return newMigratingKeyPairState(flowType, backState)
if stateToBeCreated == StateType.NoPCSCService:
return newNoPCSCServiceState(flowType, backState)
if stateToBeCreated == StateType.NotKeycard:
return newNotKeycardState(flowType, backState)
if stateToBeCreated == StateType.ManageKeycardAccounts:

View File

@ -1,4 +1,9 @@
proc ensureReaderAndCardPresence*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State =
## Check for some specific errors
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorPCSC:
return createState(StateType.NoPCSCService, state.flowType, nil)
## Handling factory reset or authentication or unlock keycard flow
if state.flowType == FlowType.FactoryReset or
state.flowType == FlowType.Authentication or

View File

@ -0,0 +1,18 @@
type
KeycardNoPCSCServiceState* = ref object of State
proc newKeycardNoPCSCServiceState*(flowType: FlowType, backState: State): KeycardNoPCSCServiceState =
result = KeycardNoPCSCServiceState()
result.setup(flowType, StateType.KeycardNoPCSCService, backState)
proc delete*(self: KeycardNoPCSCServiceState) =
self.State.delete
method executeBackCommand*(self: KeycardNoPCSCServiceState, controller: Controller) =
controller.cancelCurrentFlow()
method executePrimaryCommand*(self: KeycardNoPCSCServiceState, controller: Controller) =
controller.reRunCurrentFlow()
method getNextPrimaryState*(self: KeycardNoPCSCServiceState, controller: Controller): State =
return self.getBackState

View File

@ -0,0 +1,32 @@
type
LoginNoPCSCServiceState* = ref object of State
proc newLoginNoPCSCServiceState*(flowType: FlowType, backState: State): LoginNoPCSCServiceState =
result = LoginNoPCSCServiceState()
result.setup(flowType, StateType.LoginNoPCSCService, backState)
proc delete*(self: LoginNoPCSCServiceState) =
self.State.delete
method executePrimaryCommand*(self: LoginNoPCSCServiceState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
controller.runLoadAccountFlow(seedPhraseLength = 0, seedPhrase = "", pin = "", puk = "", factoryReset = true)
method getNextTertiaryState*(self: LoginNoPCSCServiceState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextQuaternaryState*(self: LoginNoPCSCServiceState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method getNextQuinaryState*(self: LoginNoPCSCServiceState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.LostKeycardOptions, self.flowType, self)
method resolveKeycardNextState*(self: LoginNoPCSCServiceState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)

View File

@ -32,6 +32,7 @@ type StateType* {.pure.} = enum
UserProfileEnterSeedPhrase = "UserProfileEnterSeedPhrase"
UserProfileWrongSeedPhrase = "UserProfileWrongSeedPhrase"
Biometrics = "Biometrics"
KeycardNoPCSCService = "KeycardNoPCSCService"
KeycardPluginReader = "KeycardPluginReader"
KeycardInsertKeycard = "KeycardInsertKeycard"
KeycardInsertedKeycard = "KeycardInsertedKeycard"
@ -56,6 +57,7 @@ type StateType* {.pure.} = enum
KeycardMaxPinRetriesReached = "KeycardMaxPinRetriesReached"
KeycardMaxPukRetriesReached = "KeycardMaxPukRetriesReached"
Login = "Login"
LoginNoPCSCService = "LoginNoPCSCService"
LoginPlugin = "LoginPlugin"
LoginKeycardInsertKeycard = "LoginKeycardInsertKeycard"
LoginKeycardInsertedKeycard = "LoginKeycardInsertedKeycard"

View File

@ -27,6 +27,7 @@ proc ensureReaderAndCardPresenceAndResolveNextOnboardingState*(state: State, key
proc ensureReaderAndCardPresenceAndResolveNextLoginState*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State
include biometrics_state
include keycard_no_pcsc_service_state
include keycard_create_pin_state
include keycard_display_seed_phrase_state
include keycard_empty_state
@ -63,6 +64,7 @@ include welcome_state_new_user
include welcome_state_old_user
include welcome_state
include login_state
include login_no_pcsc_service_state
include login_plugin_state
include login_keycard_converted_to_regular_account_state
include login_keycard_insert_keycard_state

View File

@ -57,6 +57,8 @@ proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: St
return newKeycardEnterSeedPhraseWordsState(flowType, backState)
if stateToBeCreated == StateType.KeycardNotEmpty:
return newKeycardNotEmptyState(flowType, backState)
if stateToBeCreated == StateType.KeycardNoPCSCService:
return newKeycardNoPCSCServiceState(flowType, backState)
if stateToBeCreated == StateType.KeycardNotKeycard:
return newKeycardNotKeycardState(flowType, backState)
if stateToBeCreated == StateType.KeycardEmpty:
@ -103,6 +105,8 @@ proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: St
return newLoginKeycardMaxPairingSlotsReachedState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardEmpty:
return newLoginKeycardEmptyState(flowType, backState)
if stateToBeCreated == StateType.LoginNoPCSCService:
return newLoginNoPCSCServiceState(flowType, backState)
if stateToBeCreated == StateType.LoginNotKeycard:
return newLoginNotKeycardState(flowType, backState)
if stateToBeCreated == StateType.ProfileFetching:

View File

@ -1,6 +1,8 @@
proc ensureReaderAndCardPresenceLogin*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State =
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0:
if keycardEvent.error == ErrorPCSC:
return createState(StateType.LoginNoPCSCService, state.flowType, nil)
if keycardEvent.error == ErrorNoReader:
controller.reRunCurrentFlowLater()
if state.stateType == StateType.LoginPlugin:

View File

@ -2,6 +2,8 @@ proc ensureReaderAndCardPresenceOnboarding*(state: State, keycardFlowType: strin
let backState = findBackStateWhichDoesNotBelongToAnyOfReadingStates(state)
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0:
if keycardEvent.error == ErrorPCSC:
return createState(StateType.KeycardNoPCSCService, state.flowType, backState)
if keycardEvent.error == ErrorNoReader:
controller.reRunCurrentFlowLater()
if state.stateType == StateType.KeycardPluginReader:

View File

@ -66,6 +66,7 @@ OnboardingBasePage {
return seedPhraseInputViewComponent
case Constants.startupState.login:
case Constants.startupState.loginNoPCSCService:
case Constants.startupState.loginPlugin:
case Constants.startupState.loginKeycardInsertKeycard:
case Constants.startupState.loginKeycardInsertedKeycard:
@ -104,6 +105,7 @@ OnboardingBasePage {
case Constants.startupState.keycardEnterSeedPhraseWords:
return seedphraseWordsInputViewComponent
case Constants.startupState.keycardNoPCSCService:
case Constants.startupState.keycardNotEmpty:
case Constants.startupState.keycardNotKeycard:
case Constants.startupState.keycardEmpty:

View File

@ -199,6 +199,43 @@ Item {
font.pixelSize: Constants.keycard.general.fontSize2
}
},
State {
name: Constants.startupState.keycardNoPCSCService
when: root.startupStore.currentStartupState.stateType === Constants.startupState.keycardNoPCSCService
PropertyChanges {
target: image
pattern: Constants.keycardAnimations.strongError.pattern
source: ""
startImgIndexForTheFirstLoop: Constants.keycardAnimations.strongError.startImgIndexForTheFirstLoop
startImgIndexForOtherLoops: Constants.keycardAnimations.strongError.startImgIndexForOtherLoops
endImgIndex: Constants.keycardAnimations.strongError.endImgIndex
duration: Constants.keycardAnimations.strongError.duration
loops: Constants.keycardAnimations.strongError.loops
}
PropertyChanges {
target: title
text: qsTr("PCSC not available")
color: Theme.palette.directColor1
font.pixelSize: Constants.keycard.general.fontSize1
}
PropertyChanges {
target: info
text: qsTr("The Smartcard reader (PCSC service), required\nfor using Keycard, is not currently working.\nEnsure PCSC is installed and running and try again")
color: Theme.palette.directColor1
}
PropertyChanges {
target: button
text: qsTr("Retry")
}
PropertyChanges {
target: link
text: ""
}
PropertyChanges {
target: message
text: ""
}
},
State {
name: Constants.startupState.keycardNotKeycard
when: root.startupStore.currentStartupState.stateType === Constants.startupState.keycardNotKeycard

View File

@ -1214,6 +1214,58 @@ Item {
visible: true
}
},
State {
name: Constants.startupState.loginNoPCSCService
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginNoPCSCService
PropertyChanges {
target: image
pattern: Constants.keycardAnimations.strongError.pattern
source: ""
startImgIndexForTheFirstLoop: Constants.keycardAnimations.strongError.startImgIndexForTheFirstLoop
startImgIndexForOtherLoops: Constants.keycardAnimations.strongError.startImgIndexForOtherLoops
endImgIndex: Constants.keycardAnimations.strongError.endImgIndex
duration: Constants.keycardAnimations.strongError.duration
loops: Constants.keycardAnimations.strongError.loops
}
PropertyChanges {
target: title
text: ""
visible: false
}
PropertyChanges {
target: passwordSection
visible: false
}
PropertyChanges {
target: pinSection
visible: false
}
PropertyChanges {
target: info
text: qsTr("PCSC not available")
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.dangerColor1
height: Constants.keycard.general.loginInfoHeight1
icon: ""
}
PropertyChanges {
target: message
text: qsTr("The Smartcard reader (PCSC service), required\nfor using Keycard, is not currently working.\nEnsure PCSC is installed and running and try again")
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
}
PropertyChanges {
target: button
text: qsTr("Retry")
}
PropertyChanges {
target: link
text: ""
visible: false
}
},
State {
name: Constants.startupState.loginNotKeycard
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginNotKeycard

View File

@ -24,6 +24,7 @@ Item {
anchors.fill: parent
sourceComponent: {
switch (root.sharedKeycardModule.currentState.stateType) {
case Constants.keycardSharedState.noPCSCService:
case Constants.keycardSharedState.pluginReader:
case Constants.keycardSharedState.insertKeycard:
case Constants.keycardSharedState.keycardInserted:

View File

@ -71,6 +71,10 @@ QtObject {
normalColor: "transparent"
text: qsTr("Cancel")
visible: {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.noPCSCService) {
return true
}
switch (root.sharedKeycardModule.currentState.flowType) {
case Constants.keycardSharedFlow.setupNewKeycard:
@ -516,6 +520,10 @@ QtObject {
objectName: "PrimaryButton"
height: Constants.keycard.general.footerButtonsHeight
text: {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.noPCSCService) {
return qsTr("Retry")
}
switch (root.sharedKeycardModule.currentState.flowType) {
case Constants.keycardSharedFlow.setupNewKeycard:

View File

@ -632,6 +632,33 @@ Item {
text: ""
}
},
State {
name: Constants.keycardSharedState.noPCSCService
when: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.noPCSCService
PropertyChanges {
target: title
text: qsTr("PCSC not available")
font.pixelSize: Constants.keycard.general.fontSize1
font.weight: Font.Bold
color: Theme.palette.dangerColor1
}
PropertyChanges {
target: image
pattern: Constants.keycardAnimations.strongError.pattern
source: ""
startImgIndexForTheFirstLoop: Constants.keycardAnimations.strongError.startImgIndexForTheFirstLoop
startImgIndexForOtherLoops: Constants.keycardAnimations.strongError.startImgIndexForOtherLoops
endImgIndex: Constants.keycardAnimations.strongError.endImgIndex
duration: Constants.keycardAnimations.strongError.duration
loops: Constants.keycardAnimations.strongError.loops
}
PropertyChanges {
target: message
text: qsTr("The Smartcard reader (PCSC service), required\nfor using Keycard, is not currently working.\nEnsure PCSC is installed and running and try again")
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.dangerColor1
}
},
State {
name: Constants.keycardSharedState.notKeycard
when: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.notKeycard

View File

@ -43,6 +43,7 @@ QtObject {
readonly property string userProfileEnterSeedPhrase: "UserProfileEnterSeedPhrase"
readonly property string userProfileWrongSeedPhrase: "UserProfileWrongSeedPhrase"
readonly property string biometrics: "Biometrics"
readonly property string keycardNoPCSCService: "KeycardNoPCSCService"
readonly property string keycardPluginReader: "KeycardPluginReader"
readonly property string keycardInsertKeycard: "KeycardInsertKeycard"
readonly property string keycardInsertedKeycard: "KeycardInsertedKeycard"
@ -67,6 +68,7 @@ QtObject {
readonly property string keycardMaxPinRetriesReached: "KeycardMaxPinRetriesReached"
readonly property string keycardMaxPukRetriesReached: "KeycardMaxPukRetriesReached"
readonly property string login: "Login"
readonly property string loginNoPCSCService: "LoginNoPCSCService"
readonly property string loginPlugin: "LoginPlugin"
readonly property string loginKeycardInsertKeycard: "LoginKeycardInsertKeycard"
readonly property string loginKeycardInsertedKeycard: "LoginKeycardInsertedKeycard"
@ -120,6 +122,7 @@ QtObject {
}
readonly property QtObject keycardSharedState: QtObject {
readonly property string noPCSCService: "NoPCSCService"
readonly property string noState: "NoState"
readonly property string pluginReader: "PluginReader"
readonly property string readingKeycard: "ReadingKeycard"