feat(@desktop/onboarding): `Lost Keycard` - `Create replacement Keycard with seed phrase` flow
This commit introduces: - `Create replacement Keycard with seed phrase` flow - `Order new keycard` option Closes: #7641
This commit is contained in:
parent
d3fffac4be
commit
3ca03bdd49
|
@ -47,6 +47,7 @@ logScope:
|
|||
type
|
||||
AppController* = ref object of RootObj
|
||||
storeKeyPair: bool
|
||||
syncWalletForReplacedKeycard: bool
|
||||
statusFoundation: StatusFoundation
|
||||
notificationsManager*: NotificationsManager
|
||||
|
||||
|
@ -108,6 +109,7 @@ proc userLoggedIn*(self: AppController): string
|
|||
proc logout*(self: AppController)
|
||||
proc finishAppLoading*(self: AppController)
|
||||
proc storeKeyPairForNewKeycardUser*(self: AppController)
|
||||
proc syncWalletAccountsOnLoginForReplacedKeycard*(self: AppController)
|
||||
|
||||
# Main Module Delegate Interface
|
||||
proc mainDidLoad*(self: AppController)
|
||||
|
@ -130,6 +132,7 @@ proc connect(self: AppController) =
|
|||
proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
||||
result = AppController()
|
||||
result.storeKeyPair = false
|
||||
result.syncWalletForReplacedKeycard = false
|
||||
result.statusFoundation = statusFoundation
|
||||
|
||||
# Preparing settings service to be exposed later as global QObject
|
||||
|
@ -434,25 +437,54 @@ proc buildAndRegisterUserProfile(self: AppController) =
|
|||
|
||||
singletonInstance.engine.setRootContextProperty("userProfile", self.userProfileVariant)
|
||||
|
||||
if self.storeKeyPair and singletonInstance.userProfile.getIsKeycardUser():
|
||||
let allAccounts = self.walletAccountService.fetchAccounts()
|
||||
let defaultWalletAccounts = allAccounts.filter(a =>
|
||||
a.walletType == WalletTypeDefaultStatusAccount and
|
||||
a.path == account_constants.PATH_DEFAULT_WALLET and
|
||||
not a.isChat and
|
||||
a.isWallet
|
||||
)
|
||||
if defaultWalletAccounts.len == 0:
|
||||
error "default wallet account was not generated"
|
||||
return
|
||||
let defaultWalletAddress = defaultWalletAccounts[0].address
|
||||
let keyPair = KeyPairDto(keycardUid: self.keycardService.getLastReceivedKeycardData().flowEvent.instanceUID,
|
||||
keycardName: displayName,
|
||||
keycardLocked: false,
|
||||
accountsAddresses: @[defaultWalletAddress],
|
||||
keyUid: loggedInAccount.keyUid)
|
||||
let keystoreDir = self.accountsService.getKeyStoreDir()
|
||||
discard self.walletAccountService.addMigratedKeyPair(keyPair, keystoreDir)
|
||||
if singletonInstance.userProfile.getIsKeycardUser():
|
||||
if self.storeKeyPair:
|
||||
let allAccounts = self.walletAccountService.fetchAccounts()
|
||||
let defaultWalletAccounts = allAccounts.filter(a =>
|
||||
a.walletType == WalletTypeDefaultStatusAccount and
|
||||
a.path == account_constants.PATH_DEFAULT_WALLET and
|
||||
not a.isChat and
|
||||
a.isWallet
|
||||
)
|
||||
if defaultWalletAccounts.len == 0:
|
||||
error "default wallet account was not generated"
|
||||
return
|
||||
let defaultWalletAddress = defaultWalletAccounts[0].address
|
||||
let keyPair = KeyPairDto(keycardUid: self.keycardService.getLastReceivedKeycardData().flowEvent.instanceUID,
|
||||
keycardName: displayName,
|
||||
keycardLocked: false,
|
||||
accountsAddresses: @[defaultWalletAddress],
|
||||
keyUid: loggedInAccount.keyUid)
|
||||
let keystoreDir = self.accountsService.getKeyStoreDir()
|
||||
discard self.walletAccountService.addMigratedKeyPair(keyPair, keystoreDir)
|
||||
if self.syncWalletForReplacedKeycard:
|
||||
let allAccounts = self.walletAccountService.fetchAccounts()
|
||||
let accountsForLoggedInUser = allAccounts.filter(a => a.keyUid == loggedInAccount.keyUid)
|
||||
var kpDto = KeyPairDto(keycardUid: "",
|
||||
keycardName: displayName,
|
||||
keycardLocked: false,
|
||||
accountsAddresses: @[],
|
||||
keyUid: loggedInAccount.keyUid)
|
||||
var activeValidPathsToStoreToAKeycard: seq[string]
|
||||
for acc in accountsForLoggedInUser:
|
||||
activeValidPathsToStoreToAKeycard.add(acc.path)
|
||||
kpDto.accountsAddresses.add(acc.address)
|
||||
self.keycardService.startStoreMetadataFlow(displayName, self.startupModule.getPin(), activeValidPathsToStoreToAKeycard)
|
||||
## sleep for 3 seconds, since that is more than enough to store metadata to a keycard, if the reader is still plugged in
|
||||
## and the card is still inserted, otherwise we just skip that.
|
||||
## At the moment we're not able to sync later keycard without metadata, cause such card doesn't return instance uid for
|
||||
## loaded seed phrase, that's in the notes I am taking for discussion with keycard team. If they are able to provide
|
||||
## instance uid for GetMetadata flow we will be able to use SIGNAL_SHARED_KEYCARD_MODULE_TRY_KEYCARD_SYNC signal for syncing
|
||||
## otherwise we need to handle that way separatelly in `handleKeycardSyncing` of shared module
|
||||
sleep(3000)
|
||||
let (_, kcEvent) = self.keycardService.getLastReceivedKeycardData()
|
||||
if kcEvent.instanceUID.len > 0:
|
||||
kpDto.keycardUid = kcEvent.instanceUID
|
||||
let keystoreDir = self.accountsService.getKeyStoreDir()
|
||||
discard self.walletAccountService.addMigratedKeyPair(kpDto, keystoreDir)
|
||||
|
||||
proc storeKeyPairForNewKeycardUser*(self: AppController) =
|
||||
self.storeKeyPair = true
|
||||
self.storeKeyPair = true
|
||||
|
||||
proc syncWalletAccountsOnLoginForReplacedKeycard*(self: AppController) =
|
||||
self.syncWalletForReplacedKeycard = true
|
|
@ -1,2 +1,5 @@
|
|||
## All app's labels/terms/warnings which need to be used/created on the backed side and displayed on the UI later
|
||||
## should be stated here and translated via translations map in `Constants.qml` to be displayed well in user's language
|
||||
const LOGIN_ACCOUNTS_LIST_ADD_NEW_USER* = "LOGIN-ACCOUNTS-LIST-ADD-NEW-USER"
|
||||
const LOGIN_ACCOUNTS_LIST_ADD_EXISTING_USER* = "LOGIN-ACCOUNTS-LIST-ADD-EXISTING-USER"
|
||||
const LOGIN_ACCOUNTS_LIST_ADD_EXISTING_USER* = "LOGIN-ACCOUNTS-LIST-ADD-EXISTING-USER"
|
||||
const LOGIN_ACCOUNTS_LIST_LOST_KEYCARD* = "LOGIN-ACCOUNTS-LIST-LOST-KEYCARD"
|
|
@ -22,7 +22,8 @@ method executePrePrimaryStateCommand*(self: FactoryResetSuccessState, controller
|
|||
controller.runLoadAccountFlow(seedPhraseLength = 0, seedPhrase = "", pin = controller.getPinForKeycardCopy())
|
||||
|
||||
method executeCancelCommand*(self: FactoryResetSuccessState, controller: Controller) =
|
||||
if self.flowType == FlowType.SetupNewKeycard or
|
||||
if self.flowType == FlowType.FactoryReset or
|
||||
self.flowType == FlowType.SetupNewKeycard or
|
||||
self.flowType == FlowType.SetupNewKeycardNewSeedPhrase or
|
||||
self.flowType == FlowType.SetupNewKeycardOldSeedPhrase or
|
||||
self.flowType == FlowType.CreateCopyOfAKeycard:
|
||||
|
|
|
@ -379,7 +379,7 @@ proc getSelectedLoginAccount*(self: Controller): AccountDto =
|
|||
if(acc.keyUid == self.tmpSelectedLoginAccountKeyUid):
|
||||
return acc
|
||||
|
||||
proc keyUidMatch*(self: Controller, keyUid: string): bool =
|
||||
proc keyUidMatchSelectedLoginAccount*(self: Controller, keyUid: string): bool =
|
||||
return self.tmpSelectedLoginAccountKeyUid == keyUid
|
||||
|
||||
proc isSelectedLoginAccountKeycardAccount*(self: Controller): bool =
|
||||
|
@ -391,7 +391,7 @@ proc setSelectedLoginAccount*(self: Controller, keyUid: string, isKeycardAccount
|
|||
let selectedAccount = self.getSelectedLoginAccount()
|
||||
singletonInstance.localAccountSettings.setFileName(selectedAccount.name)
|
||||
|
||||
proc isKeycardCreatedAccountSelectedOne*(self: Controller): bool =
|
||||
proc isSelectedAccountAKeycardAccount*(self: Controller): bool =
|
||||
let selectedAccount = self.getSelectedLoginAccount()
|
||||
return selectedAccount.keycardPairing.len > 0
|
||||
|
||||
|
@ -413,7 +413,14 @@ proc login*(self: Controller) =
|
|||
if(error.len > 0):
|
||||
self.delegate.emitAccountLoginError(error)
|
||||
|
||||
proc loginAccountKeycard*(self: Controller) =
|
||||
proc loginAccountKeycard*(self: Controller, storeToKeychain = false, syncWalletAfterLogin = false) =
|
||||
if syncWalletAfterLogin:
|
||||
self.delegate.syncWalletAccountsOnLoginForReplacedKeycard()
|
||||
if storeToKeychain:
|
||||
## storing not now, user will be asked to store the pin once he is logged in
|
||||
singletonInstance.localAccountSettings.setStoreToKeychainValue(LS_VALUE_NOT_NOW)
|
||||
else:
|
||||
singletonInstance.localAccountSettings.setStoreToKeychainValue(LS_VALUE_NEVER)
|
||||
self.delegate.moveToLoadingAppState()
|
||||
let error = self.accountsService.loginAccountKeycard(self.tmpKeycardEvent)
|
||||
if(error.len > 0):
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
type
|
||||
BiometricsState* = ref object of State
|
||||
storeToKeychain: bool
|
||||
|
||||
proc newBiometricsState*(flowType: FlowType, backState: State): BiometricsState =
|
||||
result = BiometricsState()
|
||||
result.setup(flowType, StateType.Biometrics, backState)
|
||||
result.storeToKeychain = false
|
||||
|
||||
proc delete*(self: BiometricsState) =
|
||||
self.State.delete
|
||||
|
@ -28,6 +30,9 @@ method executePrimaryCommand*(self: BiometricsState, controller: Controller) =
|
|||
controller.storeKeycardAccountAndLogin(storeToKeychain)
|
||||
elif self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
controller.setupKeycardAccount(storeToKeychain)
|
||||
elif self.flowType == FlowType.LostKeycardReplacement:
|
||||
self.storeToKeychain = storeToKeychain
|
||||
controller.startLoginFlowAutomatically(controller.getPin())
|
||||
|
||||
method executeSecondaryCommand*(self: BiometricsState, controller: Controller) =
|
||||
let storeToKeychain = false # false, cause we don't have keychain support for other than mac os
|
||||
|
@ -44,4 +49,15 @@ method executeSecondaryCommand*(self: BiometricsState, controller: Controller) =
|
|||
elif self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
|
||||
controller.storeKeycardAccountAndLogin(storeToKeychain)
|
||||
elif self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
controller.setupKeycardAccount(storeToKeychain)
|
||||
controller.setupKeycardAccount(storeToKeychain)
|
||||
elif self.flowType == FlowType.LostKeycardReplacement:
|
||||
self.storeToKeychain = storeToKeychain
|
||||
controller.startLoginFlowAutomatically(controller.getPin())
|
||||
|
||||
method resolveKeycardNextState*(self: BiometricsState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
if self.flowType == FlowType.LostKeycardReplacement:
|
||||
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
|
||||
keycardEvent.error.len == 0:
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
controller.loginAccountKeycard(self.storeToKeychain, syncWalletAfterLogin = true)
|
|
@ -11,7 +11,8 @@ proc delete*(self: KeycardInsertKeycardState) =
|
|||
method executeBackCommand*(self: KeycardInsertKeycardState, controller: Controller) =
|
||||
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys or
|
||||
self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard or
|
||||
self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
self.flowType == FlowType.FirstRunOldUserKeycardImport or
|
||||
self.flowType == FlowType.LostKeycardReplacement:
|
||||
controller.cancelCurrentFlow()
|
||||
|
||||
method resolveKeycardNextState*(self: KeycardInsertKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
|
|
|
@ -11,7 +11,8 @@ proc delete*(self: KeycardInsertedKeycardState) =
|
|||
method executeBackCommand*(self: KeycardInsertedKeycardState, controller: Controller) =
|
||||
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys or
|
||||
self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard or
|
||||
self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
self.flowType == FlowType.FirstRunOldUserKeycardImport or
|
||||
self.flowType == FlowType.LostKeycardReplacement:
|
||||
controller.cancelCurrentFlow()
|
||||
|
||||
method getNextPrimaryState*(self: KeycardInsertedKeycardState, controller: Controller): State =
|
||||
|
|
|
@ -8,6 +8,10 @@ proc newKeycardLockedState*(flowType: FlowType, backState: State): KeycardLocked
|
|||
proc delete*(self: KeycardLockedState) =
|
||||
self.State.delete
|
||||
|
||||
method executeBackCommand*(self: KeycardLockedState, controller: Controller) =
|
||||
if self.flowType == FlowType.LostKeycardReplacement:
|
||||
controller.cancelCurrentFlow()
|
||||
|
||||
method executePrimaryCommand*(self: KeycardLockedState, controller: Controller) =
|
||||
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys:
|
||||
controller.runFactoryResetPopup()
|
|
@ -8,9 +8,14 @@ proc newKeycardNotEmptyState*(flowType: FlowType, backState: State): KeycardNotE
|
|||
proc delete*(self: KeycardNotEmptyState) =
|
||||
self.State.delete
|
||||
|
||||
method executeBackCommand*(self: KeycardNotEmptyState, controller: Controller) =
|
||||
if self.flowType == FlowType.LostKeycardReplacement:
|
||||
controller.cancelCurrentFlow()
|
||||
|
||||
method executePrimaryCommand*(self: KeycardNotEmptyState, controller: Controller) =
|
||||
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys or
|
||||
self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
|
||||
self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard or
|
||||
self.flowType == FlowType.LostKeycardReplacement:
|
||||
controller.runFactoryResetPopup()
|
||||
|
||||
method executeSecondaryCommand*(self: KeycardNotEmptyState, controller: Controller) =
|
||||
|
@ -32,4 +37,4 @@ method resolveKeycardNextState*(self: KeycardNotEmptyState, keycardFlowType: str
|
|||
if keycardFlowType == ResponseTypeValueEnterNewPIN and
|
||||
keycardEvent.error.len > 0 and
|
||||
keycardEvent.error == ErrorRequireInit:
|
||||
return createState(StateType.UserProfileEnterSeedPhrase, self.flowType, self.getBackState)
|
||||
return createState(StateType.UserProfileEnterSeedPhrase, self.flowType, self.getBackState)
|
||||
|
|
|
@ -6,4 +6,8 @@ proc newKeycardNotKeycardState*(flowType: FlowType, backState: State): KeycardNo
|
|||
result.setup(flowType, StateType.KeycardNotKeycard, backState)
|
||||
|
||||
proc delete*(self: KeycardNotKeycardState) =
|
||||
self.State.delete
|
||||
self.State.delete
|
||||
|
||||
method executeBackCommand*(self: KeycardNotKeycardState, controller: Controller) =
|
||||
if self.flowType == FlowType.LostKeycardReplacement:
|
||||
controller.cancelCurrentFlow()
|
|
@ -30,11 +30,27 @@ method getNextPrimaryState*(self: KeycardPinSetState, controller: Controller): S
|
|||
controller.loginAccountKeycard()
|
||||
return nil
|
||||
return createState(StateType.KeycardWrongPuk, self.flowType, self.getBackState)
|
||||
if self.flowType == FlowType.LostKeycardReplacement:
|
||||
if not defined(macosx):
|
||||
return nil
|
||||
return createState(StateType.Biometrics, self.flowType, self.getBackState)
|
||||
|
||||
method executePrimaryCommand*(self: KeycardPinSetState, controller: Controller) =
|
||||
if controller.getValidPuk() and not defined(macosx):
|
||||
controller.setupKeycardAccount(false)
|
||||
if defined(macosx):
|
||||
return
|
||||
# if controller.getValidPuk():
|
||||
# controller.setupKeycardAccount(false)
|
||||
# return
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
if controller.getRecoverUsingSeedPhraseWhileLogin():
|
||||
controller.startLoginFlowAutomatically(controller.getPin())
|
||||
controller.startLoginFlowAutomatically(controller.getPin())
|
||||
if self.flowType == FlowType.LostKeycardReplacement:
|
||||
controller.startLoginFlowAutomatically(controller.getPin())
|
||||
|
||||
method resolveKeycardNextState*(self: KeycardPinSetState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
if self.flowType == FlowType.LostKeycardReplacement:
|
||||
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
|
||||
keycardEvent.error.len == 0:
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
controller.loginAccountKeycard()
|
|
@ -11,7 +11,8 @@ proc delete*(self: KeycardPluginReaderState) =
|
|||
method executeBackCommand*(self: KeycardPluginReaderState, controller: Controller) =
|
||||
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys or
|
||||
self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard or
|
||||
self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
self.flowType == FlowType.FirstRunOldUserKeycardImport or
|
||||
self.flowType == FlowType.LostKeycardReplacement:
|
||||
controller.cancelCurrentFlow()
|
||||
|
||||
method resolveKeycardNextState*(self: KeycardPluginReaderState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
|
|
|
@ -11,7 +11,8 @@ proc delete*(self: KeycardReadingKeycardState) =
|
|||
method executeBackCommand*(self: KeycardReadingKeycardState, controller: Controller) =
|
||||
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys or
|
||||
self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard or
|
||||
self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
self.flowType == FlowType.FirstRunOldUserKeycardImport or
|
||||
self.flowType == FlowType.LostKeycardReplacement:
|
||||
controller.cancelCurrentFlow()
|
||||
|
||||
method getNextPrimaryState*(self: KeycardReadingKeycardState, controller: Controller): State =
|
||||
|
|
|
@ -11,7 +11,8 @@ proc delete*(self: KeycardRecognizedKeycardState) =
|
|||
method executeBackCommand*(self: KeycardRecognizedKeycardState, controller: Controller) =
|
||||
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys or
|
||||
self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard or
|
||||
self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
self.flowType == FlowType.FirstRunOldUserKeycardImport or
|
||||
self.flowType == FlowType.LostKeycardReplacement:
|
||||
controller.cancelCurrentFlow()
|
||||
|
||||
method getNextPrimaryState*(self: KeycardRecognizedKeycardState, controller: Controller): State =
|
||||
|
@ -21,3 +22,5 @@ method getNextPrimaryState*(self: KeycardRecognizedKeycardState, controller: Con
|
|||
return createState(StateType.UserProfileEnterSeedPhrase, self.flowType, self.getBackState)
|
||||
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
return createState(StateType.KeycardEnterPin, self.flowType, self.getBackState)
|
||||
if self.flowType == FlowType.LostKeycardReplacement:
|
||||
return createState(StateType.UserProfileEnterSeedPhrase, self.flowType, self.getBackState)
|
||||
|
|
|
@ -15,14 +15,15 @@ method executeBackCommand*(self: KeycardRepeatPinState, controller: Controller)
|
|||
method executePrimaryCommand*(self: KeycardRepeatPinState, controller: Controller) =
|
||||
if not controller.getPinMatch():
|
||||
return
|
||||
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys:
|
||||
controller.storePinToKeycard(controller.getPin(), controller.generateRandomPUK())
|
||||
elif self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
|
||||
controller.storePinToKeycard(controller.getPin(), controller.generateRandomPUK())
|
||||
elif self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
controller.storePinToKeycard(controller.getPin(), puk = "")
|
||||
elif self.flowType == FlowType.AppLogin:
|
||||
controller.storePinToKeycard(controller.getPin(), puk = "")
|
||||
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys or
|
||||
self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
|
||||
controller.storePinToKeycard(controller.getPin(), controller.generateRandomPUK())
|
||||
return
|
||||
if self.flowType == FlowType.FirstRunOldUserKeycardImport or
|
||||
self.flowType == FlowType.AppLogin or
|
||||
self.flowType == FlowType.LostKeycardReplacement:
|
||||
controller.storePinToKeycard(controller.getPin(), puk = "")
|
||||
return
|
||||
|
||||
method resolveKeycardNextState*(self: KeycardRepeatPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
|
@ -65,4 +66,10 @@ method resolveKeycardNextState*(self: KeycardRepeatPinState, keycardFlowType: st
|
|||
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
controller.setPukValid(true)
|
||||
return createState(StateType.KeycardPinSet, self.flowType, self.getBackState)
|
||||
return createState(StateType.KeycardPinSet, self.flowType, self.getBackState)
|
||||
if self.flowType == FlowType.LostKeycardReplacement:
|
||||
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
controller.setPukValid(true)
|
||||
let backState = findBackStateWithTargetedStateType(self, StateType.LostKeycardOptions)
|
||||
return createState(StateType.KeycardPinSet, self.flowType, backState)
|
|
@ -25,6 +25,11 @@ method getNextQuaternaryState*(self: LoginKeycardEmptyState, controller: Control
|
|||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
|
||||
|
||||
method getNextQuinaryState*(self: LoginKeycardEmptyState, controller: Controller): State =
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.LostKeycardOptions, self.flowType, self)
|
||||
|
||||
method resolveKeycardNextState*(self: LoginKeycardEmptyState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)
|
|
@ -21,4 +21,9 @@ method getNextTertiaryState*(self: LoginKeycardEnterPasswordState, controller: C
|
|||
method getNextQuaternaryState*(self: LoginKeycardEnterPasswordState, controller: Controller): State =
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
|
||||
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
|
||||
|
||||
method getNextQuinaryState*(self: LoginKeycardEnterPasswordState, controller: Controller): State =
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.LostKeycardOptions, self.flowType, self)
|
|
@ -24,6 +24,11 @@ method getNextQuaternaryState*(self: LoginKeycardEnterPinState, controller: Cont
|
|||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
|
||||
|
||||
method getNextQuinaryState*(self: LoginKeycardEnterPinState, controller: Controller): State =
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.LostKeycardOptions, self.flowType, self)
|
||||
|
||||
method resolveKeycardNextState*(self: LoginKeycardEnterPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
let state = ensureReaderAndCardPresenceLogin(self, keycardFlowType, keycardEvent, controller)
|
||||
|
|
|
@ -18,6 +18,11 @@ method getNextQuaternaryState*(self: LoginKeycardInsertKeycardState, controller:
|
|||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
|
||||
|
||||
method getNextQuinaryState*(self: LoginKeycardInsertKeycardState, controller: Controller): State =
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.LostKeycardOptions, self.flowType, self)
|
||||
|
||||
method resolveKeycardNextState*(self: LoginKeycardInsertKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
let state = ensureReaderAndCardPresenceLogin(self, keycardFlowType, keycardEvent, controller)
|
||||
|
|
|
@ -9,7 +9,7 @@ proc delete*(self: LoginKeycardMaxPairingSlotsReachedState) =
|
|||
self.State.delete
|
||||
|
||||
method executeBackCommand*(self: LoginKeycardMaxPairingSlotsReachedState, controller: Controller) =
|
||||
if self.flowType == FlowType.AppLogin and controller.isKeycardCreatedAccountSelectedOne():
|
||||
if self.flowType == FlowType.AppLogin and controller.isSelectedAccountAKeycardAccount():
|
||||
controller.runLoginFlow()
|
||||
|
||||
method getNextPrimaryState*(self: LoginKeycardMaxPairingSlotsReachedState, controller: Controller): State =
|
||||
|
@ -27,6 +27,11 @@ method getNextQuaternaryState*(self: LoginKeycardMaxPairingSlotsReachedState, co
|
|||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
|
||||
|
||||
method getNextQuinaryState*(self: LoginKeycardMaxPairingSlotsReachedState, controller: Controller): State =
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.LostKeycardOptions, self.flowType, self)
|
||||
|
||||
method resolveKeycardNextState*(self: LoginKeycardMaxPairingSlotsReachedState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)
|
|
@ -9,7 +9,7 @@ proc delete*(self: LoginKeycardMaxPinRetriesReachedState) =
|
|||
self.State.delete
|
||||
|
||||
method executeBackCommand*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller) =
|
||||
if self.flowType == FlowType.AppLogin and controller.isKeycardCreatedAccountSelectedOne():
|
||||
if self.flowType == FlowType.AppLogin and controller.isSelectedAccountAKeycardAccount():
|
||||
controller.runLoginFlow()
|
||||
|
||||
method getNextPrimaryState*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller): State =
|
||||
|
@ -26,6 +26,11 @@ method getNextQuaternaryState*(self: LoginKeycardMaxPinRetriesReachedState, cont
|
|||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
|
||||
|
||||
method getNextQuinaryState*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller): State =
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.LostKeycardOptions, self.flowType, self)
|
||||
|
||||
method resolveKeycardNextState*(self: LoginKeycardMaxPinRetriesReachedState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)
|
|
@ -9,7 +9,7 @@ proc delete*(self: LoginKeycardMaxPukRetriesReachedState) =
|
|||
self.State.delete
|
||||
|
||||
method executeBackCommand*(self: LoginKeycardMaxPukRetriesReachedState, controller: Controller) =
|
||||
if self.flowType == FlowType.AppLogin and controller.isKeycardCreatedAccountSelectedOne():
|
||||
if self.flowType == FlowType.AppLogin and controller.isSelectedAccountAKeycardAccount():
|
||||
controller.runLoginFlow()
|
||||
|
||||
method getNextPrimaryState*(self: LoginKeycardMaxPukRetriesReachedState, controller: Controller): State =
|
||||
|
@ -27,6 +27,11 @@ method getNextQuaternaryState*(self: LoginKeycardMaxPukRetriesReachedState, cont
|
|||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
|
||||
|
||||
method getNextQuinaryState*(self: LoginKeycardMaxPukRetriesReachedState, controller: Controller): State =
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.LostKeycardOptions, self.flowType, self)
|
||||
|
||||
method resolveKeycardNextState*(self: LoginKeycardMaxPukRetriesReachedState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)
|
|
@ -24,6 +24,11 @@ method getNextQuaternaryState*(self: LoginKeycardWrongKeycardState, controller:
|
|||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
|
||||
|
||||
method getNextQuinaryState*(self: LoginKeycardWrongKeycardState, controller: Controller): State =
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.LostKeycardOptions, self.flowType, self)
|
||||
|
||||
method resolveKeycardNextState*(self: LoginKeycardWrongKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)
|
|
@ -26,6 +26,11 @@ method getNextQuaternaryState*(self: LoginKeycardWrongPinState, controller: Cont
|
|||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
|
||||
|
||||
method getNextQuinaryState*(self: LoginKeycardWrongPinState, controller: Controller): State =
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.LostKeycardOptions, self.flowType, self)
|
||||
|
||||
method resolveKeycardNextState*(self: LoginKeycardWrongPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
let state = ensureReaderAndCardPresenceLogin(self, keycardFlowType, keycardEvent, controller)
|
||||
|
|
|
@ -22,6 +22,11 @@ method getNextQuaternaryState*(self: LoginNotKeycardState, controller: Controlle
|
|||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
|
||||
|
||||
method getNextQuinaryState*(self: LoginNotKeycardState, controller: Controller): State =
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.LostKeycardOptions, self.flowType, self)
|
||||
|
||||
method resolveKeycardNextState*(self: LoginNotKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)
|
|
@ -18,6 +18,11 @@ method getNextQuaternaryState*(self: LoginPluginState, controller: Controller):
|
|||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
|
||||
|
||||
method getNextQuinaryState*(self: LoginPluginState, controller: Controller): State =
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.LostKeycardOptions, self.flowType, self)
|
||||
|
||||
method resolveKeycardNextState*(self: LoginPluginState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)
|
|
@ -34,6 +34,11 @@ method getNextQuaternaryState*(self: LoginState, controller: Controller): State
|
|||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
|
||||
|
||||
method getNextQuinaryState*(self: LoginState, controller: Controller): State =
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
controller.cancelCurrentFlow()
|
||||
return createState(StateType.LostKeycardOptions, self.flowType, self)
|
||||
|
||||
method resolveKeycardNextState*(self: LoginState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)
|
|
@ -0,0 +1,27 @@
|
|||
type
|
||||
LostKeycardOptionsState* = ref object of State
|
||||
|
||||
proc newLostKeycardOptionsState*(flowType: FlowType, backState: State): LostKeycardOptionsState =
|
||||
result = LostKeycardOptionsState()
|
||||
result.setup(flowType, StateType.LostKeycardOptions, backState)
|
||||
|
||||
proc delete*(self: LostKeycardOptionsState) =
|
||||
self.State.delete
|
||||
|
||||
method executeBackCommand*(self: LostKeycardOptionsState, controller: Controller) =
|
||||
if controller.isSelectedAccountAKeycardAccount() and
|
||||
(self.flowType == FlowType.LostKeycardReplacement or self.flowType == FlowType.AppLogin):
|
||||
controller.cancelCurrentFlow()
|
||||
controller.runLoginFlow()
|
||||
|
||||
method executePrimaryCommand*(self: LostKeycardOptionsState, controller: Controller) =
|
||||
if controller.isSelectedAccountAKeycardAccount():
|
||||
self.setFlowType(FlowType.LostKeycardReplacement)
|
||||
controller.runLoadAccountFlow()
|
||||
|
||||
method executeSecondaryCommand*(self: LostKeycardOptionsState, controller: Controller) =
|
||||
echo "TODO: start using account without keycard..."
|
||||
|
||||
method resolveKeycardNextState*(self: LostKeycardOptionsState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
return ensureReaderAndCardPresenceAndResolveNextOnboardingState(self, keycardFlowType, keycardEvent, controller)
|
|
@ -13,6 +13,7 @@ type FlowType* {.pure.} = enum
|
|||
FirstRunOldUserKeycardImport = "FirstRunOldUserKeycardImport"
|
||||
FirstRunOldUserImportSeedPhrase = "FirstRunOldUserImportSeedPhrase"
|
||||
AppLogin = "AppLogin"
|
||||
LostKeycardReplacement = "LostKeycardReplacement"
|
||||
|
||||
type StateType* {.pure.} = enum
|
||||
NoState = "NoState"
|
||||
|
@ -72,6 +73,7 @@ type StateType* {.pure.} = enum
|
|||
ProfileFetchingSuccess = "ProfileFetchingSuccess"
|
||||
ProfileFetchingTimeout = "ProfileFetchingTimeout"
|
||||
ProfileFetchingAnnouncement = "ProfileFetchingAnnouncement"
|
||||
LostKeycardOptions = "LostKeycardOptions"
|
||||
|
||||
|
||||
## This is the base class for all state we may have in onboarding/login flow.
|
||||
|
|
|
@ -15,6 +15,7 @@ logScope:
|
|||
# Forward declaration
|
||||
# General section
|
||||
proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: State): State
|
||||
proc findBackStateWithTargetedStateType*(currentState: State, targetedStateType: StateType): 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
|
||||
|
@ -77,6 +78,7 @@ include profile_fetching_success_state
|
|||
include profile_fetching_timeout_state
|
||||
include profile_fetching_announcement_state
|
||||
include recover_old_user_state
|
||||
include lost_keycard_options_state
|
||||
|
||||
include state_factory_general_implementation
|
||||
include state_factory_state_onboarding_implementation
|
||||
|
|
|
@ -111,5 +111,17 @@ proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: St
|
|||
return newProfileFetchingAnnouncementState(flowType, backState)
|
||||
if stateToBeCreated == StateType.RecoverOldUser:
|
||||
return newRecoverOldUserState(flowType, backState)
|
||||
if stateToBeCreated == StateType.LostKeycardOptions:
|
||||
return newLostKeycardOptionsState(flowType, backState)
|
||||
|
||||
error "No implementation available for state ", state=stateToBeCreated
|
||||
error "No implementation available for state ", state=stateToBeCreated
|
||||
|
||||
proc findBackStateWithTargetedStateType*(currentState: State, targetedStateType: StateType): State =
|
||||
if currentState.isNil:
|
||||
return nil
|
||||
var state = currentState
|
||||
while not state.isNil:
|
||||
if state.stateType == targetedStateType:
|
||||
return state
|
||||
state = state.getBackState
|
||||
return nil
|
|
@ -27,7 +27,7 @@ proc ensureReaderAndCardPresenceAndResolveNextLoginState*(state: State, keycardF
|
|||
return createState(StateType.LoginKeycardPinVerified, state.flowType, nil)
|
||||
if keycardFlowType == ResponseTypeValueEnterPIN:
|
||||
if keycardEvent.error.len == 0:
|
||||
if not controller.keyUidMatch(keycardEvent.keyUid):
|
||||
if not controller.keyUidMatchSelectedLoginAccount(keycardEvent.keyUid):
|
||||
return createState(StateType.LoginKeycardWrongKeycard, state.flowType, nil)
|
||||
return createState(StateType.LoginKeycardRecognizedKeycard, state.flowType, nil)
|
||||
if keycardEvent.error.len > 0:
|
||||
|
|
|
@ -11,10 +11,14 @@ proc ensureReaderAndCardPresenceOnboarding*(state: State, keycardFlowType: strin
|
|||
keycardEvent.error == ErrorConnection:
|
||||
if state.stateType == StateType.KeycardInsertKeycard:
|
||||
return nil
|
||||
return createState(StateType.KeycardInsertKeycard, state.flowType, state.getBackState)
|
||||
if state.stateType == StateType.KeycardPluginReader:
|
||||
return createState(StateType.KeycardInsertKeycard, state.flowType, state.getBackState)
|
||||
return createState(StateType.KeycardInsertKeycard, state.flowType, state)
|
||||
if keycardFlowType == ResponseTypeValueCardInserted:
|
||||
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WronglyInsertedCard, add = false))
|
||||
return createState(StateType.KeycardInsertedKeycard, state.flowType, state.getBackState)
|
||||
if state.stateType == StateType.KeycardInsertKeycard:
|
||||
return createState(StateType.KeycardInsertedKeycard, state.flowType, state.getBackState)
|
||||
return createState(StateType.KeycardInsertedKeycard, state.flowType, state)
|
||||
|
||||
proc ensureReaderAndCardPresenceAndResolveNextOnboardingState*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State =
|
||||
let ensureState = ensureReaderAndCardPresenceOnboarding(state, keycardFlowType, keycardEvent, controller)
|
||||
|
@ -114,4 +118,29 @@ proc ensureReaderAndCardPresenceAndResolveNextOnboardingState*(state: State, key
|
|||
if keycardFlowType == ResponseTypeValueEnterNewPIN and
|
||||
keycardEvent.error.len > 0 and
|
||||
keycardEvent.error == ErrorRequireInit:
|
||||
return createState(StateType.KeycardCreatePin, state.flowType, state.getBackState)
|
||||
return createState(StateType.KeycardCreatePin, state.flowType, state.getBackState)
|
||||
|
||||
if state.flowType == FlowType.LostKeycardReplacement:
|
||||
var backState = state.getBackState
|
||||
if state.stateType == StateType.LostKeycardOptions:
|
||||
backState = state
|
||||
|
||||
if keycardFlowType == ResponseTypeValueEnterNewPIN and
|
||||
keycardEvent.error.len > 0 and
|
||||
keycardEvent.error == ErrorRequireInit:
|
||||
if state.stateType == StateType.UserProfileEnterSeedPhrase:
|
||||
return createState(StateType.KeycardCreatePin, state.flowType, state)
|
||||
return createState(StateType.KeycardRecognizedKeycard, state.flowType, backState)
|
||||
if keycardFlowType == ResponseTypeValueEnterPIN and
|
||||
keycardEvent.error.len == 0:
|
||||
return createState(StateType.KeycardNotEmpty, state.flowType, backState)
|
||||
if keycardFlowType == ResponseTypeValueSwapCard and
|
||||
keycardEvent.error.len > 0:
|
||||
if keycardEvent.error == ErrorNotAKeycard:
|
||||
return createState(StateType.KeycardNotKeycard, state.flowType, backState)
|
||||
if keycardEvent.error == RequestParamFreeSlots:
|
||||
return createState(StateType.KeycardLocked, state.flowType, backState)
|
||||
if keycardEvent.error == RequestParamPUKRetries:
|
||||
return createState(StateType.KeycardLocked, state.flowType, backState)
|
||||
if keycardEvent.error == ErrorHasKeys:
|
||||
return createState(StateType.KeycardNotEmpty, state.flowType, backState)
|
|
@ -1,13 +1,13 @@
|
|||
type
|
||||
UserProfileEnterSeedPhraseState* = ref object of State
|
||||
successfulImport: bool
|
||||
correctKeycard: bool
|
||||
enteredMnemonicMatchTargetedKeyUid: bool
|
||||
|
||||
proc newUserProfileEnterSeedPhraseState*(flowType: FlowType, backState: State): UserProfileEnterSeedPhraseState =
|
||||
result = UserProfileEnterSeedPhraseState()
|
||||
result.setup(flowType, StateType.UserProfileEnterSeedPhrase, backState)
|
||||
result.successfulImport = false
|
||||
result.correctKeycard = false
|
||||
result.enteredMnemonicMatchTargetedKeyUid = false
|
||||
|
||||
proc delete*(self: UserProfileEnterSeedPhraseState) =
|
||||
self.State.delete
|
||||
|
@ -22,7 +22,7 @@ method getNextPrimaryState*(self: UserProfileEnterSeedPhraseState, controller: C
|
|||
if self.flowType == FlowType.FirstRunNewUserImportSeedPhrase:
|
||||
return createState(StateType.UserProfileCreate, self.flowType, self)
|
||||
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
if not self.correctKeycard:
|
||||
if not self.enteredMnemonicMatchTargetedKeyUid:
|
||||
return createState(StateType.KeycardWrongKeycard, self.flowType, nil)
|
||||
if self.flowType == FlowType.FirstRunOldUserImportSeedPhrase:
|
||||
return createState(StateType.UserProfileCreatePassword, self.flowType, self)
|
||||
|
@ -44,10 +44,18 @@ method executePrimaryCommand*(self: UserProfileEnterSeedPhraseState, controller:
|
|||
if self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
|
||||
controller.storeSeedPhraseToKeycard(controller.getSeedPhraseLength(), controller.getSeedPhrase())
|
||||
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
self.correctKeycard = controller.getKeyUidForSeedPhrase(controller.getSeedPhrase()) == controller.getKeyUid()
|
||||
if self.correctKeycard:
|
||||
self.enteredMnemonicMatchTargetedKeyUid = controller.getKeyUidForSeedPhrase(controller.getSeedPhrase()) == controller.getKeyUid()
|
||||
if self.enteredMnemonicMatchTargetedKeyUid:
|
||||
controller.runLoadAccountFlow(controller.getSeedPhraseLength(), controller.getSeedPhrase(), pin = "", puk = "",
|
||||
factoryReset = true)
|
||||
if self.flowType == FlowType.LostKeycardReplacement:
|
||||
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WrongSeedPhrase, add = false))
|
||||
let keyUid = controller.getKeyUidForSeedPhrase(controller.getSeedPhrase())
|
||||
self.enteredMnemonicMatchTargetedKeyUid = controller.keyUidMatchSelectedLoginAccount(keyUid)
|
||||
if self.enteredMnemonicMatchTargetedKeyUid:
|
||||
controller.storeSeedPhraseToKeycard(controller.getSeedPhraseLength(), controller.getSeedPhrase())
|
||||
else:
|
||||
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WrongSeedPhrase, add = true))
|
||||
|
||||
method resolveKeycardNextState*(self: UserProfileEnterSeedPhraseState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
|
|
|
@ -11,7 +11,7 @@ proc delete*(self: WelcomeStateNewUser) =
|
|||
method executeBackCommand*(self: WelcomeStateNewUser, controller: Controller) =
|
||||
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys:
|
||||
controller.cancelCurrentFlow()
|
||||
elif self.flowType == FlowType.AppLogin and controller.isKeycardCreatedAccountSelectedOne():
|
||||
elif self.flowType == FlowType.AppLogin and controller.isSelectedAccountAKeycardAccount():
|
||||
controller.runLoginFlow()
|
||||
|
||||
method executeSecondaryCommand*(self: WelcomeStateNewUser, controller: Controller) =
|
||||
|
|
|
@ -9,7 +9,7 @@ proc delete*(self: WelcomeStateOldUser) =
|
|||
self.State.delete
|
||||
|
||||
method executeBackCommand*(self: WelcomeStateOldUser, controller: Controller) =
|
||||
if self.flowType == FlowType.AppLogin and controller.isKeycardCreatedAccountSelectedOne():
|
||||
if self.flowType == FlowType.AppLogin and controller.isSelectedAccountAKeycardAccount():
|
||||
controller.runLoginFlow()
|
||||
|
||||
method getNextPrimaryState*(self: WelcomeStateOldUser, controller: Controller): State =
|
||||
|
|
|
@ -143,6 +143,9 @@ method runFactoryResetPopup*(self: AccessInterface) {.base.} =
|
|||
method storeKeyPairForNewKeycardUser*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method syncWalletAccountsOnLoginForReplacedKeycard*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method checkForStoringPasswordToKeychain*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
@ -165,3 +168,4 @@ type
|
|||
c.userLoggedIn()
|
||||
c.finishAppLoading()
|
||||
c.storeKeyPairForNewKeycardUser()
|
||||
c.syncWalletAccountsOnLoginForReplacedKeycard()
|
||||
|
|
|
@ -113,6 +113,8 @@ method load*[T](self: Module[T]) =
|
|||
thumbnailImage = "", largeImage = "", keyUid = ""))
|
||||
items.add(login_acc_item.initItem(order = items.len, name = atc.LOGIN_ACCOUNTS_LIST_ADD_EXISTING_USER, icon = "wallet",
|
||||
thumbnailImage = "", largeImage = "", keyUid = ""))
|
||||
items.add(login_acc_item.initItem(order = items.len, name = atc.LOGIN_ACCOUNTS_LIST_LOST_KEYCARD, icon = "keycard",
|
||||
thumbnailImage = "", largeImage = "", keyUid = ""))
|
||||
self.view.setLoginAccountsModelItems(items)
|
||||
self.setSelectedLoginAccount(items[0])
|
||||
self.delegate.startupDidLoad()
|
||||
|
@ -451,11 +453,24 @@ method onSharedKeycarModuleFlowTerminated*[T](self: Module[T], lastStepInTheCurr
|
|||
self.keycardSharedModule.delete
|
||||
self.keycardSharedModule = nil
|
||||
if lastStepInTheCurrentFlow:
|
||||
self.controller.cleanTmpData()
|
||||
self.view.setCurrentStartupState(newWelcomeState(FlowType.General, nil))
|
||||
# self.controller.cleanTmpData()
|
||||
let currStateObj = self.view.currentStartupStateObj()
|
||||
if currStateObj.isNil:
|
||||
error "cannot resolve current state for onboarding/login flow continuation"
|
||||
return
|
||||
if currStateObj.flowType() == FlowType.LostKeycardReplacement:
|
||||
let newState = currStateObj.getBackState()
|
||||
if newState.isNil:
|
||||
error "cannot resolve new state for onboarding/login flow continuation after shared flow is terminated"
|
||||
return
|
||||
self.view.setCurrentStartupState(newState)
|
||||
debug "new state for onboarding/login flow continuation after shared flow is terminated", setCurrFlow=newState.flowType(), newCurrState=newState.stateType()
|
||||
|
||||
method storeKeyPairForNewKeycardUser*[T](self: Module[T]) =
|
||||
self.delegate.storeKeyPairForNewKeycardUser()
|
||||
|
||||
method syncWalletAccountsOnLoginForReplacedKeycard*[T](self: Module[T]) =
|
||||
self.delegate.syncWalletAccountsOnLoginForReplacedKeycard()
|
||||
|
||||
method checkForStoringPasswordToKeychain*[T](self: Module[T]) =
|
||||
self.controller.checkForStoringPasswordToKeychain()
|
|
@ -42,6 +42,7 @@ OnboardingBasePage {
|
|||
case Constants.startupState.userProfileImportSeedPhrase:
|
||||
case Constants.startupState.profileFetchingAnnouncement:
|
||||
case Constants.startupState.userProfileCreateSameChatKey:
|
||||
case Constants.startupState.lostKeycardOptions:
|
||||
return keysMainViewComponent
|
||||
|
||||
case Constants.startupState.userProfileCreate:
|
||||
|
|
|
@ -238,24 +238,51 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Row {
|
||||
id: button3
|
||||
|
||||
property string text: ""
|
||||
property string link: ""
|
||||
property bool useLinkForButton: false
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: text !== ""
|
||||
color: Theme.palette.primaryColor1
|
||||
font.pixelSize: Constants.onboarding.fontSize3
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
parent.font.underline = true
|
||||
}
|
||||
onExited: {
|
||||
parent.font.underline = false
|
||||
visible: button3.text !== ""
|
||||
spacing: 0
|
||||
padding: 0
|
||||
|
||||
StatusBaseText {
|
||||
text: button3.text
|
||||
color: Theme.palette.primaryColor1
|
||||
font.pixelSize: Constants.onboarding.fontSize3
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
parent.font.underline = true
|
||||
}
|
||||
onExited: {
|
||||
parent.font.underline = false
|
||||
}
|
||||
onClicked: {
|
||||
if (button3.useLinkForButton) {
|
||||
Qt.openUrlExternally(button3.link)
|
||||
return
|
||||
}
|
||||
root.startupStore.doTertiaryAction()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusFlatRoundButton {
|
||||
visible: button3.link !== ""
|
||||
height: 20
|
||||
width: 20
|
||||
icon.name: "external"
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
onClicked: {
|
||||
root.startupStore.doTertiaryAction()
|
||||
Qt.openUrlExternally(button3.link)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -451,6 +478,39 @@ Item {
|
|||
target: button3
|
||||
text: ""
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: Constants.startupState.lostKeycardOptions
|
||||
when: root.startupStore.currentStartupState.stateType === Constants.startupState.lostKeycardOptions
|
||||
PropertyChanges {
|
||||
target: keysImg
|
||||
Layout.preferredWidth: Constants.keycard.general.imageWidth
|
||||
Layout.preferredHeight: Constants.keycard.general.imageHeight
|
||||
source: Style.png("keycard/keycard-new")
|
||||
}
|
||||
PropertyChanges {
|
||||
target: txtTitle
|
||||
text: ""
|
||||
}
|
||||
PropertyChanges {
|
||||
target: txtDesc
|
||||
text: qsTr("Sorry to hear you’ve lost your Keycard, you have 3 options")
|
||||
height: Constants.onboarding.loginInfoHeight2
|
||||
}
|
||||
PropertyChanges {
|
||||
target: button1
|
||||
text: qsTr("Create replacement Keycard with seed phrase")
|
||||
}
|
||||
PropertyChanges {
|
||||
target: button2
|
||||
text: qsTr("Start using account without keycard")
|
||||
}
|
||||
PropertyChanges {
|
||||
target: button3
|
||||
text: qsTr("Order new keycard")
|
||||
link: "https://get.keycard.tech"
|
||||
useLinkForButton: true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -64,6 +64,8 @@ Item {
|
|||
readonly property string stateLoginRegularUser: "regularUserLogin"
|
||||
readonly property string stateLoginKeycardUser: "keycardUserLogin"
|
||||
|
||||
readonly property string lostKeycardItemKey: Constants.appTranslatableConstants.loginAccountsListLostKeycard
|
||||
|
||||
property int remainingAttempts: root.startupStore.startupModuleInst.remainingAttempts
|
||||
onRemainingAttemptsChanged: {
|
||||
pinInputField.statesInitialization()
|
||||
|
@ -280,11 +282,22 @@ Item {
|
|||
roleName: "order"
|
||||
sortOrder: Qt.AscendingOrder
|
||||
}
|
||||
filters: ValueFilter {
|
||||
roleName: "keyUid"
|
||||
value: root.startupStore.selectedLoginAccount.keyUid
|
||||
inverted: true
|
||||
}
|
||||
filters: [
|
||||
ExpressionFilter {
|
||||
expression: {
|
||||
if (!root.startupStore.selectedLoginAccount.keycardCreatedAccount &&
|
||||
model.username === d.lostKeycardItemKey) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
},
|
||||
ValueFilter {
|
||||
roleName: "keyUid"
|
||||
value: root.startupStore.selectedLoginAccount.keyUid
|
||||
inverted: true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
onAboutToShow: {
|
||||
|
@ -305,7 +318,8 @@ Item {
|
|||
}
|
||||
label: {
|
||||
if (model.username === Constants.appTranslatableConstants.loginAccountsListAddNewUser ||
|
||||
model.username === Constants.appTranslatableConstants.loginAccountsListAddExistingUser) {
|
||||
model.username === Constants.appTranslatableConstants.loginAccountsListAddExistingUser ||
|
||||
model.username === Constants.appTranslatableConstants.loginAccountsListLostKeycard) {
|
||||
return Constants.appTranslationMap[model.username]
|
||||
}
|
||||
return model.username
|
||||
|
@ -324,6 +338,10 @@ Item {
|
|||
accountsPopup.close()
|
||||
root.startupStore.doQuaternaryAction()
|
||||
}
|
||||
else if (model.username === Constants.appTranslatableConstants.loginAccountsListLostKeycard) {
|
||||
accountsPopup.close()
|
||||
root.startupStore.doQuinaryAction()
|
||||
}
|
||||
else {
|
||||
d.resetLogin()
|
||||
accountsPopup.close()
|
||||
|
|
|
@ -30,6 +30,21 @@ Item {
|
|||
id: timer
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
property bool wrongSeedPhrase: root.startupStore.startupModuleInst.keycardData & Constants.predefinedKeycardData.wrongSeedPhrase
|
||||
|
||||
onWrongSeedPhraseChanged: {
|
||||
if (wrongSeedPhrase) {
|
||||
invalidSeedTxt.text = qsTr("Seed phrase doesn’t match the profile of an existing Keycard user on this device")
|
||||
}
|
||||
else {
|
||||
invalidSeedTxt.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function pasteWords () {
|
||||
const clipboardText = globalUtils.getFromClipboard()
|
||||
// Split words separated by commas and or blank spaces (spaces, enters, tabs)
|
||||
|
@ -200,7 +215,7 @@ Item {
|
|||
property int itemIndex: index
|
||||
z: (grid.currentIndex === index) ? 150000000 : 0
|
||||
onTextChanged: {
|
||||
invalidSeedTxt.visible = false
|
||||
invalidSeedTxt.text = ""
|
||||
}
|
||||
onDoneInsertingWord: {
|
||||
grid.addWord(mnemonicIndex, word)
|
||||
|
@ -272,8 +287,7 @@ Item {
|
|||
anchors.top: grid.bottom
|
||||
anchors.topMargin: 24
|
||||
color: Theme.palette.dangerColor1
|
||||
visible: false
|
||||
text: qsTr("Invalid seed")
|
||||
visible: text !== ""
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
|
@ -297,7 +311,8 @@ Item {
|
|||
root.startupStore.currentStartupState.flowType === Constants.startupFlow.appLogin) {
|
||||
return qsTr("Recover Keycard")
|
||||
}
|
||||
else if (root.startupStore.currentStartupState.flowType === Constants.startupFlow.firstRunNewUserImportSeedPhraseIntoKeycard) {
|
||||
else if (root.startupStore.currentStartupState.flowType === Constants.startupFlow.firstRunNewUserImportSeedPhraseIntoKeycard ||
|
||||
root.startupStore.currentStartupState.flowType === Constants.startupFlow.lostKeycardReplacement) {
|
||||
return qsTr("Next")
|
||||
}
|
||||
return ""
|
||||
|
@ -313,7 +328,7 @@ Item {
|
|||
root.mnemonicInput = []
|
||||
root.startupStore.doPrimaryAction()
|
||||
} else {
|
||||
invalidSeedTxt.visible = true
|
||||
invalidSeedTxt.text = qsTr("Invalid seed")
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,11 +34,11 @@ ColumnLayout {
|
|||
Image {
|
||||
visible: d.noKeycardsSet
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.preferredHeight: sourceSize.height
|
||||
Layout.preferredWidth: sourceSize.width
|
||||
Layout.preferredHeight: 240
|
||||
Layout.preferredWidth: 350
|
||||
fillMode: Image.PreserveAspectFit
|
||||
antialiasing: true
|
||||
source: Style.png("keycard/security-keycard@2x")
|
||||
source: Style.png("keycard/keycard-security")
|
||||
mipmap: true
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 81 KiB |
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
|
@ -23,6 +23,7 @@ QtObject {
|
|||
readonly property string firstRunOldUserKeycardImport: "FirstRunOldUserKeycardImport"
|
||||
readonly property string firstRunOldUserImportSeedPhrase: "FirstRunOldUserImportSeedPhrase"
|
||||
readonly property string appLogin: "AppLogin"
|
||||
readonly property string lostKeycardReplacement: "LostKeycardReplacement"
|
||||
}
|
||||
|
||||
readonly property QtObject startupState: QtObject {
|
||||
|
@ -83,6 +84,7 @@ QtObject {
|
|||
readonly property string profileFetchingSuccess: "ProfileFetchingSuccess"
|
||||
readonly property string profileFetchingTimeout: "ProfileFetchingTimeout"
|
||||
readonly property string profileFetchingAnnouncement: "ProfileFetchingAnnouncement"
|
||||
readonly property string lostKeycardOptions: "LostKeycardOptions"
|
||||
}
|
||||
|
||||
readonly property QtObject predefinedKeycardData: QtObject {
|
||||
|
@ -781,11 +783,13 @@ QtObject {
|
|||
readonly property QtObject appTranslatableConstants: QtObject {
|
||||
readonly property string loginAccountsListAddNewUser: "LOGIN-ACCOUNTS-LIST-ADD-NEW-USER"
|
||||
readonly property string loginAccountsListAddExistingUser: "LOGIN-ACCOUNTS-LIST-ADD-EXISTING-USER"
|
||||
readonly property string loginAccountsListLostKeycard: "LOGIN-ACCOUNTS-LIST-LOST-KEYCARD"
|
||||
}
|
||||
|
||||
readonly property var appTranslationMap: ({})
|
||||
Component.onCompleted: {
|
||||
appTranslationMap[appTranslatableConstants.loginAccountsListAddNewUser] = qsTr("Add new user")
|
||||
appTranslationMap[appTranslatableConstants.loginAccountsListAddExistingUser] = qsTr("Add existing Status user")
|
||||
appTranslationMap[appTranslatableConstants.loginAccountsListLostKeycard] = qsTr("Lost Keycard")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue