Skip to content

Commit

Permalink
feature(@desktop/keycard): create a new Keycard account with a new se…
Browse files Browse the repository at this point in the history
…ed phrase

Fixes: #7028
  • Loading branch information
saledjenic committed Jan 4, 2023
1 parent 735f6e7 commit 0e65f2a
Show file tree
Hide file tree
Showing 87 changed files with 1,778 additions and 868 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ method onSharedKeycarModuleFlowTerminated*(self: AccessInterface, lastStepInTheC
method runSetupKeycardPopup*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")

method runGenerateSeedPhrasePopup*(self: AccessInterface) {.base.} =
method runCreateNewKeycardWithNewSeedPhrasePopup*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")

method runImportOrRestoreViaSeedPhrasePopup*(self: AccessInterface) {.base.} =
Expand Down
23 changes: 12 additions & 11 deletions src/app/modules/main/profile_section/keycard/module.nim
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,11 @@ method runSetupKeycardPopup*(self: Module) =
return
self.keycardSharedModule.runFlow(keycard_shared_module.FlowType.SetupNewKeycard)

method runGenerateSeedPhrasePopup*(self: Module) =
info "TODO: Generate a seed phrase..."
method runCreateNewKeycardWithNewSeedPhrasePopup*(self: Module) =
self.createSharedKeycardModule()
if self.keycardSharedModule.isNil:
return
self.keycardSharedModule.runFlow(keycard_shared_module.FlowType.SetupNewKeycardNewSeedPhrase)

method runImportOrRestoreViaSeedPhrasePopup*(self: Module) =
info "TODO: Import or restore via a seed phrase..."
Expand Down Expand Up @@ -158,8 +161,6 @@ method runCreateBackupCopyOfAKeycardPopup*(self: Module, keyUid: string) =
self.createSharedKeycardModule()
if self.keycardSharedModule.isNil:
return
let item = self.view.keycardModel().getItemForKeyUid(keyUid)
self.keycardSharedModule.setKeyPairForCopy(item)
self.keycardSharedModule.runFlow(keycard_shared_module.FlowType.CreateCopyOfAKeycard, keyUid)

method runCreatePukPopup*(self: Module, keyUid: string) =
Expand Down Expand Up @@ -204,25 +205,25 @@ proc buildKeycardItem(self: Module, walletAccounts: seq[WalletAccountDto], keyPa
if knownAccounts.len == 0:
return nil
var item = initKeycardItem(keycardUid = keyPair.keycardUid,
pubKey = knownAccounts[0].publicKey,
keyUid = keyPair.keyUid,
pubKey = knownAccounts[0].publicKey,
locked = keyPair.keycardLocked,
name = keyPair.keycardName,
derivedFrom = knownAccounts[0].derivedfrom)
for ka in knownAccounts:
var icon = ""
if ka.walletType == WalletTypeDefaultStatusAccount:
item.setPairType(KeyPairType.Profile)
item.setPairType(KeyPairType.Profile.int)
item.setPubKey(singletonInstance.userProfile.getPubKey())
item.setImage(singletonInstance.userProfile.getIcon())
icon = "wallet"
if ka.walletType == WalletTypeSeed:
item.setPairType(KeyPairType.SeedImport)
item.setPairType(KeyPairType.SeedImport.int)
item.setIcon("keycard")
if ka.walletType == WalletTypeKey:
item.setPairType(KeyPairType.PrivateKeyImport)
item.setPairType(KeyPairType.PrivateKeyImport.int)
item.setIcon("keycard")
item.addAccount(ka.name, ka.path, ka.address, ka.emoji, ka.color, icon = icon, balance = 0.0)
item.addAccount(newKeyPairAccountItem(ka.name, ka.path, ka.address, ka.publicKey, ka.emoji, ka.color, icon = icon, balance = 0.0))
return item

proc areAllKnownKeycardsLockedForKeypair(self: Module, keyUid: string): bool =
Expand All @@ -241,7 +242,7 @@ proc buildKeycardList(self: Module) =
if item.isNil:
continue
## If all created keycards for certain keypair are locked, then we need to display that item as locked.
item.setLocked(self.areAllKnownKeycardsLockedForKeypair(item.keyUid()))
item.setLocked(self.areAllKnownKeycardsLockedForKeypair(item.getKeyUid()))
items.add(item)
self.view.setKeycardItems(items)

Expand Down Expand Up @@ -297,4 +298,4 @@ method prepareKeycardDetailsModel*(self: Module, keyUid: string) =
if item.isNil:
continue
items.add(item)
self.view.createModelAndSetKeycardDetailsItems(items)
self.view.createModelAndSetKeycardDetailsItems(items)
6 changes: 3 additions & 3 deletions src/app/modules/main/profile_section/keycard/view.nim
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ QtObject:
proc runSetupKeycardPopup*(self: View) {.slot.} =
self.delegate.runSetupKeycardPopup()

proc runGenerateSeedPhrasePopup*(self: View) {.slot.} =
self.delegate.runGenerateSeedPhrasePopup()
proc runCreateNewKeycardWithNewSeedPhrasePopup*(self: View) {.slot.} =
self.delegate.runCreateNewKeycardWithNewSeedPhrasePopup()

proc runImportOrRestoreViaSeedPhrasePopup*(self: View) {.slot.} =
self.delegate.runImportOrRestoreViaSeedPhrasePopup()
Expand Down Expand Up @@ -120,4 +120,4 @@ QtObject:
self.keycardDetailsModelChanged()

proc prepareKeycardDetailsModel*(self: View, keyUid: string) {.slot.} =
self.delegate.prepareKeycardDetailsModel(keyUid)
self.delegate.prepareKeycardDetailsModel(keyUid)
135 changes: 81 additions & 54 deletions src/app/modules/shared_modules/keycard_popup/controller.nim
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import ../../../../app_service/service/accounts/service as accounts_service
import ../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../app_service/service/keychain/service as keychain_service

import models/[key_pair_item]

logScope:
topics = "keycard-popup-controller"

Expand All @@ -32,14 +34,12 @@ type
connectionKeycardResponse: UUID
tmpKeycardContainsMetadata: bool
tmpCardMetadata: CardMetadata
tmpKeyUidForProcessing: string
tmpPin: string
tmpPinMatch: bool
tmpPuk: string
tmpPukMatch: bool
tmpValidPuk: bool
tmpPassword: string
tmpKeycardName: string
tmpPairingCode: string
tmpSelectedKeyPairIsProfile: bool
tmpSelectedKeyPairDto: KeyPairDto
Expand Down Expand Up @@ -139,23 +139,25 @@ proc delete*(self: Controller) =
proc init*(self: Controller) =
self.connectKeycardReponseSignal()

let handlerId = self.events.onWithUUID(SIGNAL_SHARED_KEYCARD_MODULE_USER_AUTHENTICATED) do(e: Args):
var handlerId = self.events.onWithUUID(SIGNAL_SHARED_KEYCARD_MODULE_USER_AUTHENTICATED) do(e: Args):
let args = SharedKeycarModuleArgs(e)
if args.uniqueIdentifier != self.uniqueIdentifier:
return
self.connectKeycardReponseSignal()
self.delegate.onUserAuthenticated(args.password, args.pin)
self.connectionIds.add(handlerId)

self.events.on(SIGNAL_NEW_KEYCARD_SET) do(e: Args):
handlerId = self.events.onWithUUID(SIGNAL_NEW_KEYCARD_SET) do(e: Args):
let args = KeycardActivityArgs(e)
self.tmpAddingMigratedKeypairSuccess = args.success
self.delegate.onSecondaryActionClicked()
self.connectionIds.add(handlerId)

self.events.on(SIGNAL_CONVERTING_PROFILE_KEYPAIR) do(e: Args):
handlerId = self.events.onWithUUID(SIGNAL_CONVERTING_PROFILE_KEYPAIR) do(e: Args):
let args = ResultArgs(e)
self.tmpConvertingProfileSuccess = args.success
self.delegate.onSecondaryActionClicked()
self.connectionIds.add(handlerId)

proc getKeycardData*(self: Controller): string =
return self.delegate.getKeycardData()
Expand All @@ -172,11 +174,11 @@ proc containsMetadata*(self: Controller): bool =
proc setContainsMetadata*(self: Controller, value: bool) =
self.tmpKeycardContainsMetadata = value

proc getKeyUidWhichNeedToBeProcessed*(self: Controller): string =
self.tmpKeyUidForProcessing
proc setKeyPairForProcessing*(self: Controller, item: KeyPairItem) =
self.delegate.setKeyPairForProcessing(item)

proc setKeyUidWhichNeedToBeProcessed*(self: Controller, keyUid: string) =
self.tmpKeyUidForProcessing = keyUid
proc getKeyPairForProcessing*(self: Controller): KeyPairItem =
return self.delegate.getKeyPairForProcessing()

proc setPin*(self: Controller, value: string) =
self.tmpPin = value
Expand Down Expand Up @@ -226,12 +228,6 @@ proc setPassword*(self: Controller, value: string) =
proc getPassword*(self: Controller): string =
return self.tmpPassword

proc setKeycardName*(self: Controller, value: string) =
self.tmpKeycardName = value

proc getKeycardName*(self: Controller): string =
return self.tmpKeycardName

proc setPairingCode*(self: Controller, value: string) =
self.tmpPairingCode = value

Expand All @@ -241,18 +237,30 @@ proc getPairingCode*(self: Controller): string =
proc getKeyUidWhichIsBeingAuthenticating*(self: Controller): string =
self.tmpKeyUidWhichIsBeingAuthenticating

proc setSelectedKeyPairIsProfile*(self: Controller, value: bool) =
self.tmpSelectedKeyPairIsProfile = value
proc setSelectedKeyPair*(self: Controller, isProfile: bool, paths: seq[string], keyPairDto: KeyPairDto) =
if paths.len != keyPairDto.accountsAddresses.len:
error "selected keypair has different number of paths and addresses"
return
self.tmpSelectedKeyPairIsProfile = isProfile
self.tmpSelectedKeyPairWalletPaths = paths
self.tmpSelectedKeyPairDto = keyPairDto

proc getSelectedKeyPairIsProfile*(self: Controller): bool =
return self.tmpSelectedKeyPairIsProfile

proc setSelectedKeyPairDto*(self: Controller, keyPairDto: KeyPairDto) =
self.tmpSelectedKeyPairDto = keyPairDto

proc getSelectedKeyPairDto*(self: Controller): KeyPairDto =
return self.tmpSelectedKeyPairDto

proc getSelectedKeyPairWalletPaths*(self: Controller): seq[string] =
return self.tmpSelectedKeyPairWalletPaths

proc setSelectedKeypairAsKeyPairForProcessing*(self: Controller) =
var cardMetadata = CardMetadata(name: self.tmpSelectedKeyPairDto.keycardName)
for i in 0 ..< self.tmpSelectedKeyPairWalletPaths.len:
cardMetadata.walletAccounts.add(WalletAccount(path: self.tmpSelectedKeyPairWalletPaths[i],
address: self.tmpSelectedKeyPairDto.accountsAddresses[i]))
self.delegate.updateKeyPairForProcessing(cardMetadata)

proc setKeycardUidTheSelectedKeypairIsMigratedTo*(self: Controller, value: string) =
self.tmpSelectedKeyPairDto.keycardUid = value

Expand All @@ -268,12 +276,6 @@ proc setDestinationKeycardUid*(self: Controller, value: string) =
proc getDestinationKeycardUid*(self: Controller): string =
return self.tmpKeycardCopyDestinationKeycardUid

proc setSelectedKeyPairWalletPaths*(self: Controller, paths: seq[string]) =
self.tmpSelectedKeyPairWalletPaths = paths

proc getSelectedKeyPairWalletPaths*(self: Controller): seq[string] =
return self.tmpSelectedKeyPairWalletPaths

proc setSeedPhrase*(self: Controller, value: string) =
let words = value.split(" ")
self.tmpSeedPhrase = value
Expand All @@ -297,17 +299,18 @@ proc getKeyUidForSeedPhrase*(self: Controller, seedPhrase: string): string =
let acc = self.accountsService.createAccountFromMnemonic(seedPhrase)
return acc.keyUid

proc seedPhraseRefersToSelectedKeyPair*(self: Controller, seedPhrase: string): bool =
proc generateAccountsFromSeedPhrase*(self: Controller, seedPhrase: string, paths: seq[string]): GeneratedAccountDto =
if not serviceApplicable(self.accountsService):
return
let acc = self.accountsService.createAccountFromMnemonic(seedPhrase)
return acc.keyUid == self.tmpSelectedKeyPairDto.keyUid
return self.accountsService.createAccountFromMnemonic(seedPhrase, paths)

proc seedPhraseRefersToKeyPairBeingProcessed*(self: Controller, seedPhrase: string): bool =
if not serviceApplicable(self.accountsService):
proc buildSeedPhrasesFromIndexes*(self: Controller, seedPhraseIndexes: seq[int]) =
if seedPhraseIndexes.len == 0:
let err = "cannot generate seed phrase from empty array"
error "keycard error: ", err
return
let acc = self.accountsService.createAccountFromMnemonic(seedPhrase)
return acc.keyUid == self.tmpKeyUidForProcessing
let sp = self.keycardService.buildSeedPhrasesFromIndexes(seedPhraseIndexes)
self.setSeedPhrase(sp.join(" "))

proc verifyPassword*(self: Controller, password: string): bool =
if not serviceApplicable(self.accountsService):
Expand Down Expand Up @@ -344,28 +347,23 @@ proc getLastReceivedKeycardData*(self: Controller): tuple[flowType: string, flow
proc getMetadataFromKeycard*(self: Controller): CardMetadata =
return self.tmpCardMetadata

proc setMetadataFromKeycard*(self: Controller, cardMetadata: CardMetadata, updateKeyPair = false) =
proc setMetadataFromKeycard*(self: Controller, cardMetadata: CardMetadata) =
self.tmpCardMetadata = cardMetadata
if updateKeyPair:
self.delegate.setKeyPairStoredOnKeycard(cardMetadata)
self.delegate.updateKeyPairForProcessing(cardMetadata)

proc getMetadataForKeycardCopy*(self: Controller): CardMetadata =
return self.tmpKeycardCopyCardMetadata

proc setMetadataForKeycardCopy*(self: Controller, cardMetadata: CardMetadata, updateKeyPair = false) =
proc setMetadataForKeycardCopy*(self: Controller, cardMetadata: CardMetadata) =
self.tmpKeycardCopyCardMetadata = cardMetadata
if updateKeyPair:
self.delegate.setKeyPairStoredOnKeycard(cardMetadata)
self.setMetadataFromKeycard(cardMetadata)

proc setPinForKeycardCopy*(self: Controller, value: string) =
self.tmpKeycardCopyPin = value

proc getPinForKeycardCopy*(self: Controller): string =
return self.tmpKeycardCopyPin

proc setNamePropForKeyPairStoredOnKeycard*(self: Controller, name: string) =
self.delegate.setNamePropForKeyPairStoredOnKeycard(name)

proc notifyAboutGeneratedWalletAccount*(self: Controller, generatedWalletAccount: GeneratedWalletAccount, derivedFrom: string) =
let data = SharedKeycarModuleUserAuthenticatedAndWalletAddressGeneratedArgs(uniqueIdentifier: self.uniqueIdentifier,
address: generatedWalletAccount.address,
Expand All @@ -375,8 +373,8 @@ proc notifyAboutGeneratedWalletAccount*(self: Controller, generatedWalletAccount
)
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_USER_AUTHENTICATED_AND_WALLET_ADDRESS_GENERATED, data)

proc runSharedModuleFlow*(self: Controller, flowToRun: FlowType) =
self.delegate.runFlow(flowToRun)
proc runSharedModuleFlow*(self: Controller, flowToRun: FlowType, keyUid = "") =
self.delegate.runFlow(flowToRun, keyUid)

proc cancelCurrentFlow*(self: Controller) =
if not serviceApplicable(self.keycardService):
Expand Down Expand Up @@ -466,6 +464,28 @@ proc readyToDisplayPopup*(self: Controller) =
let data = SharedKeycarModuleBaseArgs(uniqueIdentifier: self.uniqueIdentifier)
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_DISPLAY_POPUP, data)

proc cleanTmpData(self: Controller) =
self.tmpKeyUidWhichIsBeingAuthenticating = ""
self.tmpAddingMigratedKeypairSuccess = false
self.tmpConvertingProfileSuccess = false
self.tmpCardMetadata = CardMetadata()
self.tmpKeycardCopyCardMetadata = CardMetadata()
self.setContainsMetadata(false)
self.setPin("")
self.setPinMatch(false)
self.setPuk("")
self.setPukMatch(false)
self.setPukValid(false)
self.setPassword("")
self.setPairingCode("")
self.setSelectedKeyPair(isProfile = false, paths = @[], KeyPairDto())
self.setSeedPhrase("")
self.setUsePinFromBiometrics(false)
self.setOfferToStoreUpdatedPinToKeychain(false)
self.setKeycardUid("")
self.setPinForKeycardCopy("")
self.setDestinationKeycardUid("")

proc terminateCurrentFlow*(self: Controller, lastStepInTheCurrentFlow: bool) =
self.cancelCurrentFlow()
let (_, flowEvent) = self.getLastReceivedKeycardData()
Expand All @@ -476,6 +496,7 @@ proc terminateCurrentFlow*(self: Controller, lastStepInTheCurrentFlow: bool) =
data.password = if exportedEncryptionPubKey.len > 0: exportedEncryptionPubKey else: self.getPassword()
data.pin = self.getPin()
data.keyUid = flowEvent.keyUid
self.cleanTmpData()
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_FLOW_TERMINATED, data)

proc authenticateUser*(self: Controller, keyUid = "") =
Expand Down Expand Up @@ -510,10 +531,10 @@ proc getAllMigratedKeyPairs*(self: Controller): seq[KeyPairDto] =
return
return self.walletAccountService.getAllMigratedKeyPairs()

proc getMigratedKeyPairByKeyUid*(self: Controller, keyUid: string): seq[KeyPairDto] =
proc getAllKnownKeycards*(self: Controller): seq[KeyPairDto] =
if not serviceApplicable(self.walletAccountService):
return
return self.walletAccountService.getMigratedKeyPairByKeyUid(keyUid)
return self.walletAccountService.getAllKnownKeycards()

proc setCurrentKeycardStateToLocked*(self: Controller, keycardUid: string) =
if not serviceApplicable(self.walletAccountService):
Expand Down Expand Up @@ -544,6 +565,17 @@ proc updateKeycardUid*(self: Controller, keycardUid: string) =
self.tmpKeycardUid = keycardUid
info "update keycard uid failed", oldKeycardUid=self.tmpKeycardUid, newKeycardUid=keycardUid

proc addWalletAccount*(self: Controller, name, address, path, addressAccountIsDerivedFrom, publicKey, keyUid, accountType,
color, emoji: string): bool =
if not serviceApplicable(self.walletAccountService):
return false
let err = self.walletAccountService.addWalletAccount(name, address, path, addressAccountIsDerivedFrom, publicKey, keyUid,
accountType, color, emoji)
if err.len > 0:
info "adding wallet account failed", name=name, path=path
return false
return true

proc getSigningPhrase*(self: Controller): string =
if not serviceApplicable(self.settingsService):
return
Expand Down Expand Up @@ -584,26 +616,21 @@ proc generateRandomPUK*(self: Controller): string =
return
return self.keycardService.generateRandomPUK()

proc isMnemonicBackedUp*(self: Controller): bool =
proc isProfileMnemonicBackedUp*(self: Controller): bool =
if not serviceApplicable(self.privacyService):
return
return self.privacyService.isMnemonicBackedUp()

proc getMnemonic*(self: Controller): string =
proc getProfileMnemonic*(self: Controller): string =
if not serviceApplicable(self.privacyService):
return
return self.privacyService.getMnemonic()

proc removeMnemonic*(self: Controller) =
proc removeProfileMnemonic*(self: Controller) =
if not serviceApplicable(self.privacyService):
return
self.privacyService.removeMnemonic()

proc getMnemonicWordAtIndex*(self: Controller, index: int): string =
if not serviceApplicable(self.privacyService):
return
return self.privacyService.getMnemonicWordAtIndex(index)

proc tryToObtainDataFromKeychain*(self: Controller) =
if not serviceApplicable(self.keychainService):
return
Expand Down
Loading

0 comments on commit 0e65f2a

Please sign in to comment.